Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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!

yshz
Rails, React
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした