Rails项目中Chromedriver无法通过测试数据库用户登录问题求助
Rails 5.0.x 系统测试登录失败问题排查
核心问题
正在为2017年的Rails项目(Rails 5.0.x)编写RSpec系统测试,依赖Capybara、FactoryBot和Devise:
- 使用Chromedriver运行带
:js => true的测试时,用户登录失败,Chrome浏览器弹出Bootstrap的“凭据错误”提示框 - 通过
binding.pry确认测试数据库中存在该用户,且凭据正确 - 移除
:js => true(不使用JS驱动)时,登录完全正常
现有配置信息
Rails Helper 配置
Capybara.register_driver :selenium_chrome do |app| Capybara::Selenium::Driver.new(app, browser: :chrome) end Capybara.default_driver = :selenium_chrome Capybara.javascript_driver = :selenium_chrome
Application.rb 配置
require 'webdrivers/chromedriver' Webdrivers::Chromedriver.required_version = "114.0.5735.90"
Test.log 关键日志
Completed 401 Unauthorized in 9ms (ActiveRecord: 2.4ms) Processing by Devise::SessionsController#new as HTML Parameters: {"utf8"=>"✓", "fan"=>{"email"=>"test1@example.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"}
Gem 依赖
gem 'rails', '>= 5.0.1.rc2', '< 5.1' group :development, :test do gem 'byebug', platform: :mri gem 'rspec-rails', '~> 3.5.0' gem 'puma', '~> 3.0' end group :test do gem 'capybara', '~> 3.6.0' gem 'factory_girl_rails', '~> 4.7' gem 'faker' gem 'selenium-webdriver', '~> 3.6.0' gem "database_cleaner", "~> 1.5" gem 'shoulda-matchers', '~> 3.1' gem 'launchy' end
尝试其他驱动的问题
改用geckodriver时,出现以下错误:
Failures: 1) Splash and devise: Fans in Canada can sign in, visit signed in home page, and log out in Failure/Error: click_link('LOG IN') Selenium::WebDriver::Error::UnknownError: Invalid Content-Type
后续排查与新问题
线程共享连接方案
发现测试存在3个互不通信的线程,添加共享数据库连接的代码后,登录测试生效:
class ActiveRecord::Base mattr_accessor :shared_connection @@shared_connection = nil def self.connection @@shared_connection || retrieve_connection end end # Forces all threads to share the same connection. This works on # Capybara because it starts the web server in a thread. ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
事务Fixtures配置冲突
按照相关建议将use_transactional_fixtures设为true并停用database_cleaner时,触发错误:
An error occurred in a `before(:suite)` hook. Failure/Error: raise(<<-MSG) Delete line `config.use_transactional_fixtures = true` from rails_helper.rb (or set it to false) to prevent uncommitted transactions being used in JavaScript-dependent specs. During testing, the app-under-test that the browser driver connects to uses a different database connection to the database connection used by the spec. The app's database connection would not be able to access uncommitted transaction data setup over the spec's database connection. MSG
当前完整配置
Rails Helper 完整配置
# This file is copied to spec/ when you run 'rails generate rspec:install' ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../../config/environment', __FILE__) # Prevent database truncation if the environment is production abort("The Rails environment is running in production mode!") if Rails.env.production? require 'spec_helper' require 'rspec/rails' # Add additional requires below this line. Rails is not loaded until this point! require "devise" require "pundit/rspec" require 'capybara/rails' Dir[Rails.root.join('spec/support/*.rb')].each { |f| require f } # If you are not using ActiveRecord, you can remove this line. ActiveRecord::Migration.maintain_test_schema! Capybara.register_driver :selenium_chrome do |app| Capybara::Selenium::Driver.new(app, browser: :chrome) end Capybara.default_driver = :selenium_chrome Capybara.javascript_driver = :selenium_chrome Capybara.run_server = true class ActiveRecord::Base mattr_accessor :shared_connection @@shared_connection = nil def self.connection @@shared_connection || retrieve_connection end end # Forces all threads to share the same connection. This works on # Capybara because it starts the web server in a thread. ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection RSpec.configure do |config| config.include Devise::Test::ControllerHelpers, type: :controller # controller spec macros config.extend ControllerMacros, :type => :controller # Include Factory Girl syntax to simplify calls to factories config.include FactoryGirl::Syntax::Methods # 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! config.include Rails.application.routes.url_helpers # 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") config.include Warden::Test::Helpers, type: :feature config.after(type: :feature) { Warden.test_reset! } config.include Capybara::DSL config.filter_run_when_matching focus: true end Shoulda::Matchers.configure do |config| config.integrate do |with| with.test_framework :rspec with.library :rails end end
Application.rb 完整配置
require 'webdrivers/chromedriver' Webdrivers::Chromedriver.required_version = "114.0.5735.90"
当前状态
- 目前仅在gem列表中声明了database_cleaner,未找到其他相关配置,但测试数据库始终只有一个FactoryBot创建的用户,推测database_cleaner已在生效
- 已在第一个系统测试场景上花费10多天,希望确认当前配置是否可行,以便继续推进测试编写
内容的提问来源于stack exchange,提问作者daveasdf
相关产品推荐
相关产品推荐

