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

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")
settings = YAML.load_file(yaml)
rescue Exception => e
puts "Couldn't load #{yaml} configuration file."
p e.message
p e.backtrace

settings.keys.each do |key|
Setting.create(:name => key.to_s, :default_value => Base64.encode64(Marshal.dump(settings[key])))

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).

This entry was posted in Rails, Ruby. Bookmark the permalink.

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

  1. Thanks David. Your tip helped me a lot with setting up some required database records before each step that would normally be created during install phase.

  2. david says:

    No problem, Slobodan. I had the exact same issue so I’m glad I could save someone else some time !

  3. Thanks. Nice approach and gave me ideas to solve similar problem that I had.

  4. david says:

    Glad I could help !

Comments are closed.