我在许多Rails项目中将RSpec与Capybara和Capybara-webkit结合使用,它通常运行顺畅。出于某种原因,我在配置js: true
功能规范时遇到了问题。他们没有正确地与数据库交互。我使用factory_girl
和database_cleaner
来管理测试数据库内容。对于DatabaseCleaner.strategy = :truncation
测试,我在database_cleaner.rb
中有js: true
但它仍然不起作用。奇怪的是,当我将ActiveRecord::Base.establish_connection
放入databse_cleaner.rb
时,测试工作正常。为什么?
以下是rails_helper.rb
:
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if
Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
ActiveRecord::Migration.maintain_test_schema!
Capybara::Webkit.configure(&:block_unknown_urls)
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = false
config.infer_spec_type_from_file_location!
# Filter lines from Rails gems in backtraces.
config.filter_rails_from_backtrace!
# arbitrary gems may also be filtered via:
# config.filter_gems_from_backtrace("gem name")
end
这是spec_helper.rb
的重要部分:
ENV['RAILS_ENV'] ||= 'test'
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup'
Bundler.require
require 'pry-byebug'
require 'capybara/rspec'
require 'capybara/webkit'
require 'database_cleaner'
require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)
# use `describe 'Feature', type: :feature, js: true` to use this driver
Capybara.javascript_driver = :webkit
# tests use regular (faster) driver if they don't require js
Capybara.default_driver = :rack_test
Capybara::Webkit.configure do |config|
config.allow_unknown_urls
end
RSpec.configure do |config|
config.after(:suite) do
FileUtils.rm_rf(Dir["#{Rails.root}/spec/test_files/"])
end
config.include Capybara::DSL
...
这是database_cleaner.rb
(位于spec/support
):
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, js: true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
当我更改它时,测试可以正确地与db交互:
config.before(:each, js: true) do
ActiveRecord::Base.establish_connection
DatabaseCleaner.strategy = :truncation
end
为什么呢?我不应该明确告诉它建立数据库连接。
答案 0 :(得分:1)
您的问题表明您正在使用:js测试的事务,但代码显示:截断。截断是你应该用于你的js测试,所以我认为问题是一个错字。
您应该使用推荐的database_cleaner - https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example - 它根据所使用的驱动程序而不是'js:true'元数据检测是否需要截断,并且还使用append_after
而不仅仅after
{1}},这对测试稳定性非常重要。
我也没有在你的rails_helper或spec_helper中看到require 'capybara/rails'
答案 1 :(得分:0)
当您设置js: true
时,您基本上只使用Capybara,这实际上是Selenium驱动的浏览器请求。在测试过程之外运行的任何代码(如此Selenium浏览器请求)都看不到数据库夹具。
除了您正在做的事情之外,最好是在Selenium Web服务器上共享数据状态并测试代码本身。
在Rspec.config中的某个地方(可能是你的database_cleaner.rb),你要设置
config.use_transactional_fixtures = false
"使用Rspec"进行日常Rails测试有一些技巧有时需要在某些测试场景中需要在Rails 5之前共享相同的数据库连接。虽然它可能导致其他问题,如下面的评论中所指出的那样:
制作 spec / support / shared_db_connection.rb 文件并添加此内容:
class ActiveRecord::Base
mattr_accessor :shared_connection
@@shared_connection = nil
def self.connection
@@shared_connection || retrieve_connection
end
end
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection