テストが失敗した場合でも後続のテストを検証する方法

#はじめに
たまに1つの`it`の中に複数の`example`を入れたいケースがあると思います。
単純に複数の`example`を追加しただけだと、テストが失敗した時に後続のテストが流れず、**失敗したテストの修正→後続のテストが失敗する→失敗したテストの修正**の繰り返しになり面倒です。
そんな時は`aggregate_failures`を指定すると解決できます。
#aggregate_failuresとは
[公式ドキュメント](https://relishapp.com/rspec/rspec-expectations/docs/aggregating-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を使わない場合
以下のコードで確認してみます。

```ruby
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`を指定して実行してみます。

```ruby
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`の指定方法はいくつかあるので、ここからはそれぞれの指定の仕方を見ていきます。

##ブロックで指定する方法
先ほども記載しましたが、ブロックでの指定です。

```ruby
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`のメタ情報として指定する方法です。

```ruby
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`を第一引数で指定してみます。

```ruby
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`を指定していきましょう。