PIYO - Tech & Life -

RSpecで失敗したテストだけを対象にできる--only-failuresオプション

RSpec Ruby

プロジェクトの根幹ぽいところをちょっと変えたばっかりにテストの半分ぐらいがが失敗してしまって、1箇所直したら全部パスするみたいなことはあるあるなんじゃないかと思います。RSpecでは失敗したテストのみを対象に再実行できるオプションがあるので、それを使うと良いです。

特にコマンドラインからrspecコマンドでテストを流している人(=IDEのサポートがあまりない人)にはオススメです。社内見てると案外使われてないのか?という感じでしたが、僕は超使っているので書いておこうかと。

まずRSpec3.3以降が必要です。出たのは3年ほど前なので、最近は大丈夫かと思います。

それと、この機能は最後に実行したテストの実行結果をどこかにとっておく必要があり、それをファイルで実現しているので、その設定が必要です。

spec_helper.rbあたりに以下の記述をしてあげると良いです。

# spec_helper.rb
RSpec.configure do |config|
  config.example_status_persistence_file_path = "spec/examples.txt"
end

また、spec/examples.txtはソース管理に入れる必要がないので除外しておきます。

この状態でRSpecを実行してみると、例えば次のようなファイルが生成されます。

./spec/models/user_spec.rb[1:1:1:1]                 | passed | 0.11494 seconds |
./spec/models/user_spec.rb[1:1:2:1]                 | failed | 0.1067 seconds  |
./spec/models/user_spec.rb[1:2:1:1]                 | failed | 0.11267 seconds |
./spec/models/user_spec.rb[1:2:2:1]                 | passed | 0.06915 seconds |
./spec/models/user_spec.rb[1:2:3:1]                 | passed | 0.08749 seconds |
./spec/models/user_spec.rb[1:3:1:1:1:1]             | passed | 0.16688 seconds |
./spec/models/user_spec.rb[1:3:1:1:2:1:1]           | passed | 0.11628 seconds |
./spec/models/user_spec.rb[1:3:1:1:2:2:1]           | passed | 0.12612 seconds |
./spec/models/user_spec.rb[1:3:1:1:2:2:2]           | passed | 0.10565 seconds |

それぞれのテストがpassedなりfailedなりマークされています。

次の実行時に--only-failuresオプションを付けて同様のfailedとマークされたテストのみが実施されます。例えば↑の例であれば2件しか実行されないので時間短縮になります。

また、このexamples.txtのようなファイルは都度全て上書きされるわけではなく、rspecの対象ファイルを指定して実行したときに、関連の箇所しか書き換えません。説明がむずい。

例えば、次のような順番で実行したとします。

# 全件テスト
% rspec
=> user_spec.rbとproject_spec.rbで一部のテストが失敗したとする

# まずはuser_spec側を修正して再テスト
% rspec path/to/user_spec.rb --only-failures
=> user_specのうち失敗したテストを実行

# project_spec側をテスト
% rspec path/to/project_spec.rb --only-failures

みたいなときに、最後のproject_spec.rbを対象に実施したときにも、最初のfailedが残っているのでその箇所のみテストを実行できるわけです。

↑のような全体をテストをしてファイルごとに直して確認していく、というようなことはよくやります。最近ではHeadless Chromeへの移行時に似たようなことを実施しました。

一応言っておくと、ファイルごとに直していくとその変更が他のテストに影響することもあり得るので最後に全体をテストするのは大事です。