be-let-it-beというコマンドラインツールを書きました。これはRSpecのスペックファイル中に存在する let
や let!
を自動的に可能な限り let_it_be
に書き換えるというものです。
$ be-let-it-be convert path/to/your_spec.rb
というふうに簡単に使うことができます。
let_it_beの効用
test-profに含まれているメソッド (宣言?) です。
let
やlet!
はテストごとに実行されるのに対して let_it_be
はテスト間で使い回されます *1。データベースがからむプロジェクトでRSpecを使っているとしばしば let
等の中でfactory_botを呼び出してレコードを作ったりすることになるわけですが、 let_it_be
を使うとそれがテスト間で1回で済むことになるためテストの実行時間を短くできる可能性が出てきます。
let_it_be
の効用の詳細については既に先行している有用な情報がありますのでそちらに譲ります:
- let_it_beとbefore_allでRSpecの実行時間を短くする - Blogメモφ(..)
- 約9000個の自動テストの 時間を50分->10分に短縮 Flakyテストを1%以下に抑えた話 - Speaker Deck
というわけで、be-let-it-beによって可能な限り let_it_be
に書き換えると自動的にテストの実行時間が短くなることが見込めるわけです。
どのように動くのか
富豪的な挙動ではあって、
- 与えられたスペックファイル内の
let
とlet!
を抽出してくる let
/let!
の出現した順からlet_it_be
に書き換えてテストを実行する。通ったらlet_it_be
の書き換えを維持し、通らなかったら元に戻す- 2を全て終わるまで繰り返す
というものになっています。つまり let
/let!
の個数ぶんの回数テストが実行されることになる……のでこのあたりはもうちょっとなんとかしたいなとは思っているという感じです *2。
また、出現した順にやっていくというのも最適解では無いとは思っており、本来であれば一番テスト実行時間が短くなる組み合わせを探索するのが良いのだろうとは思うのですが、しかし組み合わせ爆発が起こることが容易に想像できることや、ローカルでのテスト実行時間が案外ブレるのでそれを素朴に指標として使うことができないなどといった理由からここには手を付けていないという状況になっています。
というような感じではありますがちゃんと動くし、その結果についても一定満足というような感じではあります。
余談ではありますが、最初のバージョンでは let
/let!
の抽出にperser、コードの書き換えにunperserを使っていたのですが、 id:tomo_ariさんから「Prism使ったら良いんじゃないすか」というアドバイスをもらったのでそのようにしました。Prismを使うとparser挙動はもちろん、unparser的なことも一挙にできて便利で良かったです。
まとめ
be-let-it-beのご紹介でした。実戦投入されています。
なかなか良い感じです。ぜひご活用ください。