Article summary
A couple of weeks back, I was working on some RSpec tests that required a different setup and tear-down than other tests in the app. We had “database cleaner”:https://github.com/bmabey/database_cleaner providing cleanup for us to prevent test interaction, but certain tests we created needed a heavier cleanup than others. We had a simple before(:each)
and after(:each)
with the setup and tear-down, but that had to change to accommodate certain types of tests.
The Setup
We have defined RSpec metadata on certain tests that need extra attention in the setup or tear-down stages like so:
This allows us to filter (“RSpec filtering in before/after hooks”:https://www.relishapp.com/rspec/rspec-core/v/2-13/docs/hooks/filters) the tests with type :spec_type
in our spec_helper.rb file. The :spec_type
is arbitrary in this case, it could be anything (:unit
, :special_test
, :things_need_more_cleaning
, etc). In our spec_helper.rb we can now target these tests for extra work with befores and afters:
Looking back at our project, we had a few of these guys set up to provide database cleanup between tests, but they didn’t care about the test type — we had only one need fore cleanup. After introducing a couple of new test types, we had need for different cleanup methods, so we would have written this:
This example shows a general setup for any test type, but for some cases of test types it had some special hooks. In this case, the :special_type
and :fancy_type
shared the same setup and tear-down — not very DRY, huh? After a little looking, we found the RSpec around hook.
RSpec Around Hook Explained
The “around hook”:https://www.relishapp.com/rspec/rspec-core/v/2-13/docs/hooks/around-hooks allows us to DRY up the setup and tear-down of our tests. DRYing up the tests is not the only thing around()
lets us do; it also allows us to wrap our before and afters with another layer of setup/teardown. This is how we came out:
Our sample would run in this order:
# around each setup (general or special setup — dependent on the if statement)
# before each
# the actual spec
# after each
# around each tear-down (general or special tear-down — dependent on the if statement)
There are plenty of possibilities with the around, before, and after hooks, especially since they can be targeted to all tests, a suite of tests, and each test.
Thanks, but your forgot to pass the |example| variable to your around block. ;)
Ah, thanks! Sorry if that caused any confusion!