🐒
テストメソッドを1つだけ実行するのが面倒だったので minitest_runner.rb というスクリプトを書いてみた
minitest では次のように -n
オプションを使うことでテストメソッド(テストケース)1個だけを実行することができます。
ruby test/test_foo.rb -n {メソッド名}
このときファイル名はシェルの補完が効くのでスッと入力できますが、メソッド名はシェルの補完が効きません。
で、手入力したり、エディタで開いているテストコードやファイルを grep した結果からコピペしてくることになるのですが、いずれにしてもめんどくさく……。
というわけでやっつけスクリプトを書いてみました。
使い方
- (1) プロジェクトのルートディレクトリで
ruby minitest_runner.rb
を実行する - (2) テストファイルが番号付きで列挙されるので、番号を入力して選択
- (3) 選択したファイル内のテストメソッドが番号付きで列挙されるので、番号を入力して選択
- (4) 選択したテストメソッドが実行される
というのが基本ですが、
ruby minitest_runner.rb {ファイルの番号} {メソッドの番号}
のように引数でファイルとメソッドの番号を指定した場合は非対話的に実行されるようにしています。すでに番号が分かっていて何度も繰り返したい場合はこれで。
実行の例
例として Rake でやってみたもの。
$ ruby minitest_runner.rb
----
files:
(0) . / test / test_private_reader.rb (0)
(1) . / test / test_rake.rb (1)
(2) . / test / test_rake_application.rb (2)
... 長いので途中省略 ...
(43) . / test / test_rake_win32.rb (43)
(44) . / test / test_thread_history_display.rb (44)
(45) . / test / test_trace_output.rb (45)
Select item: 44 ... 番号を入力する
----
methods:
(0) test_banner (0)
(1) test_item_queued (1)
(2) test_item_dequeued (2)
(3) test_multiple_items (3)
(4) test_waiting (4)
(5) test_continue (5)
(6) test_thread_deleted (6)
(7) test_thread_created (7)
Select item: 6 ... 番号を入力する
----
bundle exec ruby ./test/test_thread_history_display.rb -n test_thread_deleted ... 実際に実行されるコマンド
----
Run options: -n test_thread_deleted --seed 62390
# Running:
.
Finished in 0.001000s, 999.5052 runs/s, 1999.0104 assertions/s.
1 runs, 2 assertions, 0 failures, 0 errors, 0 skips
ソース
10分くらいで適当に書いたものなのでプロジェクトによっては動かせなかったりすると思いますが、必要になったらその都度いじればいいかなと。
# minitest_runner.rb
def select_item(title, items)
puts "----"
puts "#{title}:"
# 候補一覧を表示
items
.map { |item| item.gsub("/", " / ") } # パスの区切りを見やすく
.each_with_index { |item, i| puts " (#{i}) #{item} (#{i})" }
# ユーザの入力を受け取る
puts ""
print "Select item: "
input = $stdin.gets
raise if /\d+/ !~ input
items[input.to_i]
end
def select_file(idx)
files = Dir.glob("./test/**/test_*.rb").sort
if idx
files[idx.to_i]
else
select_item("files", files)
end
end
def select_method(file, idx)
method_lines =
File.read(file).each_line
.select { |line| /def test_.+/ =~ line }
.map { |line| line.sub(/def /, "").strip }
method_line =
if idx
method_lines[idx.to_i]
else
select_item("methods", method_lines)
end
md = method_line.match(/(test_[a-z0-9_]+)/)
md[1]
end
# --------------------------------
file_idx, method_idx = ARGV
file = select_file(file_idx)
method = select_method(file, method_idx)
cmd = ""
cmd << "bundle exec " if File.exist?("./Gemfile")
cmd << "ruby #{file} -n #{method}"
puts "----"
puts cmd
puts "----"
system cmd
exit $?.exitstatus unless $?.success?
Ruby関連で他に書いたもの
Discussion