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