rspecの死んでいるコードを検出するrspectreを試してみた
rspectreってなに?
rspectreはspecファイル内の以下のような意味をなしていない死んだコードを違反として検出・自動修正してくれるツール(Ruby Gem)です。
- 未使用の
let
(UnusedLet
) - 未使用の
subject
(UnusedSubject
) - 未使用の
shared_examples
とshared_contexts
(UnusedSharedSetup
)
rubocop-rspec のような静的解析ツールでは検出しがたいものを実際にrspecを実行しつつ解析して検出します。
Ruby 2.5以降、rspec 3.0以降をサポートしているようです。[1]
rspectreの使い方
インストール
READMEのままです。
以下を実行する
gem install rspectre
または Gemfile
に以下を追加して bundle install
します。
gem "rspectre"
実行方法
特に設定ファイルなどはないようです。
以下のように実行します。[2]
$ rspectre
rspecに追加のオプションを渡したい場合は以下のように --rspec
オプションを使います。
$ rspectre --rspec '--fail-fast --format documentation spec/'
特定のファイルだけ指定して実行したい場合も --rspec
オプションを使います。
$ rspectre --rspec '--fail-fast spec/path/to/your_spec.rb'
自動修正する場合は以下のように --auto-correct
オプションを使います。
$ rspec --auto-correct
お試し実行
以下のようなspecファイルがあったとします。
require "spec_helper"
RSpec.describe "rspectreお試し" do
shared_examples "未使用のshared_examplesです" do
it "使われない検証です" do
expect(1 + 1).to eq 2
end
end
subject { "未使用のsubjectです" }
let(:unused_let) { "未使用のletです" }
it "何か検証します" do
expect(1 + 1).to eq 2
end
end
rspectreを実行すると違反が以下のように検出されます。
$ rspectre
/home/yuji_developer/rspectre-test/spec/hoge_spec.rb:4:3: UnusedSharedSetup: Unused `shared_examples`, `shared_examples_for`, or `shared_context` definition.
shared_examples "未使用のshared_examplesです" do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/home/yuji_developer/rspectre-test/spec/hoge_spec.rb:10:3: UnusedSubject: Unused `subject` definition.
subject { "未使用のsubjectです" }
^^^^^^^
/home/yuji_developer/rspectre-test/spec/hoge_spec.rb:11:3: UnusedLet: Unused `let` definition.
let(:unused_let) { "未使用のletです" }
^^^^^^^^^^^^^^^^
自動修正を実行してみます。
$ rspectre --auto-correct
差分は以下のようになります。
diff --git spec/hoge_spec.rb spec/hoge_spec.rb
index 0cecc3e..97fd20f 100644
--- spec/hoge_spec.rb
+++ spec/hoge_spec.rb
@@ -1,14 +1,10 @@
require "spec_helper"
RSpec.describe "rspectreお試し" do
- shared_examples "未使用のshared_examplesです" do
- it "使われない検証です" do
- expect(1 + 1).to eq 2
- end
- end
+
- subject { "未使用のsubjectです" }
- let(:unused_let) { "未使用のletです" }
+
+
it "何か検証します" do
expect(1 + 1).to eq 2
気になったところ
自動修正でインデントのスペースや空行が残る
自動修正で UnusedLet
などを修正するとインデントのスペースや空行が残ったままになります。
これはrubocopで余分なスペースや空行を修正できるのでそこまで困ることはなさそうですがちょっと気になりますよね。
--rspec
オプションを指定した場合はrspecに指定したいすべてのオプションを指定する必要がある
例えば以下のようにフォーマットオプションだけを指定した場合、デフォルトで指定される --fail-fast
オプションが指定されていない扱いになります。
これだけならまだ良いのですが、対象のファイルも指定されていない扱いになるようでこれだと何も解析されません。
$ rspectre --rspec '--format documentation'
意図したように動作させるためには、以下のように指定する必要があります。
$ rspectre --rspec '--fail-fast --format documentation spec/'
実行中にrspecの出力が表示されない
rspectre経由で実行するとrspecの出力が実行中にコンソールに出力されません。
テストが失敗した場合は最後にrspecの出力が表示される仕組みになっているようです。
どこまで進んだのかが見えないのがちょっと精神衛生上良くないかなと思ったりします。
並列実行がサポートされていない
rspecはparallel_testsなどで並列実行が可能ですが、rspectreではサポートされていないようです。
規模が大きいプロジェクトでは気軽に全specファイルに対して実行するのは難しいかもしれません。
依存関係がそこそこある
一概に悪いとは言えませんが、rspectreは依存関係がそれなりにあります。
依存関係があまり増えるとメンテナンスの手間が上がるので Gemfile
に追加するか迷っています。
まとめ
rspectreはまだ改善の余地がありそうですが、現状でもかなり便利に使えると思います。
実際に動いているプロジェクトでrspectreを使ってみたところ、未使用の let
が見つかったり、未使用の let
と思いきやexmapleがないことで未使用と検出された[3]ものが見つかったりと、かなり有意義な結果となりました。
どなたかのご参考になれば幸いです。
Discussion