capybara-webkit js: настоящие тесты rspec не могут взаимодействовать с базой данных

Я использовал RSpec в сочетании с Capybara и Capybara-webkit во многих проектах Rails, и обычно это работает гладко. По какой-то причине у меня возникли проблемы с настройкой спецификаций функций 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

Когда я изменяю это, тесты могут правильно взаимодействовать с БД:

config.before(:each, js: true) do
  ActiveRecord::Base.establish_connection
  DatabaseCleaner.strategy = :truncation
end

Почему? Мне не нужно было явно указывать ему, чтобы установить соединение с БД.


person John Hess    schedule 23.04.2017    source источник
comment
Какая версия рейлов?   -  person Thomas Walpole    schedule 24.04.2017


Ответы (2)


В вашем вопросе говорится, что вы используете: транзакцию для своих тестов js, но код показывает: усечение. Усечение — это то, что вы должны использовать для своих тестов js, поэтому я предполагаю, что вопрос — опечатка.

Вы должны использовать рекомендуемый database_cleaner — https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example — определяет, требуется ли усечение на основе используемого драйвера, а не метаданных «js: true», а также использует append_after, а не только after, что очень важно для теста. стабильность.

Я также не вижу require 'capybara/rails' нигде в ваших rails_helper или spec_helper

person Thomas Walpole    schedule 24.04.2017
comment
Большое спасибо, фрагмент из документов сработал, я должен был увидеть его раньше. Спасибо, что указали мне правильное направление, это имеет смысл. И да, :transaction была опечаткой, которую я исправил - person John Hess; 24.04.2017

Когда вы устанавливаете js: true, вы, по сути, просто используете Capybara, которая по сути является запросом браузера, управляемым Selenium. Любой код, работающий вне тестового процесса (например, этот запрос браузера Selenium), не видит фикстуру базы данных.

Однако предпочтительнее, чем то, что вы делаете, — делиться состоянием данных на веб-сервере Selenium и тестировать сам код.

Где-то в Rspec.config (возможно, в вашем database_cleaner.rb) вы захотите установить

config.use_transactional_fixtures = false

В «Ежедневном тестировании Rails с Rspec» есть хитрость, которая иногда требовалась для определенных тестовых сценариев, когда вам нужно совместно использовать одно и то же соединение с БД до 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
person codelitt    schedule 23.04.2017
comment
Я использую webkit в качестве драйвера, а не Selenium. У меня также есть config.use_transactional_fixtures = false в моем rails_helper.rb. Эта настройка работала нормально в прошлом без дополнительного кода для создания общего подключения. - person John Hess; 24.04.2017
comment
До Rails 5.1 подключение к общей базе данных могло приводить к зависаниям, которые трудно отлаживать, когда вы начинаете добавлять в приложение такие вещи, как ActionCable, или если вы выполняете проверки БД в тестах функций (плохая идея, но многие люди так делают). В Rails 5.1 добавлена ​​блокировка пула соединений в тестовом режиме, которая безопасно разделяет одно соединение. - person Thomas Walpole; 24.04.2017
comment
@JohnHess Я пропустил, что у тебя была эта линия, но похоже, ты понял это. - person codelitt; 24.04.2017