Posted at

ちょっとだけ嬉しくなるrspecの小ネタ


はじめに

この記事は 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 という抽象的な表現より可読性は高く思えます。

subjectlet と同様に遅延評価される処理で

let! と同様に subject! と書くことで、example の直前に評価させることもできます。


example の書き方

ドキュメント の最初には it で example が書かれていますが

他にも examplespecify という別名が存在します。

どの書き方でも挙動は同じです。

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ケースだけ確認したいのに…」という場合にケースを絞る方法がいくつかあります。

もっと手軽に一部ケースだけを実行する方法として、行数指定があります。

※下記は引用したコードを少しだけ書き直したもの

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



おわりに

小ネタでした。事務的にテストコードを書くのではなく

実行結果がより仕様らしく見えるように、自然な英語になるように

また、楽にメンテできるように心がけたいです。