Aggregating failures in RSpec
Sometimes our examples have multiple independent expectations. In such cases, the default behavior of RSpec to abort on the first failure may not be ideal.
Consider the following example:
it do
get('/api/v1/users')
expect(response.status).to eq(200)
expect(response.body).to eq('[{"name":"Johny"}]')
end
If our API returns a wrong status, RSpec will print the following output:
1) Users GET /api/v1/users example at ./spec/requests/api/v1/users_spec.rb:9
Failure/Error: expect(response.status).to eq(200)
expected: 200
got: 201
While this gives us feedback on the response’s status being wrong, it entirely skips the assertion on the response’s body, even though having both results could make debugging easier.
RSpec has a neat solution to this: Aggregating Failures.
To use it, you can either tag the whole example with :aggregate_failures
:
it 'does something', :aggregate_failures do
...
end
Or you can just wrap your assertions in an aggregate_failures
block:
it do
get('/api/v1/users')
aggregate_failures do
expect(response.status).to eq(200)
expect(response.body).to eq('[{"name":"Johny"}]')
end
end
This will change RSpec’s default behavior and will group both expectations:
1) Users GET /api/v1/users example at ./spec/requests/api/v1/users_spec.rb:9
Got 2 failures from failure aggregation block.
1.1) Failure/Error: expect(response.status).to eq(200)
expected: 200
got: 201
1.2) Failure/Error: expect(response.body).to eq('[{"name":"Johny"}]')
expected: "[{\"name\":\"Johny\"}]"
got: "[{\"name\":\"Jane\"}]"
More info: documentation
Tweet