はじめに
この記事は LIFULLその2 Advent Calendar 2018 の20日目の記事です。
業務で rspec のテストコードを書いたときの些細な発見を整理してまとめます。
オムニバスな感じで、ひとつくらい読者様の発見があれば幸せです。
rspecメモ
subject の工夫
DRYなテストコードを書くためには subject
が必須です。
ということはいろんなところで書かれていますが
subject
に名前がつけられるということを Better Specs で学びました。 ※下記は引用
subject(:hero) { Hero.first }
it "carries a sword" do
expect(hero.equipment).to include "sword"
end
テスト対象がつまり何なのかを直接的に書けるため
subject
という抽象的な表現より可読性は高く思えます。
subject
も let
と同様に遅延評価される処理で
let!
と同様に subject!
と書くことで、example の直前に評価させることもできます。
example の書き方
ドキュメント の最初には it
で example が書かれていますが
他にも example
や specify
という別名が存在します。
どの書き方でも挙動は同じです。
describe Account do
it "has a balance of zero when first opened" do
end
example "has a balance of zero when first opened" do
end
specify "has a balance of zero when first opened" do
end
end
じゃあなんで3つあるのかと思ってコード内のコメントを読んでみると
メソッド | コメント | 意訳 |
---|---|---|
example | Defines an example within a group. | exampleを定義します |
it | Defines an example within a group. This is the primary API to define a code example. |
これがプライマリなAPIです |
specify | Defines an example within a group. Useful for when your docstring does not read well off of it . |
docstringが it をうまく読めないときに便利です |
(ワンライナーとか書くならどうせ選択肢はなくなるので)
全体的に it
を使っていて問題ないと思いますが
日本語で自然な記述を目指すのであれば example
が望ましいように見えます。
実行するテストケースのフィルタリング
1ファイルが小さい単位で作られていたら幸せですが
歴史を積み重ねたファイルには多くのテストケースが存在します。
「1ケースだけ確認したいのに…」という場合にケースを絞る方法がいくつかあります。
- focus (Inclusion filters): focusと明示したケースだけを実行する
- 実行時のtagオプション: 実行したいケースにタグを付けておいて部分的に実行する
- 実行時のexampleオプション: 名前を指定したケースだけ実行する
もっと手軽に一部ケースだけを実行する方法として、行数指定があります。
※下記は引用したコードを少しだけ書き直したもの
RSpec.describe "outer group" do
it "example in outer group" do
end
describe "nested group" do
it "first example in nested group" do
end
it "second example in nested group" do
end
end
end
2行目の example in outer group
だけ実行
$ bundle exec rspec --format d test_spec.rb:2
Run options: include {:locations=>{"./test_spec.rb"=>[2]}}
outer group
example in outer group
Finished in 0.00369 seconds (files took 0.14879 seconds to load)
1 example, 0 failures
5行目にある nested group
内だけを実行
$ bundle exec rspec --format d test_spec.rb:5
Run options: include {:locations=>{"./test_spec.rb"=>[5]}}
outer group
nested group
first example in nested group
second example in nested group
Finished in 0.00342 seconds (files took 0.13323 seconds to load)
2 examples, 0 failures
9行目にある second example in nested group
だけを実行
$ bundle exec rspec --format d test_spec.rb:9
Run options: include {:locations=>{"./test_spec.rb"=>[9]}}
outer group
nested group
second example in nested group
Finished in 0.00342 seconds (files took 0.13009 seconds to load)
1 example, 0 failures
一部だけを実行する方法としてはもっとも楽ではないかと思います。
(よく見たらヘルプにも記載されていました)
you can select individual examples by appending the line number(s) to the filename:
rspec path/to/a_spec.rb:37:87
おわりに
小ネタでした。事務的にテストコードを書くのではなく
実行結果がより仕様らしく見えるように、自然な英語になるように
また、楽にメンテできるように心がけたいです。