Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
12
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

@yshz

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

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!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
12
Help us understand the problem. What are the problem?