Olly Legg home

Global After Blocks in RSpec; or How to Keep Timecop Happy

18 Jan 2010

I recently ran into a problem with a test suite in a Rails application which had me stumped for a while. To sum up briefly a group of test suddenly started failing. What had happened was that Timecop was being set globally and wasn't being reset. This caused problems when a couple of weeks later the tests were run and the times were different to what they were expecting. Although the final solution is very simplistic

One way to fix the test suite would have been to use Timecop's block syntax, for example:

it "should mark the sprint as in the past" do 
  Timecop.freeze(Date.today + 30) do
    sprint.should be_past
  end
end

However I'm not a great fan of this syntax in my tests, I prefer my tests to be more procedural. It also prevents you from stubbing the time in a before block for a group of tests.

The solution I settled with was to add a global after block which resets Timecop after each test. In spec/spec_helper.rb add this simple global after block:

Spec::Runner.configure do |config|
  config.after(:each) do
    Timecop.return
  end
end