毎日SEの技術ブログ

平日は社内SE、休みは自宅でサービス開発するSEの技術ブログ

RSpec before(:all)とbefore(:each)の違い

はまったのでメモ。

大きな違いは実行順番ではない

自分もそうなんですが:allと:eachの違いは実行順番だけだと思っていましたが実際は違います。 例えば下記のようなテストの場合

describe Account do
  context '#signin' do
    context 'メールアドレスとパスワードが一致していたら' do 

      before(:all)
        @mail = 'hoge@mail.com'
        @password = '1234'
        Account.create(mail: @mail, password: @password)
      end

      after(:each)
        Account.delete_all
      end
      
      it 'サインイン出来る' do
        # テスト処理
      end
    end
  end
end

この処理はサインインできることをテストするために、必要なアカウントをbefire(:all)で用意し、 テスト実施後に用意したデータを消すつもりで書いています。

しかし消えません。

いろいろ調べた結果、:allと:eachは実行順番以外の違いがあることが分かりました。
:eachは変数の書き換えやトランザクション発行を全てそのスコープ内限定(今回だとit サインイン出来る)で利用出来るようにしています。
:eachで用意したデータは特定のitでのみ利用するいう意味合いを含むためこのような仕様になっているのかと思います。

ではなぜ用意したデータが消えないかという、after(:each)で発行したdelete_all(delete処理)が他のテストに影響しないよう、丁寧にロールバックされているためです。 :eachでのトランザクションは全てロールバックされるので、before(:each)でAccount.createすれば、特にdelete処理をする必要も無かったということで一件落着しました。