Initializing the test database before a Cucumber session (in Rails)

Posted on August 7, 2011

In one of my side projects, I needed some setup data to be present in the test database before each Cucumber session. Since this took me a few moments to get right, I figured I’d document it here.

The goal

Cucumber will (quite naturally) start each scenario with a known database state: usually an empty database with a defined schema. That is quite annoying when your application relies on information stored in the database (e.g. application settings) to function properly.

To be clear, I’m talking about settings that will be loaded during the application “installation” phase (e.g. via a Rake task), not settings that users can set to determine their profile preferences (or similar).

Loading data before the Cucumber session

We’ll create a hook to load the data. Cucumber provides a set of hooks related to the Cucumber lifecycle (such as Before, After, AfterStep, AfterConfiguration). Since all we need to do is to run a bunch of code at the start of a Cucumber session (as opposed to running said code before/after each scenario), we don’t really need to use a Cucumber hook, but I’ll do so anyway in the interest of conveying meaning.

Cucumber will load all files conforming to the features/**/*.rb glob, so the hook code could technically be put anywhere, but for the sake of maintainability, we’ll put it in features/support/hooks.rb.

  
  
    AfterConfiguration do
  # use a run-once hook to initialize test database with settings
  yaml = File.join(Rails.root, "/config/settings.yml")
  begin
    settings = YAML.load_file(yaml)
  rescue Exception => e
    puts "Couldn't load #{yaml} configuration file."
    p e.message
    p e.backtrace
    exit
  end
 
  settings.keys.each do |key|
    default_val = Base64.encode64(Marshal.dump(settings[key]))
    Setting.create(:name => key.to_s, :default_value => default_val)
  end
end
  
  

As you can tell, what we do is quite straightforward: we simply load the application settings and put them in the database.

Preventing destruction across scenarios

Since the default DatabaseCleaner strategy configured in features/support/env.rb is transaction, the settings stored in the database will persist across tests. But if you wanted to use the truncation strategy instead, you can ensure the settings table is kept by specifying

  
  
    
    DatabaseCleaner.strategy = :truncation, {:except => %w[settings]}
  
    
  

in features/support/env.rb (you’ll have to replace the setting that is already there).


Would you like to see more Elixir content like this? Sign up to my mailing list so I can gauge how much interest there is in this type of content.