#はじめに
たまに1つのit
の中に複数のexample
を入れたいケースがあると思います。
単純に複数のexample
を追加しただけだと、テストが失敗した時に後続のテストが流れず、失敗したテストの修正→後続のテストが失敗する→失敗したテストの修正の繰り返しになり面倒です。
そんな時はaggregate_failures
を指定すると解決できます。
#aggregate_failuresとは
公式ドキュメントを見るとこのように説明されています。
RSpec::Expectations provides aggregate_failures, an API that allows you to group a set of expectations and see all the failures at once, rather than it aborting on the first failure.
つまり、aggregate_failures
を指定することで、テストが失敗した場合でも後続のテストを検証することができます。
実際に挙動を見た方が早いと思うので、早速試してみたいと思います。
##aggregate_failuresを使わない場合
以下のコードで確認してみます。
require 'spec_helper'
RSpec.describe 'hoge spec' do
it 'hogeになること' do
expect(1).to eq(2)
expect(1).to eq(3)
end
end
テストを走らせてみると以下のような結果になりました。
hoge spec
hogeになること (FAILED - 1)
Failures:
1) hoge spec hogeになること
Failure/Error: expect(1).to eq(2)
expected: 2
got: 1
(compared using ==)
# ./spec/hoge_spec.rb:5:in `block (2 levels) in <top (required)>'
Top 1 slowest examples (0.0273 seconds, 89.2% of total time):
hoge spec hogeになること
0.0273 seconds ./spec/hoge_spec.rb:4
Finished in 0.0306 seconds (files took 0.23906 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/hoge_spec.rb:4 # hoge spec hogeになること
結果を見ると1つ目のexpect
が失敗した後、2つ目のexpect
は検証されていないことが分かります。
##aggregate_failuresを使った場合
次に以下のようにaggregate_failures
を指定して実行してみます。
require 'spec_helper'
RSpec.describe 'hoge spec' do
it 'hogeになること' do
aggregate_failures do
expect(1).to eq(2)
expect(1).to eq(3)
end
end
end
結果はこのようになりました。
hoge spec
hogeになること (FAILED - 1)
Failures:
1) hoge spec hogeになること
Got 2 failures from failure aggregation block.
# ./spec/hoge_spec.rb:5:in `block (2 levels) in <top (required)>'
1.1) Failure/Error: expect(1).to eq(2)
expected: 2
got: 1
(compared using ==)
# ./spec/hoge_spec.rb:6:in `block (3 levels) in <top (required)>'
1.2) Failure/Error: expect(1).to eq(3)
expected: 3
got: 1
(compared using ==)
# ./spec/hoge_spec.rb:7:in `block (3 levels) in <top (required)>'
Top 1 slowest examples (0.0255 seconds, 90.1% of total time):
hoge spec hogeになること
0.0255 seconds ./spec/hoge_spec.rb:4
Finished in 0.0283 seconds (files took 0.23094 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/hoge_spec.rb:4 # hoge spec hogeになること
どうやら1つ目のexpect
は失敗するのは同じですが、2つ目のexpect
も検証されているようです。
#aggregate_failuresの指定の仕方
ここまでで、aggregate_failures
を指定することでテストが失敗した場合でも後続のテストを検証してくれることが分かりました。
aggregate_failures
の指定方法はいくつかあるので、ここからはそれぞれの指定の仕方を見ていきます。
##ブロックで指定する方法
先ほども記載しましたが、ブロックでの指定です。
require 'spec_helper'
RSpec.describe 'hoge spec' do
it 'hogeになること' do
aggregate_failures do
expect(1).to eq(2)
expect(1).to eq(3)
end
end
end
##メタ情報として指定する方法
次はit
のメタ情報として指定する方法です。
require 'spec_helper'
RSpec.describe 'hoge spec' do
it 'hogeになること', :aggregate_failures do
expect(1).to eq(2)
expect(1).to eq(3)
end
end
###悪いパターン
以下のようにaggregate_failures
を第一引数で指定してみます。
require 'spec_helper'
RSpec.describe 'hoge spec' do
it :aggregate_failures do
expect(1).to eq(2)
expect(1).to eq(3)
end
end
結果はこちら。
hoge spec
aggregate_failures (FAILED - 1)
Failures:
1) hoge spec aggregate_failures
Failure/Error: expect(1).to eq(2)
expected: 2
got: 1
(compared using ==)
# ./spec/hoge_spec.rb:5:in `block (2 levels) in <top (required)>'
Top 1 slowest examples (0.02586 seconds, 89.1% of total time):
hoge spec aggregate_failures
0.02586 seconds ./spec/hoge_spec.rb:4
Finished in 0.02902 seconds (files took 0.23787 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/hoge_spec.rb:4 # hoge spec aggregate_failures
結果を見ても分かる通り、第一引数で指定した場合は後続の処理が流れていないので、期待した挙動になっていません。
失敗した場合でも後続の処理が流れているどうかはあまり確認しないと思うので、これは気付きづらいですね・・
#おわりに
aggregate_failures
の挙動といくつかの指定方法を見てきました。
個人的にはブロックで指定する方法がハマりどころもなさそうなので良いかなと思ってます。
複数のexample
を含める場合はaggregate_failures
を指定していきましょう。