Browsers and Transactions

Mischa Molhoek edited this page Jul 16, 2015 · 21 revisions

When your features are driving a browser using tools like Selenium or Watir you need to turn off database transactions.

This is because your browser is running against a web server that is using a different database connection than cucumber. This is because they run in separate processes. Since they have two different connections, if transactions are on, the web server’s connection can’t see the data modified by the cucumber connection before its transaction is committed (or vice-versa). With transactions on, transactions are never committed to the database (but rolled back at the end of each scenario). Therefore, the web server’s connection will never see data from cucumber, and therefore your browser won’t either. Likewise, cucumber’s connection won’t see data from the web server.

(This paragraph is outdated. You must implement this behaviour manually: https://groups.google.com/forum/#!topic/cukes/Euv9NT4E8hs)
If you’re using Ruby on Rails it’s easy to turn off transactions for a feature or particular scenarios. Just use the @no-txn tag, e.g.

@no-txn
Feature: Lots of scenarios with transactions off.

or

Feature: ...
  @no-txn
  Scenario: One scenario with transactions off.

With Rails you can also turn off transaction globally in your features/support/env.rb:

Cucumber::Rails::World.use_transactional_fixtures = false

Cleaning Your Database

(This paragraph is outdated. If you use @no-txn with Rails you now get the behavior described below out of the box. Details in the Cucumber Rails source)

Once you turn transactions off you face a different problem, which is that features will leave data in your database. If you’re using Ruby on Rails, a good tool to deal with this is Ben Mabey’s Database Cleaner gem which you can install with gem install bmabey-database_cleaner --source http://gems.github.com/. (Or just gem install database_cleaner if you are using gemcutter.) You can use this very effectively with the @no-txn tag. Something like the following somewhere in e.g. features/support/db_cleaner.rb should work well:

require 'database_cleaner'
DatabaseCleaner.clean_with :truncation # clean once to ensure clean slate
DatabaseCleaner.strategy = :truncation

Before('@no-txn') do
  DatabaseCleaner.start
end

After('@no-txn') do
  DatabaseCleaner.clean
end

If you’re not using Rails you can recreate the entire @no-txn bevhaviour using DatabaseCleaner with the following code:

# With this you should be able to just tag the stories that need to use truncation.
# Otherwise, the transaction strategy will be used all the other times.
 
require 'database_cleaner'
DatabaseCleaner.clean_with :truncation # clean once to ensure clean slate
DatabaseCleaner.strategy = :transaction # use transactions by default
 
Before('@no-txn') do
  DatabaseCleaner.strategy = :truncation
end
 
Before do
  DatabaseCleaner.start
end
 
After do
  DatabaseCleaner.clean
end
 
After('@no-txn') do
  DatabaseCleaner.strategy = :transaction
end