DiffDaily

Deep & Concise - OSS変更の定点観測

[rails/rails] Railties テスト実行時の `--trace` オプションエラーを修正

rails/rails

背景

Railties ディレクトリで bundle exec rake test --trace を実行すると、すべてのテストは成功するものの、プロセス終了時に invalid option: --trace というエラーが発生していました。この問題は、Rake のオプションが Minitest に誤って渡されることで発生していました。

問題の原因

エラーが発生する流れは以下の通りです:

  1. test:isolated タスクが test/isolation/abstract_unit.rb を require
  2. abstract_unit.rbactive_support/testing/autorun を require
  3. autorun.rbMinitest.autorun を呼び出し、at_exit フックを設定
  4. プロセス終了時、Minitest が ARGV をパースしようとする
  5. ARGV に残っている --trace(Rake のオプション)を Minitest が認識できずエラー

この問題は、Rake と Minitest が同じ ARGV を共有しているために発生します。Rake のオプションが終了時まで ARGV に残り、Minitest の自動実行フックがそれをパースしようとして失敗していました。

解決方法

今回の修正では、test:isolated タスクの ensure ブロック内で ARGV.clear を呼び出すことで、この問題を解決しています。

変更後:

namespace :test do
  task :isolated do
    # ... テスト実行処理 ...
  ensure
    output_file&.close
    output_file&.unlink

    # Clear ARGV to prevent Minitest from trying to parse rake options like --trace
    # at exit. The abstract_unit.rb requires active_support/testing/autorun which
    # calls Minitest.autorun, setting up an at_exit hook that would fail on
    # unrecognized options.
    ARGV.clear
  end
end

ensure ブロックで ARGV をクリアすることにより、Minitest の at_exit フックが実行される時点では、Rake 固有のオプションが残っていない状態になります。これにより、Minitest はクリーンな状態でオプションをパースでき、エラーが発生しなくなります。

技術的な考察

この問題は、Ruby のグローバル変数 ARGV を複数のライブラリが共有することで発生する典型的な競合の例です。at_exit フックの実行タイミングと、そこで参照される ARGV の状態に注意を払う必要があります。

特に、以下のような場合には同様の問題が発生する可能性があります:

  • Rake タスク内でテストフレームワークを実行する
  • at_exit フックで ARGV を参照するライブラリを使用する
  • 複数のコマンドラインツールを組み合わせて使用する

今回の修正は、テスト実行後のクリーンアップ処理として ARGV をクリアすることで、後続の処理に副作用を残さないようにしています。