编写系统测试时如何在before钩子中实现登录?
问题:Capybara+Selenium测试中before钩子导致多窗口会话隔离问题
问题场景
我有一个基于Ruby on Rails的应用,使用RSpec、Capybara搭配Chromium/Chrome的Selenium做测试。测试功能前需先登录,在测试用例内直接编写登录逻辑时一切正常:
it 'shows users' do visit('/') fill_in('user_username', with: 'test') fill_in('user_password', with: 'testing123') click_on('Sign In') visit('/users') expect(page).to have_text('Users') end
但因每个测试用例都需登录,我将登录逻辑移至before :each钩子后,出现异常:登录操作在单独浏览器窗口完成,最终打开两个窗口,一个已认证、一个未认证:
before :each do visit('/') fill_in('user_username', with: 'test') fill_in('user_password', with: 'testing123') click_on('Sign In') end it 'shows users' do visit('/users') expect(page).to have_text('Users') end
为排查问题,我创建了全新Rails应用简化为session存储测试,修改如下文件:
application_controller.rb
class ApplicationController < ActionController::Base after_action only: :index do session['memory'] = 'MEMORY' end def index render plain: session['memory'] || 'First try!' end end
systems_spec.rb
require 'rails_helper' RSpec.describe "Systems", type: :system do before do visit('/') end it 'visits /' do visit('/') # halt to see two browser windows open at once # debugger expect(page).to have_text('MEMORY') end end
仅安装rspec-rails未做其他修改,仍出现相同问题:打开两个浏览器窗口,均显示“First try!”。我预期测试能正常运行,是否我的写法有误?
解决方案
问题根源在于Rails系统测试的默认配置:当使用type: :system的测试时,Rails会自动在每个测试用例执行前启动一个新的浏览器会话。你在before钩子中调用visit时,会在Rails自动创建的会话之外额外初始化一个新会话,导致两个独立的浏览器窗口,会话完全隔离。
有两种可行的解决方法:
- 禁用Rails系统测试的自动会话启动
在spec/rails_helper.rb或spec/spec_helper.rb中添加配置,关闭系统测试的自动访问逻辑:
RSpec.configure do |config| config.system_testing = { driven_by: :selenium, using: :chrome, screen_size: [1400, 1400], # 关闭自动访问根路径,避免自动创建新会话 auto_run: false } end
修改后Rails不会自动启动会话,before钩子中的visit会复用同一个会话,测试用例里的操作也会在同一个窗口执行。
- 显式绑定Capybara会话实例
不要直接使用全局的visit方法,而是显式获取并绑定Capybara的当前会话,确保所有操作都在同一个会话中执行:
before :each do session = Capybara.current_session session.visit('/') session.fill_in('user_username', with: 'test') session.fill_in('user_password', with: 'testing123') session.click_on('Sign In') end
这种方法无需修改全局配置,直接通过会话实例确保所有操作共享同一个浏览器上下文。
针对你简化的测试案例:修复后两次visit会在同一个会话中执行,第二次访问时能读取到第一次设置的session值,预期的MEMORY会正常显示。
内容的提问来源于stack exchange,提问作者AmShaegar
相关产品推荐
相关产品推荐

