LoginSignup
12
6

More than 5 years have passed since last update.

RSpecの特殊なマッチャーを敢えて使わない方がいいケース

Posted at

RSpecが提供するマッチャーは色々便利だったりしますが、一部のものはあまりうまく作りこまれておらず、テストの結果が本来行うべき、失敗した時にどう失敗したのかを分かりやすく伝えるという機能を損ない、本末転倒になってしまっていることがしばしばあるので、そういうマッチャーは無理に使わないようにしましょう、という話です。

expect(response).to be_ok など

例えば、下記のようなよくあるexampleを考えてみます。

it '400 Bad Requestを返す' do
  expect(response).to be_bad_request
end

このexampleが失敗した場合、次のような出力になります。

expected `#<ActionController::TestResponse:0x007f79b8ed6348 @body=...
[...超長い出力...]
>>.bad_request?` to return true, got false

欲しい情報はstatus codeだけなのに、ActionController::TestResponseオブジェクトの中身がまるまる表示されてしまい、一体間違ったstatus codeが何だったのか、少なくともひと目ではわからないでしょう。
また、これらのマッチャーはあらゆるHTTP status codeをサポートしているわけではないため、例えば下記のようには書けず、一貫性にも欠いてしまいます。

it '201 Createdを返す' do
  expect(response).to be_created
end

結局いずれの場合においても、statusメソッドの中身を直接eqマッチャーで比較したほうがわかりやすいのです。

it '400 Bad Requestを返す' do
  expect(response.status).to eq 400
end

こちらのexampleが失敗した場合は、次のように非常に明瞭な結果が出力されます。

expected: 400
     got: 200

expect(page).to have_css(...) など

同じような問題はcapybaraのマッチャーにも言えます。
have_cssは(試してないですが多分have_xpathも)はテストが失敗した時、テスト対象のDOMが具体的にどんな構造になっていたかを教えてくれません。
findメソッドなどで対象の要素を取得し、Capybara::Node::ElementのAPIを駆使して、求めたい値を比較しましょう。
例えば、下記はhogeというクラスの画像のpathを調べる例です。
[]メソッドを使ってsrcアトリビュートを取得しています。

expect(find('img.hoge')[:src]).to eq '/hoge.png'

formの要素の値を調べたりもできます。

expect(find('textarea.hoge').value).to eq 'hoge'

allを使って要素の数を確認するのもいいでしょう。

expect(all('.hoge').length).to eq 1
12
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
6