Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upgrading capybara from 1.0.1 to 1.1.4 makes database_cleaner break my specs

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?

like image 474
HakonB Avatar asked Jan 10 '13 19:01

HakonB


3 Answers

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.

like image 172
Clemens Helm Avatar answered Nov 15 '22 18:11

Clemens Helm


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

like image 38
Jo P Avatar answered Nov 15 '22 16:11

Jo P


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')
like image 37
lobati Avatar answered Nov 15 '22 18:11

lobati