LoginSignup
15
13

More than 5 years have passed since last update.

RSpecでテストをまとめて検証する方法

Last updated at Posted at 2018-10-27

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でラップする必要がなくなる。

参考

RSpec 3.3 has been released!

15
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
13