From cb907866304d62921ff999a61be90af78d46acf8 Mon Sep 17 00:00:00 2001 From: Paul Keen <125715+pftg@users.noreply.github.com> Date: Mon, 24 Aug 2026 16:34:41 +0200 Subject: [PATCH 1/2] test: Rails' missing-assertions alarm is 7.2+, so skip it on 7.1 ActiveSupport::Testing::TestsWithoutAssertions does not exist in Rails 7.1, so the rails71 matrix cell died with NameError at class-definition time -- eight errors, on master, from a test added for #270. Skip rather than stub. A hand-rolled stand-in would assert that our code cooperates with a module Rails never prepends on that version, which proves nothing and reads as coverage. Guarded on rather than a version comparison: the question is whether the constant is there to prepend, and edge/main moves independently of the version string. Verified both ways -- constant forced absent: 3 skips; present: 0 skips, 15 assertions. --- test/unit/minitest_assertions_test.rb | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/test/unit/minitest_assertions_test.rb b/test/unit/minitest_assertions_test.rb index 29011696..336b2527 100644 --- a/test/unit/minitest_assertions_test.rb +++ b/test/unit/minitest_assertions_test.rb @@ -7,16 +7,30 @@ class MinitestAssertionsTest < ActiveSupport::TestCase # inspect how before_teardown resolved (passed/skipped/failed) without polluting # the outer test's own assertions/reporting. # + # Rails 7.2+ only. `defined?` rather than a version comparison: the + # question is whether the constant is there to prepend, and edge/main can + # move independently of the version string. + RAILS_HAS_ASSERTION_ALARM = defined?(ActiveSupport::Testing::TestsWithoutAssertions) + # @param teardown [Proc, nil] optional replacement `teardown` method, to # simulate a user teardown that runs after `before_teardown`. Calls # `super()` first so DSLStub's own cleanup still happens. # @param like_rails [Boolean] prepend the module Rails prepends into every # ActiveSupport::TestCase, to observe its missing-assertions alarm. def run_inner_test(teardown: nil, like_rails: false, &block) + # Without the module there is no alarm to observe, and running anyway would + # assert that a thing which cannot fire did not fire -- green for the wrong + # reason, which is the failure mode this whole release exists to remove. + skip "ActiveSupport::Testing::TestsWithoutAssertions is Rails 7.2+" if like_rails && !RAILS_HAS_ASSERTION_ALARM + test_class = Class.new(::Minitest::Test) do # The real thing, not a stand-in: Rails prepends exactly this, - # unconditionally, at active_support/test_case.rb:205. - prepend ActiveSupport::Testing::TestsWithoutAssertions if like_rails + # unconditionally, at active_support/test_case.rb:205 -- but only since + # Rails 7.2. On 7.1 the constant does not exist, so the alarm this test + # observes is simply not a feature of that version. Skip rather than + # stub: a hand-rolled stand-in would assert that OUR code cooperates + # with a module Rails never prepends there, which proves nothing. + prepend ActiveSupport::Testing::TestsWithoutAssertions if like_rails && RAILS_HAS_ASSERTION_ALARM include SnapDiff::Minitest::Assertions include DSLStub From b57de9e366079174cfb37ff1e6236def258eea14 Mon Sep 17 00:00:00 2001 From: Paul Keen <125715+pftg@users.noreply.github.com> Date: Mon, 24 Aug 2026 17:25:05 +0200 Subject: [PATCH 2/2] test: skip the fork-parallel suite where Kernel#fork does not exist Every JRuby cell in the last 15 Test runs was `cancelled` -- 29 cancelled, 1 failure, zero successes. Fail-fast killed the lane before it could report, and `cancelled` reads as an absence rather than a verdict, so nothing said the lane had been dark since #266. Fixing the rails71 failure in the previous commit let JRuby run far enough to report, and it reported six errors: NotImplementedError: fork is not available on this platform org/jruby/RubyKernel.java:2073:in 'fork' test/unit/parallel_report_merge_test.rb:224:in 'fork_worker' All six route through `fork_worker`. This is not a product bug: Rails' `parallelize(workers: N)` forks, JRuby has no fork, and JRuby suites parallelize with threads instead -- which record in the process that finalizes and are already covered by "merging is a no-op when no worker ever forked". The behaviour is inapplicable there, so a skip is the honest report. Detection measured rather than assumed, on jruby-10.0.6.0: Process.respond_to?(:fork) => false Process.fork { } => NotImplementedError so the plain idiom is enough; no RUBY_PLATFORM sniffing. Verified both directions, because a guard that skips everywhere would be worse than the bug: MRI 4.0.6 14 runs, 68 assertions, 0 failures, 0 skips JRuby 10.0.6.0 14 runs, 34 assertions, 0 errors, 6 skips and the full unit suite on jruby-10.0.6.0 + rails72_gems.rb is 720 runs / 2090 assertions / 0 failures / 0 errors / 6 skips, so these six were the only thing broken in that lane. CI's own run of the superset (`bin/rake test`, 757 runs) failed on exactly these six and nothing else. --- test/unit/parallel_report_merge_test.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/unit/parallel_report_merge_test.rb b/test/unit/parallel_report_merge_test.rb index 14a7169a..e209e3b6 100644 --- a/test/unit/parallel_report_merge_test.rb +++ b/test/unit/parallel_report_merge_test.rb @@ -220,7 +220,16 @@ class ParallelReportMergeTest < ActiveSupport::TestCase # Runs the block in a real forked child, then the exact hook Rails runs # inside a parallel worker before it exits. + # + # JRuby has no `fork` (`Process.respond_to?(:fork)` is false, and calling it + # raises NotImplementedError), so Rails' fork-parallel mode -- the entire + # subject of this file -- cannot happen there. JRuby suites parallelize with + # threads, which record in the process that finalizes and are covered by + # "merging is a no-op when no worker ever forked" above. Skipping is the + # honest report: the behaviour is inapplicable, not untested. def fork_worker(&block) + skip "Rails' fork-parallel mode needs Kernel#fork, which #{RUBY_ENGINE} does not implement" unless Process.respond_to?(:fork) + pid = fork do block.call ActiveSupport::Testing::Parallelization.run_cleanup_hooks.each { |hook| hook.call(0) }