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 providing cleanup for us to prevent test interaction, but certain tests we created needed a heavier cleanup than others. We had a simple
after(:each) with the setup and tear-down, but that had to change to accommodate certain types of tests.
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) the tests with type
:spec_type in our spec_helper.rb file. The
:spec_type is arbitrary in this case, it could be anything (
: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
: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 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.