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| Setting.create(:name => key.to_s, :default_value => Base64.encode64(Marshal.dump(settings[key]))) 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).
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.
No problem, Slobodan. I had the exact same issue so I’m glad I could save someone else some time !
Thanks. Nice approach and gave me ideas to solve similar problem that I had.
Glad I could help !