[英]deadlock detected with capybara-webkit
我試圖通過這個規范:
scenario "Edit a service", js: true do
service = create_service_for(provider, title: "First service")
fill_edit_service_form(service)
expect(page).to have_css('#price', text: '10,00 $')
end
這是使用水豚的標准導軌規格。 我使用capybara-webkit用於javascript的所有場景。 當我試圖傳遞它時,有時候它會起作用,有時它標記的數據庫中有一條丟失的記錄,有時我有這個錯誤:
Run options: include {:locations=>{"./spec/acceptances/provider_services_spec.rb"=>[31]}}
[K 1) Provider Services Edit a service
Failure/Error: Unable to find matching line from backtrace
ActiveRecord::StatementInvalid:
PG::TRDeadlockDetected: ERROR: deadlock detected
DETAIL: Process 24164 waits for AccessExclusiveLock on relation 3446991 of database 3446538; blocked by process 24184.
Process 24184 waits for AccessShareLock on relation 3446902 of database 3446538; blocked by process 24164.
HINT: See server log for query details.
: ALTER TABLE "active_admin_comments" DISABLE TRIGGER ALL;ALTER TABLE "provider_service_territory_provideds" DISABLE TRIGGER ALL;ALTER TABLE "provider_services" DISABLE TRIGGER ALL;ALTER TABLE "provider_divisions" DISABLE TRIGGER ALL;ALTER TABLE "provider_profiles" DISABLE TRIGGER ALL;ALTER TABLE "provider_service_intervention_level_provideds" DISABLE TRIGGER ALL;ALTER TABLE "provider_service_medium_provideds" DISABLE TRIGGER ALL;ALTER TABLE "provider_service_service_provideds" DISABLE TRIGGER ALL;ALTER TABLE "regions" DISABLE TRIGGER ALL;ALTER TABLE "service_formulas" DISABLE TRIGGER ALL;ALTER TABLE "region_translations" DISABLE TRIGGER ALL;ALTER TABLE "artists" DISABLE TRIGGER ALL;ALTER TABLE "admin_users" DISABLE TRIGGER ALL;ALTER TABLE "schema_migrations" DISABLE TRIGGER ALL;ALTER TABLE "services" DISABLE TRIGGER ALL;ALTER TABLE "services_provided" DISABLE TRIGGER ALL;ALTER TABLE "territories_provided" DISABLE TRIGGER ALL;ALTER TABLE "users" DISABLE TRIGGER ALL;ALTER TABLE "countries" DISABLE TRIGGER ALL;ALTER TABLE "coupons" DISABLE TRIGGER ALL;ALTER TABLE "currencies" DISABLE TRIGGER ALL;ALTER TABLE "formulas" DISABLE TRIGGER ALL;ALTER TABLE "collector_profiles" DISABLE TRIGGER ALL;ALTER TABLE "country_translations" DISABLE TRIGGER ALL;ALTER TABLE "images" DISABLE TRIGGER ALL;ALTER TABLE "intervention_levels_provided" DISABLE TRIGGER ALL;ALTER TABLE "measure_units" DISABLE TRIGGER ALL;ALTER TABLE "media_provided" DISABLE TRIGGER ALL;ALTER TABLE "messages" DISABLE TRIGGER ALL;ALTER TABLE "page_part_translations" DISABLE TRIGGER ALL;ALTER TABLE "orders" DISABLE TRIGGER ALL;ALTER TABLE "painting_categories" DISABLE TRIGGER ALL;ALTER TABLE "page_services" DISABLE TRIGGER ALL;ALTER TABLE "page_translations" DISABLE TRIGGER ALL;ALTER TABLE "painting_category_translations" DISABLE TRIGGER ALL;ALTER TABLE "page_parts" DISABLE TRIGGER ALL;ALTER TABLE "pages" DISABLE TRIGGER ALL;ALTER TABLE "painting_provenances" DISABLE TRIGGER ALL;ALTER TABLE "painting_prices" DISABLE TRIGGER ALL;ALTER TABLE "painting_technic_translations" DISABLE TRIGGER ALL;ALTER TABLE "painting_technics" DISABLE TRIGGER ALL;ALTER TABLE "painting_type_translations" DISABLE TRIGGER ALL;ALTER TABLE "period_translations" DISABLE TRIGGER ALL;ALTER TABLE "painting_types" DISABLE TRIGGER ALL;ALTER TABLE "paintings" DISABLE TRIGGER ALL;ALTER TABLE "periods" DISABLE TRIGGER ALL
# -e:1:in `<main>'
1/1 |========================= 100 ==========================>| Time: 00:00:03
Finished in 3.41 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/acceptances/provider_services_spec.rb:29 # Provider Services Edit a service
Screenshot: /home/dougui/rails/lescollectionneurs/tmp/capybara/screenshot_2014-02-20-18-22-55.658.png
Randomized with seed 34053
我在桌子上鎖了。 這並不總是相同的表。
當我這樣做時,它會更好:
Capybara.reset_sessions!
DatabaseCleaner.clean
規范之前和之后但並不總是有效。 如果我在同一個文件中運行所有規范,我就無法工作。
它在我處理不相關的事情時附加。 它與惡作劇者合作。
這是我的spec_helper文件:
ENV["RAILS_ENV"] ||= 'test'
require 'rubygems'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/rails'
require 'capybara-webkit'
require 'database_cleaner'
require 'capybara/firebug'
require 'capybara-screenshot/rspec'
if defined?(Spring)
Spring.watch "#{Rails.root}/spec/factories"
else
require 'shoulda-matchers'
end
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.infer_base_class_for_anonymous_controllers = false
config.use_transactional_fixtures = false
config.order = "random"
config.include FactoryGirl::Syntax::Methods
config.include Warden::Test::Helpers, type: :feature
config.include FeatureHelpers, type: :feature
config.include Devise::TestHelpers, type: :controller
config.include ControllerHelpers, type: :controller
config.include EmailSpec::Helpers
config.include EmailSpec::Matchers
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
if example.metadata[:js]
DatabaseCleaner.strategy = :truncation
else
DatabaseCleaner.start
end
end
config.after(:each) do
DatabaseCleaner.clean
DatabaseCleaner.strategy = :transaction if example.metadata[:js]
end
end
Capybara.javascript_driver = :webkit
include ActionDispatch::TestProcess
I18n.locale = :fr
Geocoder.configure(:lookup => :test)
Geocoder::Lookup::Test.set_default_stub(
[
{
'latitude' => 40.7143528,
'longitude' => -74.0059731,
'address' => 'New York, NY, USA',
'state' => 'New York',
'state_code' => 'NY',
'country' => 'United States',
'country_code' => 'US'
}
]
)
以下是使用的gem: https : //github.com/GCorbel/lescollectionneursassocies/blob/master/Gemfile 。
有什么建議?
有關更多詳細信息,請查看Github回購: https : //github.com/GCorbel/lescollectionneursassocies/ 。
發生這種情況是因為您有兩個線程,即測試和請求,異步修改數據庫。 看起來你正確地在spec_helper中嘗試了不同的配置。 我花了相當多的時間來解決同樣的問題,並提出了這個問題:
# adapted from https://gist.github.com/moonfly/4950750
require 'database_cleaner'
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.before( :suite ) do
DatabaseCleaner.clean_with :truncation
DatabaseCleaner.strategy = :transaction
end
config.around( :each ) do |spec|
if spec.metadata[:js]
# JS => doesn't share connections => can't use transactions
spec.run
DatabaseCleaner.clean_with :deletion
else
# No JS/Devise => run with Rack::Test => transactions are ok
DatabaseCleaner.start
spec.run
DatabaseCleaner.clean
# see https://github.com/bmabey/database_cleaner/issues/99
begin
ActiveRecord::Base.connection.send :rollback_transaction_records, true
rescue
end
end
end
end
我把它全部保存在support / database_cleaner_configuration.rb中,這對你也有用,或者你可以簡單地替換spec_helper中的內容。 如果這不起作用,請告訴我 - 我還有一些其他的想法,但它們更怪異,如果有效的話,不值得進入,它可能會......
注意:
值得一提的是,Rails 5.1+解決了數據庫問題。 Rails團隊的Eileen Uchitelle進行了必要的更改以運行確保測試線程,並且Rails服務器可以通過共享數據庫連接在同一進程中運行。
當有兩個運行測試的線程時,您會遇到死鎖。 例如,在終端中打開一個選項卡,然后使用rspec
命令運行測試。 立即打開終端中的第二個選項卡,並使用相同的命令在那里運行測試。
所以,我猜你只是在一個選項卡中運行所有測試,並嘗試在其他選項卡中使用rspec spec/acceptances/provider_services_spec.rb:31
命令運行特定測試。
最可能的原因是必須通過ajax / database clean進行一些查詢,在sql查詢運行時過早地截斷數據庫。 其中一種方法是使webkit驅動程序等待,直到ajax請求完成。 在測試助手中添加此方法,並在單擊按鈕/提交ajax表單后調用它。
def wait_for_ajax_to_finish
looping = true
loop do
sleep 1
begin
count = page.evaluate_script('window.running_ajax_calls').to_i
looping = false if count == 0
rescue => e
if e.message.include? 'HTMLunitCorejsJavascript::Undefined'
raise "For 'wait for the AJAX call to finish' to work, please include culerity.js after including jQuery."
else
raise e
end
end
end
end
我有不同的測試隨機失敗(比如500個中的1個測試,每次我運行套件)。
這可能不是最漂亮的解決方案,但我通過在2秒后救援並重試數據庫清理器來解決問題,如下所示:
config.after(:each) do |example|
begin
DatabaseCleaner.clean
rescue Exception => e
# Recover from thread locks and retry the database clean after a slight delay
sleep 2
DatabaseCleaner.clean
end
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.