如何在RSpec的before/after :context钩子失败时截取屏幕截图?
解决RSpec+Capybara中before/after(:all)失败时无法自动截图的问题
问题分析
你当前的after(:each)钩子仅在单个it块执行失败时触发截图,但before(:all)/after(:all)(即context级钩子)的失败不会进入it块执行流程,因此无法触发该钩子。around(:each)也无法覆盖context级钩子的执行,因为它只包裹it块的生命周期。
解决方案
在spec_helper.rb中添加context级别的around钩子,捕获context生命周期内(包括before(:all)、after(:all))的所有异常并生成截图,同时保留原有的after(:each)钩子处理it块失败的情况:
RSpec.configure do |config| # 创建截图目录(确保目录存在,避免保存失败) screenshot_dir = Rails.root.join('tmp', 'screenshots') Dir.mkdir(screenshot_dir) unless Dir.exist?(screenshot_dir) # 处理context级钩子(before(:all)/after(:all))失败时的截图 config.around(:context, type: :feature) do |example_group| begin example_group.run rescue StandardError => e # 生成上下文失败的截图,用上下文描述作为文件名(替换空格为下划线) screenshot_name = "#{example_group.description.gsub(/\s+/, '_')}_failure.png" page.save_screenshot(File.join(screenshot_dir, screenshot_name)) raise e # 重新抛出异常,不影响测试报告的失败标记 end end # 保留原有逻辑,处理单个it块失败时的截图 config.after(:each, type: :feature) do |example| if example.exception screenshot_name = "#{example.description.gsub(/\s+/, '_')}_failure.png" page.save_screenshot(File.join(screenshot_dir, screenshot_name)) end end end
关键说明
- 限定type: :feature:仅在UI自动化测试(feature类型)中启用这些钩子,避免在model/controller等非Capybara测试中触发(这类测试没有
page对象)。 - around(:context)的作用:它会包裹整个context的执行流程,包括
before(:all)、所有it块、after(:all),因此任何阶段的失败都会被捕获并触发截图。 - 重新抛出异常:截图后重新抛出异常,确保测试报告能正常标记失败,不会掩盖问题。
- 文件名处理:将描述中的空格替换为下划线,避免文件名包含特殊字符导致保存失败。
验证效果
当你运行包含失败before(:all)的测试时,会自动生成对应上下文的截图;it块失败时仍会生成单个用例的截图,完全覆盖你需要的所有失败场景。
内容的提问来源于stack exchange,提问作者VLAD
相关产品推荐
相关产品推荐

