2013-01-10 16 views
8

Ho una vecchia applicazione Rails aggiornata alla versione 3.2.11 che ha un sacco di specifiche richieste scritte usando capybara versione 1.0.1 e in esecuzione usando il driver selenio . Il database viene pulito dopo ogni test utilizzando database_cleaner utilizzando la strategia di troncamento.Aggiornamento capibara da 1.0.1 a 1.1.4 rende database_cleaner rompere le mie specifiche

Desidero utilizzare poltergeist anziché selenio e capybara aggiornato da 1.0.1 a 1.1.4 per poter utilizzare l'ultima versione di poltergeist. Solo cambiando la gemma di capibara (e le sue dipendenze) ho introdotto problemi nell'esecuzione delle mie specifiche.

Ricevo costantemente errori di deadlock dal database Postgresql nel gestore di cleanup dopo ogni specifica. Il mio spec_helper è piuttosto semplice e si presenta così:

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 

L'errore che ottengo è come questo:

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' 

Io uso factorygirl per creare dati di test, ma altrimenti niente di speciale IMO.

Non sono stato in grado di capire cosa contiene l'altra estremità del deadlock creata da database_cleaner. Qualsiasi idea per capirlo è molto gradita.

Qualcuno sa di eventuali cambiamenti tra capybara 1.0.1 e 1.1.4 che è cambiato e potrebbe aver iniziato a causare questi problemi?

+0

io in realtà espe ced l'opposto. Durante i miei test, ho avuto dei blocchi permanenti che si verificavano a intermittenza fino all'aggiornamento a capybara 1.1.4 da 1.1.2. Spiacente, il mio commento non è più utile. =/ –

+0

Beh, sono contento di non essere l'unico a sperimentare problemi di deadlock :-) Semplicemente non riesco a capire perché due thread alla volta stiano accedendo alle tabelle allo stesso tempo. DatabaseClean dovrebbe funzionare solo dopo che i test effettivi sono stati completati ... – HakonB

+0

Oh anche, questa potrebbe essere una domanda stupida, ma hai provato ad aggiornare il tuo gem di DatabaseCleaner? Inoltre, FWIW, penso che per noi gli errori si siano verificati solo dopo aver iniziato a usare delayed_job (anche se abbiamo disattivato i test). –

risposta

5

ho avuto questo problema in cetriolo mettendo

sleep 0.2 

alla fine del passo (o nel suo caso "spec"), che fa alcune cose AJAX. Immagino che quello che succede sia che cetriolo/rspec chiami il pulitore del database mentre il driver JS sta ancora aspettando la risposta ajax.

+0

ha funzionato per me. Sembra strano che non ci siano più persone che stanno incontrando questo. –

+0

Ha funzionato anche per me. C'è una soluzione reale in vista? – morgler

+0

Questo funziona, ma rallenta il test inutilmente e a volte può fallire. La correzione consiste nel mettere una chiamata all'API Capybara (come has_content?) Alla fine del test. Ho elaborato la risposta qui sotto. –

5

La correzione non deve utilizzare sleep ma utilizzare solo i metodi API Capybara in attesa di ciò che è previsto.

Qui di seguito, la linea 2 non riesce (come current_path è non-attesa, ma la linea 3 opere (come has_selector? attese). Il link per l'articolo Jonas Nicklas' sotto lo spiega bene.

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

+0

Sono abbastanza sicuro che funziona solo in Capybara 2. Lo hai provato in Capybara <2? –

1

la soluzione che utilizziamo è di trovare qualcosa nella pagina che dovrebbe cambiare in risposta a una chiamata AJAX successo Quindi, qualcosa di simile a:.

click_on('Save') 
expect(page).to have_content('Saved')