Home > Software design >  Rspec Capybara Failure/Error: DatabaseCleaner.clean
Rspec Capybara Failure/Error: DatabaseCleaner.clean

Time:05-14

I am using rails 6.1.4 (Ubuntu 20.04) and am running tests with rspec, factorybot, and capybara. I also got database_cleaner where I'm using :truncation to start each test block with a clean slate (yes, not the fastest way but the most rigorous way). When I run rspec spec (applies to individual models too), I got one table where I randomly get a bunch of failing tests saying

Failure/Error: DatabaseCleaner.clean
     
     ActiveRecord::Deadlocked:
       PG::TRDeadlockDetected: ERROR:  deadlock detected
       DETAIL:  Process 105987 waits for AccessExclusiveLock on relation 1876018 of database 1876015; blocked by process 105996.
       Process 105996 waits for AccessShareLock on relation 1876043 of database 1876015; blocked by process 105987.
       HINT:  See server log for query details.
     # ./spec/support/database_cleaner.rb:32:in `block (2 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # PG::TRDeadlockDetected:
     #   ERROR:  deadlock detected
     #   DETAIL:  Process 105987 waits for AccessExclusiveLock on relation 1876018 of database 1876015; blocked by process 105996.
     #   Process 105996 waits for AccessShareLock on relation 1876043 of database 1876015; blocked by process 105987.
     #   HINT:  See server log for query details.
     #   ./spec/support/database_cleaner.rb:32:in `block (2 levels) in <top (required)>'

It is truly random where the tests start failing, i.e. I can run the same test commands consecutively and different tests will pass / fail.

in ./spec/support/database_cleaner.rb [I cut out the comments]

    RSpec.configure do |config|
      config.before(:suite) { DatabaseCleaner.clean_with(:truncation) }
    
      config.before(:each) { DatabaseCleaner.strategy = :truncation }
    
      config.before(:each, js: true) { DatabaseCleaner.strategy = :truncation }
    
      config.before(:each) { DatabaseCleaner.start }
      config.after(:each) do
[this is row 32:]        DatabaseCleaner.clean
        rescue NoMethodError => e # See: https://github.com/DatabaseCleaner/database_cleaner-sequel/issues/4
        next puts("Warning: catch #{e.message}") if e.message == %(undefined method `rollback' for nil:NilClass (DB Cleaner gem))
          raise e
      end
    end

Sometimes, after a while, all tests may work also. Does anyone have a sense for what's causing this issue? Thank you!

CodePudding user response:

Give some time to the database cleaner to do its job ! A dummy way of solving the issue is by using the sleep method like so: sleep(1), at the begining of each "it" block. Should do the job ✅

What's hapenning is that database cleaner doesn't have the time to clean your PSQL DB thqt you are already trying to recreate the same instance you used in the previous test.

  • Related