You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

关键说明

  1. 限定type: :feature:仅在UI自动化测试(feature类型)中启用这些钩子,避免在model/controller等非Capybara测试中触发(这类测试没有page对象)。
  2. around(:context)的作用:它会包裹整个context的执行流程,包括before(:all)、所有it块、after(:all),因此任何阶段的失败都会被捕获并触发截图。
  3. 重新抛出异常:截图后重新抛出异常,确保测试报告能正常标记失败,不会掩盖问题。
  4. 文件名处理:将描述中的空格替换为下划线,避免文件名包含特殊字符导致保存失败。

验证效果

当你运行包含失败before(:all)的测试时,会自动生成对应上下文的截图;it块失败时仍会生成单个用例的截图,完全覆盖你需要的所有失败场景。

内容的提问来源于stack exchange,提问作者VLAD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 10:08:20