From 5886caa127339046cedef67713ef990a7eb7710c Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 16 Apr 2026 13:15:31 +0900 Subject: [PATCH 1/2] Preserve ENV["TESTOPTS"] when verbose is enabled Rake 13.4.0 made `FileUtilsExt.verbose(true)` set `ENV["TESTOPTS"] = "-v"` unconditionally so that `rake -v test` would propagate verbosity to the test runner. The unconditional assignment also overwrote values set by other tools such as `ci_reporter_minitest`, breaking any workflow that relied on `TESTOPTS` being populated before `TestTask` ran. Move the `-v` injection out of `FileUtilsExt.verbose` and into `Rake::TestTask#option_list`. The task block now computes an effective verbose flag from `@verbose` or the global `FileUtilsExt.verbose_flag`, passes it to `option_list(verbose:)`, and the option list appends `-v` to the existing `TESTOPTS` only when it is not already present. This keeps the PR #394 behavior for `rake -v` and `t.verbose = true` while no longer clobbering pre-set `TESTOPTS` values. Fixes #722. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/rake/file_utils_ext.rb | 2 +- lib/rake/testtask.rb | 15 ++++++++++----- test/test_rake_file_utils.rb | 4 ---- test/test_rake_test_task.rb | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/lib/rake/file_utils_ext.rb b/lib/rake/file_utils_ext.rb index 7860b65ee..58d1c2113 100644 --- a/lib/rake/file_utils_ext.rb +++ b/lib/rake/file_utils_ext.rb @@ -53,7 +53,7 @@ def #{name}(*args, **options, &block) def verbose(value=nil) oldvalue = FileUtilsExt.verbose_flag FileUtilsExt.verbose_flag = value unless value.nil? - ENV["TESTOPTS"] = "-v" if value + if block_given? begin yield diff --git a/lib/rake/testtask.rb b/lib/rake/testtask.rb index cc66af845..b1737cd7e 100644 --- a/lib/rake/testtask.rb +++ b/lib/rake/testtask.rb @@ -108,10 +108,11 @@ def initialize(name=:test) def define desc @description task @name => Array(deps) do - FileUtilsExt.verbose(@verbose) do + effective_verbose = @verbose || FileUtilsExt.verbose_flag == true + FileUtilsExt.verbose(effective_verbose) do args = "#{ruby_opts_string} #{run_code} " + - "#{file_list_string} #{option_list}" + "#{file_list_string} #{option_list(verbose: effective_verbose)}" ruby args do |ok, status| if !ok && status.respond_to?(:signaled?) && status.signaled? raise SignalException.new(status.termsig) @@ -133,13 +134,17 @@ def define self end - def option_list # :nodoc: - (ENV["TESTOPTS"] || + def option_list(verbose: @verbose) # :nodoc: + opts = ENV["TESTOPTS"] || ENV["TESTOPT"] || ENV["TEST_OPTS"] || ENV["TEST_OPT"] || @options || - "") + "" + if verbose && !opts.split.include?("-v") + opts = opts.empty? ? "-v" : "#{opts} -v" + end + opts end def ruby_opts_string # :nodoc: diff --git a/test/test_rake_file_utils.rb b/test/test_rake_file_utils.rb index 771e78f0f..88e06f714 100644 --- a/test/test_rake_file_utils.rb +++ b/test/test_rake_file_utils.rb @@ -12,7 +12,6 @@ def teardown FileUtils::LN_SUPPORTED[0] = true RakeFileUtils.verbose_flag = Rake::FileUtilsExt::DEFAULT ENV["RAKE_TEST_SH"] = @rake_test_sh - ENV["TESTOPTS"] = nil super end @@ -107,12 +106,9 @@ def test_safe_ln_fails_on_script_error def test_verbose verbose true assert_equal true, verbose - assert_equal "-v", ENV["TESTOPTS"] - ENV["TESTOPTS"] = nil verbose false assert_equal false, verbose - assert_equal nil, ENV["TESTOPTS"] verbose(true) { assert_equal true, verbose diff --git a/test/test_rake_test_task.rb b/test/test_rake_test_task.rb index b7ff3658f..2ca0daa96 100644 --- a/test/test_rake_test_task.rb +++ b/test/test_rake_test_task.rb @@ -191,6 +191,40 @@ def test_task_order_only_prerequisites assert_equal [b, c], t.prerequisite_tasks end + def test_option_list_verbose_without_testopts + tt = Rake::TestTask.new { |t| t.verbose = true } + assert_equal "-v", tt.option_list + end + + def test_option_list_verbose_with_testopts + ENV["TESTOPTS"] = "--ci-reporter" + tt = Rake::TestTask.new { |t| t.verbose = true } + assert_equal "--ci-reporter -v", tt.option_list + ensure + ENV.delete "TESTOPTS" + end + + def test_option_list_not_verbose_with_testopts + ENV["TESTOPTS"] = "--ci-reporter" + tt = Rake::TestTask.new { |t| t.verbose = false } + assert_equal "--ci-reporter", tt.option_list + ensure + ENV.delete "TESTOPTS" + end + + def test_option_list_skips_duplicate_v + ENV["TESTOPTS"] = "-v --ci-reporter" + tt = Rake::TestTask.new { |t| t.verbose = true } + assert_equal "-v --ci-reporter", tt.option_list + ensure + ENV.delete "TESTOPTS" + end + + def test_option_list_verbose_keyword_overrides + tt = Rake::TestTask.new { |t| t.verbose = false } + assert_equal "-v", tt.option_list(verbose: true) + end + def test_task_order_only_prerequisites_key t = task "a" => "b", order_only: ["c"] b, c = task("b"), task("c") From 604a3d9873f75442b6209b6f9d7938a5358a9fe1 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 16 Apr 2026 13:39:02 +0900 Subject: [PATCH 2/2] Isolate TESTOPTS env in TestRakeTestTask setup/teardown Copilot review on #723 pointed out that the new option_list tests either assumed TESTOPTS was unset or unconditionally deleted it in ensure, which would clobber a pre-existing TESTOPTS and leak state across tests. Save and restore the previous value from setup/teardown so each test starts from a clean slate without losing the process environment value, and drop the now-redundant ensure blocks. Co-Authored-By: Claude Opus 4.6 (1M context) --- test/test_rake_test_task.rb | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/test/test_rake_test_task.rb b/test/test_rake_test_task.rb index 2ca0daa96..e88861217 100644 --- a/test/test_rake_test_task.rb +++ b/test/test_rake_test_task.rb @@ -5,6 +5,21 @@ class TestRakeTestTask < Rake::TestCase # :nodoc: include Rake + def setup + super + @_previous_testopts = ENV["TESTOPTS"] + ENV.delete "TESTOPTS" + end + + def teardown + if @_previous_testopts.nil? + ENV.delete "TESTOPTS" + else + ENV["TESTOPTS"] = @_previous_testopts + end + super + end + def test_initialize tt = Rake::TestTask.new do |t| end refute_nil tt @@ -200,24 +215,18 @@ def test_option_list_verbose_with_testopts ENV["TESTOPTS"] = "--ci-reporter" tt = Rake::TestTask.new { |t| t.verbose = true } assert_equal "--ci-reporter -v", tt.option_list - ensure - ENV.delete "TESTOPTS" end def test_option_list_not_verbose_with_testopts ENV["TESTOPTS"] = "--ci-reporter" tt = Rake::TestTask.new { |t| t.verbose = false } assert_equal "--ci-reporter", tt.option_list - ensure - ENV.delete "TESTOPTS" end def test_option_list_skips_duplicate_v ENV["TESTOPTS"] = "-v --ci-reporter" tt = Rake::TestTask.new { |t| t.verbose = true } assert_equal "-v --ci-reporter", tt.option_list - ensure - ENV.delete "TESTOPTS" end def test_option_list_verbose_keyword_overrides