tag:crieit.net,2005:https://crieit.net/tags/minitest/feed 「minitest」の記事 - Crieit Crieitでタグ「minitest」に投稿された最近の記事 2021-04-22T19:23:45+09:00 https://crieit.net/tags/minitest/feed tag:crieit.net,2005:PublicArticle/16985 2021-04-22T19:23:45+09:00 2021-04-22T19:23:45+09:00 https://crieit.net/posts/ruby-minitest-runner テストメソッドを1つだけ実行するための minitest_runner.rb というスクリプトを書いてみた <p><a target="_blank" rel="nofollow noopener" href="https://github.com/seattlerb/minitest">minitest</a> では次のように <code>-n</code> オプションを使うことでテストメソッド(テストケース)1個だけを実行することができます。</p> <pre><code>ruby test/test_foo.rb -n {メソッド名} </code></pre> <p>このときファイル名はシェルの補完が効くのでスッと入力できますが、メソッド名はシェルの補完が効きません。</p> <p>で、手入力したり、エディタで開いているテストコードやファイルを grep した結果からコピペしてくることになるのですが、いずれにしてもめんどくさく……。</p> <p>というわけでやっつけスクリプトを書いてみました。</p> <h1 id="使い方"><a href="#%E4%BD%BF%E3%81%84%E6%96%B9">使い方</a></h1> <ul> <li>(1) プロジェクトのルートディレクトリで <code>ruby minitest_runner.rb</code> を実行する</li> <li>(2) テストファイルが番号付きで列挙されるので、番号を入力して選択</li> <li>(3) 選択したファイル内のテストメソッドが番号付きで列挙されるので、番号を入力して選択</li> <li>(4) 選択したテストメソッドが実行される</li> </ul> <p>というのが基本ですが、</p> <pre><code>ruby minitest_runner.rb {ファイルの番号} {メソッドの番号} </code></pre> <p>のように引数でファイルとメソッドの番号を指定した場合は非対話的に実行されるようにしています。すでに番号が分かっていて何度も繰り返したい場合はこれで。</p> <h1 id="実行の例"><a href="#%E5%AE%9F%E8%A1%8C%E3%81%AE%E4%BE%8B">実行の例</a></h1> <p>例として <a target="_blank" rel="nofollow noopener" href="https://github.com/ruby/rake">Rake</a> でやってみたもの。</p> <pre><code>$ 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 </code></pre> <h1 id="ソース"><a href="#%E3%82%BD%E3%83%BC%E3%82%B9">ソース</a></h1> <p>10分くらいで適当に書いたものなのでプロジェクトによっては動かせなかったりすると思いますが、必要になったらその都度いじればいいかなと。</p> <pre><code class="ruby"># 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? </code></pre> <h1 id="Ruby関連で他に書いたもの"><a href="#Ruby%E9%96%A2%E9%80%A3%E3%81%A7%E4%BB%96%E3%81%AB%E6%9B%B8%E3%81%84%E3%81%9F%E3%82%82%E3%81%AE">Ruby関連で他に書いたもの</a></h1> <p><a target="_blank" rel="nofollow noopener" href="https://memo88.hatenablog.com/archive/category/Ruby">https://memo88.hatenablog.com/archive/category/Ruby</a></p> sonota486