[RUBY] How to validate subsequent tests even if the test fails

Introduction

Occasionally, you may want to put multiple ʻexamples in one ʻit. If you simply add multiple ʻexamples, the subsequent test will not flow when the test fails, and ** fix the failed test → fail the subsequent test → fix the failed test ** repeatedly It is troublesome to become. In such a case, you can solve it by specifying ʻaggregate_failures.

What is aggregate_failures

See the Official Documentation (https://relishapp.com/rspec/rspec-expectations/docs/aggregating-failures) and you'll see this:

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.

That is, you can specify ʻaggregate_failures` to validate subsequent tests even if the test fails. I think it's faster to actually see the behavior, so I'd like to try it immediately.

If you don't use aggregate_failures

Let's check with the following code.

require 'spec_helper'

RSpec.describe 'hoge spec' do
  it 'To be a hoge' do
    expect(1).to eq(2)
    expect(1).to eq(3)
  end
end

When I ran the test, the result was as follows.

hoge spec
To be a hoge(FAILED - 1)

Failures:

  1)hoge spec to become 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 to become 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 to become hoge

Looking at the results, we can see that after the first ʻexpect fails, the second ʻexpect has not been validated.

When using aggregate_failures

Next, specify ʻaggregate_failures` as shown below and execute it.

require 'spec_helper'

RSpec.describe 'hoge spec' do
  it 'To be a hoge' do
    aggregate_failures do
      expect(1).to eq(2)
      expect(1).to eq(3)
    end
  end
end

The result looks like this.

hoge spec
To be a hoge(FAILED - 1)

Failures:

  1)hoge spec to become 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 to become 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 to become hoge

Apparently the first ʻexpect fails the same, but the second ʻexpect is also verified.

How to specify aggregate_failures

By now, we know that specifying ʻaggregate_failures will validate subsequent tests even if the test fails. There are several ways to specify ʻaggregate_failures, so from here we will look at how to specify each.

How to specify in block

As mentioned earlier, it is a block specification.

require 'spec_helper'

RSpec.describe 'hoge spec' do
  it 'To be a hoge' do
    aggregate_failures do
      expect(1).to eq(2)
      expect(1).to eq(3)
    end
  end
end

How to specify as meta information

The following is how to specify it as meta information for ʻit`.

require 'spec_helper'

RSpec.describe 'hoge spec' do
  it 'To be a hoge', :aggregate_failures do
    expect(1).to eq(2)
    expect(1).to eq(3)
  end
end

Bad pattern

Try specifying ʻaggregate_failures` as the first argument as shown below.

require 'spec_helper'

RSpec.describe 'hoge spec' do
  it :aggregate_failures do
    expect(1).to eq(2)
    expect(1).to eq(3)
  end
end

Click here for the results.

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

As you can see from the result, when it is specified by the first argument, the subsequent processing is not flowing, so the expected behavior is not achieved. Even if it fails, I don't think I'll check if the subsequent processing is flowing, so this is hard to notice ...

in conclusion

We have seen the behavior of ʻaggregate_failures and some ways to specify it. Personally, I think it's okay because the method of specifying with blocks seems to be addictive. If you want to include multiple ʻexamples, specify ʻaggregate_failures`.

Recommended Posts

How to validate subsequent tests even if the test fails
Is there an instance even if the constructor fails?
How to mock some methods of the class under test
[Rails carrier wave] How to not transition to the error screen even if the image upload is not selected
How to use the link_to method
How to use the include? method
How to unit test Spring AOP
How to use the form_with method
How to find the average angle
How to use the wrapper class
How to add the delete function
[RSpec] How to write test code
[Java] How to use the File class
How to delete the wrong migration file
[Java] How to use the hasNext function
How to put out the error bundling
[Java] How to use the HashMap class
How to delete the migration file NO FILE
[Rails] How to use the map method
Studying how to use the constructor (java)
[Processing × Java] How to use the loop
How to determine the number of parallels
[Java] How to set the Date time to 00:00:00
[Java] How to get the current directory
[Swift] How to implement the countdown function
How to change the timezone on Ubuntu
Ransack sort_link How to change the color!
[Processing × Java] How to use the class
How to sort the List of SelectItem
I was addicted to the Spring-Batch test
How to install the legacy version [Java]
How to find the tens and ones
How to pass the value to another screen
How to get the date in java
[Processing × Java] How to use the function
How to test private scope with JUnit
[Java] How to use the Calendar class
Summarized how to climb the programming stairs
How to write an RSpec controller test
[SpringBoot] How to write a controller test
If you want to satisfy the test coverage of private methods in JUnit
[Ruby] Learn how to use odd? Even? And count the even and odd numbers in the array!
If the parameter is an array, how to include it in Stopara's params.permit
How to resolve the "OpenSSH keys only supported if ED25519 is available" error
How to resolve errors that occur in the "Ruby on Rails" integration test