RSpecの機能aggregate_failuresを紹介したいと思います。
テストコードを記述をする際、1つのexampleに対して1つのexpectationを記述できる。
RSpec.describe Client do
let(:response) { Client.make_request }
it "returns a 200 response" do
expect(response.status).to eq(200)
end
it "indicates the response body is JSON" do
expect(response.headers).to include("Content-Type" => "application/json")
end
it "returns a success message" do
expect(response.body).to eq('{"message":"Success"}')
end
end
一方、以下のように1つのexampleに対して、全てのexpectationをまとめることもできる。
RSpec.describe Client do
it "returns a successful JSON response" do
response = Client.make_request
expect(response.status).to eq(200)
expect(response.headers).to include("Content-Type" => "application/json")
expect(response.body).to eq('{"message":"Success"}')
end
end
後者の記述方法の方が
- 1回のリクエストで複数のテストができるため、テストの処理速度が速い
- 複数 example を記述する必要がないため、思いついたテストパターンを上から下へさくっと書ける
といったメリットがある。
しかし、もし最初のテストで失敗した場合、残りのテストがどうなったかがわからない問題がある。
そこで、aggregate_failuresを利用すると、一部が失敗したとしても、全ての expectation が検証されるようになる。下記のように記述する。
RSpec.describe Client do
it "returns a successful JSON response" do
response = Client.make_request
aggregate_failures "testing response" do
expect(response.status).to eq(200)
expect(response.headers).to include("Content-Type" => "application/json")
expect(response.body).to eq('{"message":"Success"}')
end
end
end
結果、全てのテストを検証してくれるようになる。
1) Client returns a successful response
Got 3 failures from failure aggregation block "testing reponse".
# ./spec/client_spec.rb:5
1.1) Failure/Error: expect(response.status).to eq(200)
expected: 200
got: 404
(compared using ==)
# ./spec/client_spec.rb:6
1.2) Failure/Error: expect(response.headers).to include("Content-Type" => "application/json")
expected {"Content-Type" => "text/plain"} to include {"Content-Type" => "application/json"}
Diff:
@@ -1,2 +1,2 @@
-[{"Content-Type"=>"application/json"}]
+"Content-Type" => "text/plain",
# ./spec/client_spec.rb:7
1.3) Failure/Error: expect(response.body).to eq('{"message":"Success"}')
expected: "{\"message\":\"Success\"}"
got: "Not Found"
(compared using ==)
# ./spec/client_spec.rb:8
さらに、全体に適用したい場合、以下のように設定する。
RSpec.configure do |c|
c.define_derived_metadata do |meta|
meta[:aggregate_failures] = true unless meta.key?(:aggregate_failures)
end
end
このように設定すると、exampleを書くたびにaggregate_failuresでラップする必要がなくなる。