Aruba 2.4.0 の依存変化に対応したテスト修正
Aruba 2.4.0 が irb への依存を追加したことで、標準ライブラリのロード順序や gemified バージョンが変化し、複数のテストが失敗するようになった。本PRはその影響を受けたテストと Gemfile の設定を修正し、テストスイートを再び安定させる。
背景
Aruba 2.4.0 の依存変更が、rspec のテスト環境に広範な影響を与えた。#325 によると、cucumber/aruba#969 によって Aruba が irb を依存として追加した結果、rdoc・erb・psych・tsort・pp など多数のライブラリの gemified バージョンが引き込まれるようになった。
この依存の連鎖により、具体的に以下の問題が発生した:
-
フォーマッターテストの失敗:
erbの gemified バージョンがバックトレースに混入し、Ruby バージョン間で期待値が一致しなくなった - JRuby テストの失敗:無名モジュールがアンセスター連鎖に混入し、モジュール名を検証するテストが壊れた
-
Ruby 3.0 での Cucumber テストの失敗:
tsortの gemified バージョン(0.1.0と0.2.0)が混在し、競合が発生した -
set.rbの読み込みが Ruby 4.0 未満での全体チェックに影響した
これらの問題は、テストの前提としていた「デフォルト gem からロードされる標準ライブラリ」の境界が、Aruba の推移的依存によって崩れたことに起因している。
技術的な変更
各問題に対して、影響を局所化する方針で修正が施された。
Gemfile:依存バージョンの整理
tsort のバージョン競合に対処するため、Ruby 3.1 未満の環境では tsort 0.1.0 を明示的に固定するよう変更された。また、mutex_m ~> 0.1.0 の指定は削除された。jruby-openssl の platform 指定も Gemfile から除去されている。
変更前:
platforms :jruby do
gem "jruby-openssl"
end
gem 'mutex_m', '~> 0.1.0' if RUBY_VERSION.to_f > 3.3
gem 'minitest', '~> 5.12.0'
変更後:
gem 'tsort', '0.1.0' if RUBY_VERSION.to_f < 3.1
gem 'minitest', '~> 5.15'
minitest のバージョン制約も ~> 5.12.0 から ~> 5.15 へ緩和されており、Aruba 2.4.0 の推移的依存との互換性が確保されている。
フォーマッターテストのバックトレース除外
erb.rb がバックトレースに混入することで、Ruby バージョンや stdlib / bundled gem の違いによってテスト期待値がブレる問題に対し、formatter_support.rb のバックトレースフィルターに erb.rb を除外するパターンを追加した。
変更後:
configuration.backtrace_formatter.exclusion_patterns << /erb\.rb/ # remove differences/churn between use of stdlib and bundled erb
これにより、stdlib の erb と gemified erb のどちらがロードされていても、フォーマッターのバックトレース出力テストが同一の結果を返すようになる。
共有サンプルグループの祖先チェーン検証を絞り込み
Aruba 2.4.0 が引き込む依存により、example_group.ancestors に無名モジュールが混入するようになった。この問題に対し、検証対象の祖先を RSpec::Core::MemoizedHelpers より前の部分のみに限定することで対処している。
変更前:
expect(example_group.ancestors.map(&:inspect)).to include_a_named_rather_than_anonymous_module
expect(example_group.ancestors.map(&:to_s)).to include_a_named_rather_than_anonymous_module
変更後:
relevant_ancestors = example_group.ancestors.take_while { |x| x != RSpec::Core::MemoizedHelpers }
expect(relevant_ancestors.map(&:inspect)).to include_a_named_rather_than_anonymous_module
expect(relevant_ancestors.map(&:to_s)).to include_a_named_rather_than_anonymous_module
take_while を用いて RSpec::Core::MemoizedHelpers に到達するまでの祖先のみを検証対象とすることで、それ以降に注入される外部由来の無名モジュールの影響を排除している。
サポートスペックの許可正規表現を修正
rspec-support の support_spec.rb では、ロードが許容されるファイルのリストに set.rb を追加するとともに、既存の正規表現のドットをエスケープする修正も行われた。
変更前:
/prettyprint.rb/, /pp.rb/, /diff\/lcs/
変更後:
/prettyprint\.rb/, /pp\.rb/, /set\.rb/, /diff\/lcs/
エスケープされていないドット(prettyprint.rb)は任意の1文字にマッチしてしまうため、\. への修正は正確なパスマッチという意味でも正しい変更だ。
設計判断
テストの期待値を変更するのではなく、テストの「観測範囲」を絞り込む方針 が採用された。
今回の修正では、外部依存の変化に合わせてアサーションの期待値を書き換えるのではなく、外部依存の影響が及ばない範囲でのみ検証するよう境界を引き直している。take_while { |x| x != RSpec::Core::MemoizedHelpers } による祖先の絞り込みや、/erb\.rb/ のバックトレース除外がその例だ。また、tsort 0.1.0 のバージョン固定は、Ruby 3.1 未満の環境で tsort の複数バージョンが混在することによる競合を Gemfile レベルで回避するための対処として採用されている。
まとめ
本PRは、単一の上流依存(Aruba 2.4.0)の変更が推移的に波及した複数のテスト失敗を、影響範囲の局所化という一貫した方針で修正した。各修正が「外部由来のノイズをテスト対象から分離する」という設計思想に沿っており、テストの堅牢性を高める改善として読み取ることができる。