I have an old Rails application upgraded to version 3.2.11 that has a lot of request specifications written using capybara version 1.0.1 and running using the selenium driver. The database are cleaned after each test using database_cleaner using the truncation strategy.
I want to use poltergeist instead of selenium and upgraded capybara from 1.0.1 to 1.1.4 to be able to use the latest version of poltergeist. Only changing the capybara gem (and its dependencies) introduced problems running my specs.
I consistently get deadlock errors from my Postgresql database in the cleanup handler after each spec. My spec_helper is pretty basic and looks like this:
RSpec.configure do |config|
config.mock_with :rspec
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
The error I get is like this:
An error occurred in an after hook
ActiveRecord::StatementInvalid: PG::Error: ERROR: deadlock detected
DETAIL: Process 41747 waits for AccessExclusiveLock on relation 17612 of database 16396; blocked by process 41752.
Process 41752 waits for RowExclusiveLock on relation 17529 of database 16396; blocked by process 41747.
HINT: See server log for query details.
: ALTER TABLE "aaa" ENABLE TRIGGER ALL;ALTER TABLE "bbbb" ENABLE TRIGGER ALL;ALTER TABLE "ccc" ENABLE TRIGGER ALL;
occurred at /xxx/.bundle/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter.rb:652:in `async_exec'
I use FactoryGirl to create test data but otherwise nothing special IMO.
I haven't been able to figure out what holds the other end of deadlock that is created by database_cleaner. Any ideas to figure that out are most welcome.
Anybody know of any changes between capybara 1.0.1 and 1.1.4 that has changed and may have started to cause these issues?
I got around this issue in cucumber by placing
sleep 0.2
at the end of the step (or in your case "spec") that does some AJAX stuff. I imagine what happens is that cucumber/rspec calls database cleaner while the JS driver is still waiting for the ajax response.
The fix isn't to use sleep
but to only use Capybara API methods as they wait for what's expected.
Below, line 2 fails (as current_path
is non-waiting, but line 3 works (as has_selector?
waits). The link to Jonas Nicklas' article below explains it well.
click_on 'signup_button' # Which does an AJAX redirect to /dashboard
assert_equal dashboard_path, current_path # This causes the deadlock error as Capybara doesn't wait.
assert page.has_selector?("#dashboard") # This works as it causes Capybara to wait for the new page.
http://www.elabs.se/blog/53-why-wait_until-was-removed-from-capybara
The solution we use is to find something in the page that should change in response to a successful ajax call. So something like:
click_on('Save')
expect(page).to have_content('Saved')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With