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_fieldbin/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 componentActive 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:trilogyDatabase 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)
endParallelization 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:isolatedIsolated 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
# ...
endUnderscore*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 = oldAssertion preferences
assert_not conditionoverassert !condition(enforced by RuboCop'sRails/AssertNotcop).assert_dom_equalfor HTML comparison in view tests (lives inactionview/lib/action_view/test_case.rb).assert_changesandassert_no_changesfor state changes.- Use
freeze_timefromActiveSupport::Testing::TimeHelpersinstead ofTimecop(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 withassert_dom_equal.ActionMailer::TestCaseandActionMailer::TestHelper— mailer assertions and inbox introspection.ActiveJob::TestCaseandActiveJob::TestHelper—assert_enqueued_with,perform_enqueued_jobs, etc. (activejob/lib/active_job/test_helper.rb).ActionCable::TestCaseandActionCable::Channel::TestCase(actioncable/lib/action_cable/channel/test_case.rb).ActiveStorage::FixtureSetfor blob/attachment fixtures.
CI reference
CI workflows live in .github/workflows/. The main jobs are:
release.yml— orchestrates tagged releases via the in-repotools/releaser/gem.rail_inspector.yml— sanity check on the docs.rails_releaser_tests.yml— tests the releaser itself.devcontainer-shellcheck.ymlanddevcontainer-smoke-test.yml— verify the dev container setup.rails-new-docker.yml— exercisesrails newagainst 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.