Taking your cucumber tests back to the future with Delorean

I’m currently working on an API for Vquence’s VQdata product which allows our customers to use a REST interface to retrieve videos with certain keywords they have previously stored. While writing tests I need to be able to mock out the Time object so that my tests were deterministic relative to time.

I remembered listening to a Ruby5 podcast which mentioned a great little gem called Delorean.

Delorean easily allows you to mock time in your tests. In no time I had hooked it up to cucumber.

In features/support/delorean.rb:

require 'delorean'  
                    
# Make sure we fix the time up after each scenario
After do
  Delorean.back_to_the_present
end

and then in features/step_definitions/delorean_steps.rb

Given /^I time travel to (.+)$/ do |period|
  Delorean.time_travel_to(period)
end      

this lets me create steps like

  Scenario: Link attributes are correct for yesterday
    Given I time travel to 2010-02-01 05:00
    When I GET the videos keywords feeds page
    Then I should see "start_time=2010-02-01T00:00:00"

Some other examples you can use with Delorean are

  • 2 weeks ago
  • tomorrow
  • next tuesday 5pm

You can find more examples in the Chronic gem documentation which Delorean uses to achieve this functionality.

Adding multiple database support to Cucumber

The Vqmetrics application needs to connect to two different databases. The first holds the videos, authors and their relevant statistics, while the second database holds the users, monitors and trackers.

We do this by specifying two databases in config/database.yml.

development:
  database: vqmetrics_devel
  < <: *login_dev_local

vqdata_development: &VQDATA_TEST
  database: vqdata_devel
  <<: *login_dev_local

So by default the vqmetrics_devel database will be used. When we need to specify a model where we need to connect to the vqdata_devel database we use

class Video < ActiveRecord::Base
  establish_connection "vqdata_#{RAILS_ENV}"
end

and for migrations that need to connect to this database we do the following.

class InitialSetup < ActiveRecord::Migration
  def self.connection
    Video.connection
  end
end

This setup works really well. However recently I moved this application to using Cucumber for testing. Tests worked fine the first time they are run but not the second time.

I discovered that the transaction on the second database where not being rolled back as they should be. Cucumber only sets up the first database for roll back by using

ActiveRecord::Base.connection

where it should be rolling them all back by looping through

ActiveRecord::Base.connection_handler.connection_pools.values.map {|pool| pool.connection}

I’ve filed a bug at lighthouseapp.