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