Why small 'it's are bad
I recently was tasked with optimizing a very slow test suite. While looking at it, I noticed that we had a lot of small it
blocks that had very slow before
blocks running before them.
Instead of running each it
block separately with the entire setup each time, a clever solution was provided by TestProf through their RuboCop
cops. They encourage using one of RSpec’s excellent features – the aggregation of failures within a single example. This approach permits grouping independent assertions together, running all setup hooks only once and considerably boosting test suite performance by reducing the total number of examples.
This change required only a minor alteration to our .rubocop.yml
file to enable the RuboCop
cops:
# .rubocop.yml
require:
- 'test_prof/rubocop'
One of the cops provided by TestProf is RSpec/AggregateExamples
. Here’s an example of how to modify your tests to take advantage of it:
# before
it { is_expected.to be_success }
it { is_expected.to have_header("X-TOTAL-PAGES", 10) }
it { is_expected.to have_header("X-NEXT-PAGE", 2) }
its(:status) { is_expected.to eq(200) }
# after
it "returns the second page", :aggregate_failures do
is_expected.to be_success
is_expected.to have_header("X-TOTAL-PAGES", 10)
is_expected.to have_header("X-NEXT-PAGE", 2)
expect(subject.status).to eq(200)
end
Notice that we now have just a single it
block with multiple assertions. This allows the setup (the before
blocks) to run only once for this group of assertions, rather than once per assertion, dramatically speeding up our test suite.
Also, TestProf’s RuboCop
cops come with an auto-correct feature, which can make these adjustments automatically!
For more details on this and other cops provided by TestProf, you can check out their documentation. Happy testing!
Sources:
That's it for this post, thanks for reading!