Open-Source Wikis

/

Ruby on Rails

/

How to contribute

/

Testing

rails/rails

Testing

Everything you need to run, write, and debug tests in the Rails codebase.

Test framework

Rails uses Minitest, not RSpec. Test files always live in test/ (never spec/) and end with _test.rb.

Tests inherit from ActiveSupport::TestCase (defined in activesupport/lib/active_support/test_case.rb) which extends Minitest::Test with helpers like assert_difference, freeze_time, fixtures, and parallelization hooks.

Running tests

The recommended entry point is per-component:

cd actionview
bin/test                                            # all tests
bin/test test/template/form_helper_test.rb          # one file
bin/test test/template/form_helper_test.rb:42       # by line number
bin/test test/template/form_helper_test.rb -n "/hidden_field/"  # name filter
bin/test test/template/form_helper_test.rb::FormHelperTest#test_hidden_field

bin/test is a thin wrapper around tools/test.rb, which loads Rails::TestUnit::Runner (the same code that powers bin/rails test in applications).

From the repo root:

rake test               # All non-isolated tests
rake test:isolated      # Tests that need their own process
rake smoke              # Quick smoke test
rake actionview:test    # One component

Active Record adapter matrix

Active Record is the only component that runs against multiple adapters:

cd activerecord
bundle exec rake test:sqlite3         # default
bundle exec rake test:postgresql
bundle exec rake test:mysql2
bundle exec rake test:trilogy

Database connection details are read from activerecord/test/config.yml (copy config.example.yml as a starting point). The PostgreSQL and MySQL suites assume you have a running server with permissions to create databases.

CI runs every adapter; locally most contributors run sqlite3 first and only run the others when their patch touches adapter-shared code.

Parallel testing

Tests run in parallel using multiple processes. The implementation lives in activesupport/lib/active_support/testing/parallelization.rb and is configured by:

class ActiveSupport::TestCase
  parallelize(workers: :number_of_processors)
end

Parallelization uses fork on platforms that support it. Each worker gets its own database (Active Record manages this via parallelize_setup).

For tests that can't run in parallel (e.g., tests that mutate global state), use parallelize(workers: 1) or annotate the test with self.use_transactional_tests = false and isolate via tagged contexts.

Test isolation

Some tests need a fresh process — they patch global state, alter autoload paths, or boot a Rails application. They live in test/ directories alongside the rest but are tagged so the runner forks a child process per test:

rake test:isolated

Isolated tests are typically about boot, generators, or autoloading. See railties/test/isolation/abstract_unit.rb and activesupport/lib/active_support/testing/isolation.rb.

Writing tests

The codebase tends to follow a few conventions documented in AGENTS.md:

Use descriptive names

def test_hidden_field_omits_autocomplete_when_remove_hidden_field_autocomplete_is_true
  # ...
end

Underscore*case method names are fine. The test* prefix is required.

Configuration testing with Object#with

When testing how a configuration flag changes behavior, prefer Object#with over manual save/restore:

require "active_support/core_ext/object/with"

ActionView::Base.with(remove_hidden_field_autocomplete: true) do
  # test code
end

#with (defined in activesupport/lib/active_support/core_ext/object/with.rb) sets attributes for the block and restores them afterwards even when an exception is raised.

Avoid the pre-#with pattern:

# Don't do this
old = ActionView::Base.remove_hidden_field_autocomplete
ActionView::Base.remove_hidden_field_autocomplete = true
# ... test
ActionView::Base.remove_hidden_field_autocomplete = old

Assertion preferences

  • assert_not condition over assert !condition (enforced by RuboCop's Rails/AssertNot cop).
  • assert_dom_equal for HTML comparison in view tests (lives in actionview/lib/action_view/test_case.rb).
  • assert_changes and assert_no_changes for state changes.
  • Use freeze_time from ActiveSupport::Testing::TimeHelpers instead of Timecop (Timecop is not a dependency).

Test grouping

Tests for one feature or class go in one file. Group related tests in the same file rather than splitting by describe blocks (describe is not used in this codebase outside Action Mailer and Active Job tests).

Fixtures

Active Record fixtures live in activerecord/test/fixtures/. They are YAML files that the test runner loads into the test database. The format is documented in activerecord/lib/active_record/fixtures.rb.

Action Text and Active Storage have their own fixture sets in actiontext/lib/action_text/fixture_set.rb and activestorage/lib/active_storage/fixture_set.rb.

Useful test helpers per component

  • ActiveSupport::TestCase — base class, time helpers, error reporter assertions, notification assertions.
  • ActionController::TestCase — controller integration testing (actionpack/lib/action_controller/test_case.rb).
  • ActionDispatch::IntegrationTest — full-stack request testing.
  • ActionView::TestCase — view testing with assert_dom_equal.
  • ActionMailer::TestCase and ActionMailer::TestHelper — mailer assertions and inbox introspection.
  • ActiveJob::TestCase and ActiveJob::TestHelperassert_enqueued_with, perform_enqueued_jobs, etc. (activejob/lib/active_job/test_helper.rb).
  • ActionCable::TestCase and ActionCable::Channel::TestCase (actioncable/lib/action_cable/channel/test_case.rb).
  • ActiveStorage::FixtureSet for blob/attachment fixtures.

CI reference

CI workflows live in .github/workflows/. The main jobs are:

  • release.yml — orchestrates tagged releases via the in-repo tools/releaser/ gem.
  • rail_inspector.yml — sanity check on the docs.
  • rails_releaser_tests.yml — tests the releaser itself.
  • devcontainer-shellcheck.yml and devcontainer-smoke-test.yml — verify the dev container setup.
  • rails-new-docker.yml — exercises rails new against a Docker base image.

The full test matrix (Ruby versions x AR adapters x components) is run via Buildkite, configured outside this repo.

For style enforcement, see tooling.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Testing – Ruby on Rails wiki | Factory