lib/minitest/unit.rb へのパッチ
ruby 1.9 を利用しており Rake を使用してテストしている。
以下、使用している Rakefile。
require "rake" require "rake/testtask" Rake::TestTask.new do |t| t.libs << "lib" t.libs << "test" t.test_files = FileList["test/**/*_{helper,test}.rb"] end task :default => :test
test ディレクトリ以下に require に失敗するスクリプトがある場合、次のような例外が発生した。
ragdoll$ rake19trunk (in /Users/kouji/work/s7) /Users/kouji/local/lib/ruby19trunk/1.9.1/minitest/unit.rb:328:in `block in autorun': unexpected return (LocalJumpError) /Users/kouji/work/s7/test/s7/secret_generator_test.rb:3:in `require': no such file to load -- s7/secret_generator (LoadError) from /Users/kouji/work/s7/test/s7/secret_generator_test.rb:3:in `<top (required)>' from /Users/kouji/local/lib/ruby19trunk/1.9.1/rake/rake_test_loader.rb:5:in `load' from /Users/kouji/local/lib/ruby19trunk/1.9.1/rake/rake_test_loader.rb:5:in `block in <main>' from /Users/kouji/local/lib/ruby19trunk/1.9.1/rake/rake_test_loader.rb:5:in `each' from /Users/kouji/local/lib/ruby19trunk/1.9.1/rake/rake_test_loader.rb:5:in `<main>' rake aborted! Command failed with status (1): [/Users/kouji/local/bin/ruby19trunk -Ilib:l...] (See full trace by running task with --trace)
上記のうち、以下が余計だと思う。原因を調べ、解決する。
/Users/kouji/local/lib/ruby19trunk/1.9.1/minitest/unit.rb:328:in `block in autorun': unexpected return (LocalJumpError)
上記の例外が発生したソースは以下。例外が発生した($! が nil でない)場合、処理を中断したいという意図だと思われる。ここは return ではなく、next がよいと思う。
def self.autorun at_exit { return if $! # don't run if there was an exception exit_code = MiniTest::Unit.new.run(ARGV) exit false if exit_code && exit_code != 0 } unless @@installed_at_exit @@installed_at_exit = true end
以下がパッチ。
Index: unit.rb =================================================================== --- unit.rb (revision 21138) +++ unit.rb (working copy) @@ -325,7 +325,7 @@ def self.autorun at_exit { - return if $! # don't run if there was an exception + next if $! # don't run if there was an exception exit_code = MiniTest::Unit.new.run(ARGV) exit false if exit_code && exit_code != 0 } unless @@installed_at_exit
このパッチを適用した結果。
ragdoll$ rake19trunk (in /Users/kouji/work/s7) /Users/kouji/work/s7/test/s7/secret_generator_test.rb:3:in `require': no such file to load -- s7/secret_generator (LoadError) from /Users/kouji/work/s7/test/s7/secret_generator_test.rb:3:in `<top (required)>' from /Users/kouji/local/lib/ruby19trunk/1.9.1/rake/rake_test_loader.rb:5:in `load' from /Users/kouji/local/lib/ruby19trunk/1.9.1/rake/rake_test_loader.rb:5:in `block in <main>' from /Users/kouji/local/lib/ruby19trunk/1.9.1/rake/rake_test_loader.rb:5:in `each' from /Users/kouji/local/lib/ruby19trunk/1.9.1/rake/rake_test_loader.rb:5:in `<main>' rake aborted! Command failed with status (1): [/Users/kouji/local/bin/ruby19trunk -Ilib:l...] (See full trace by running task with --trace)
これで、想定通りに動作するようになった。
あとは、ruby-core にメールを送ろう。
英語の作文をするために、述べたいことをまとめておく。
- test スクリプトの解析時にエラーが発生したときに LocalJump 例外が発生した。
- 原因は、self.autorun で指定している at_exit のブロックの中で return しているからです。
- return を next に修正してはどうか。
- 修正した結果、手元では LocalJump 例外が発生しなくなった。
メールを作成する前に、修正済みかもしれないので、 svn up をしてみよう。最近、Ryan が merge しているようだ。最新のソースでも修正されていないことが分かった。(誰も困っていないのかな?)
以下、作成したメール。(英語でメールを書くことになれていないため、いいたいことが伝わるかどうかが不安です。)
Hi Ryan, If $! is not nil, returns in the block of the at_exit method in MiniTest::Unit.autorun. Then raises LocalJump exception. ----- def self.autorun at_exit { return if $! # don't run if there was an exception exit_code = MiniTest::Unit.new.run(ARGV) exit false if exit_code && exit_code != 0 } unless @@installed_at_exit @@installed_at_exit = true end ----- The attached patch will fix the problem. Index: lib/minitest/unit.rb =================================================================== --- lib/minitest/unit.rb (revision 21508) +++ lib/minitest/unit.rb (working copy) @@ -325,7 +325,7 @@ def self.autorun at_exit { - return if $! # don't run if there was an exception + next if $! # don't run if there was an exception exit_code = MiniTest::Unit.new.run(ARGV) exit false if exit_code && exit_code != 0 } unless @@installed_at_exit Thanks, kouji.