After upgrading Rails from 8.0.x to 8.1.x, running system tests like
CI=true bin/rails test:system
CI=true bin/rails test test/system/login_test.rb -vstarted reporting
0 runs, 0 assertions, 0 failures, 0 errors, 0 skips
even though the test/system/*_test.rb files existed and previously ran fine on Rails 8.0.3/8.0.4.
Between Rails 8.0.4 and 8.1.0, commit b1589fa7d9 ("Let minitest parse ARGV") changed how Rails loads tests:
- In Rails 8.0.x,
Rails::TestUnit::Runner.run(argv)directly calledload_tests(argv)and thenrequire "active_support/testing/autorun". Rails itself alwaysrequired the test files, independent of any Minitest plugins. - In Rails 8.1.x,
Runner.run(args)now only:- requires
active_support/testing/autorun(which wires upMinitest.autorun), - sets
@@load_test_files = true, and - registers an
at_exithook to restoreARGV.
- requires
The actual loading of test files was moved into the Rails Minitest plugin (minitest/rails_plugin.rb). That plugin:
- Parses CLI arguments into
options[:test_files]inplugin_rails_options, then - In a final
opts.onblock, ifRails::TestUnit::Runner.load_test_filesis true, callsRails::TestUnit::Runner.load_tests(options.fetch(:test_files, []))torequirethe tests.
At the same time, the environment included:
MT_NO_PLUGINS=1Minitest's run implementation short‑circuits plugin loading when this env var is set:
def self.run(args = [])
self.load_plugins unless args.delete("--no-plugins") || ENV["MT_NO_PLUGINS"]
...
endWith MT_NO_PLUGINS=1, Minitest.load_plugins never runs, so minitest/rails_plugin.rb is never required, and plugin_rails_options never executes. In Rails 8.1, that means:
Rails::TestUnit::Runner.load_test_filesis true, butRunner.load_testsis never called, so no_test.rbfiles are required, and- Minitest runs with zero runnables, reporting
0 runs.
This explains why the same environment worked on Rails 8.0.3/8.0.4 (where Runner.run eagerly called load_tests(argv) itself) but fails starting in 8.1.0 (which now depends on the plugin).
- The regression appears at Rails 8.1.0 and persists in 8.1.1.
- The behavior is not caused by Capybara, Playwright, or other app gems; it comes from the interaction between:
- Rails 8.1's new test‑loading behavior (
Rails::TestUnit::Runner.run+minitest/rails_plugin.rb), and - the global environment variable
MT_NO_PLUGINS=1.
- Rails 8.1's new test‑loading behavior (
- When
MT_NO_PLUGINS=1is set, the Rails plugin that loads tests is disabled, so no tests are required and the suite reports0 runs.
Practical fix for this app: ensure MT_NO_PLUGINS is unset (or empty) when running Rails tests, e.g.
unset MT_NO_PLUGINS
CI=true bin/rails test:system
# or for one-off runs
env -u MT_NO_PLUGINS CI=true bin/rails test test/system/login_test.rb -vIf we ever truly need to run without Minitest plugins, a separate override of Rails::TestUnit::Runner.run (restoring pre‑8.1 behavior by calling load_tests(args) directly) could be added, but for now the simplest and most consistent solution is to avoid exporting MT_NO_PLUGINS into Rails test runs.