简体   繁体   English

RSpec:始终在开始/救援中执行before(:all)

[英]RSpec: Always execute before(:all) in begin/rescue

I'm writing Selenium tests, using Watir-Webdriver and RSpec, which can be a bit spotty when they're first being developed. 我正在使用Watir-Webdriver和RSpec编写Selenium测试,当它们最初被开发时,它们可能有点参差不齐。 I've run into a situation where I want to create something on the UI in before :all, however it can throw exceptions (based on timing or poor loading). 我遇到了一种情况,我想在:all之前在UI上创建某些内容,但是它可能会引发异常(基于时间或加载不良)。 When that happens I want to take a screenshot. 发生这种情况时,我想截图。

Here's what I have: 这是我所拥有的:

 RSpec.configure do |config|
   config.before(:all) do |group| #ExampleGroup
     @browser = Watir::Browser.new $BROWSER

     begin
       yield #Fails on yield, there is no block
     rescue StandardError => e
       Utilities.create_screenshot(@browser)
       raise(e)
     end
   end
 end

I run it and get an error: 我运行它并得到一个错误:

LocalJumpError: no block given (yield) LocalJumpError:未提供任何块(产量)

The reason I assumed yielding would work is RSpec's definition of before: 我认为屈服的原因是RSpec之前的定义:

def before(*args, &block)
  hooks.register :append, :before, *args, &block
end

How can I wrap the code I've put in my before :all in a begin/rescue block without having to do it on every suite? 我该如何包装之前放入的代码before :all包装在begin / rescue块中,而不必在每个套件中都这样做?

Thanks in advanced. 提前致谢。

The code you've written in the before hook is the &block you're referring to in RSpec::Hooks#before . 您在before钩子中编写的代码是在RSpec::Hooks#before引用的&block。 The hook yields to your code, then runs your tests after the yield is complete. 挂钩将屈服于您的代码,然后在屈服完成后运行测试。

As for how to make this work, I think this should do: 至于如何进行这项工作,我认为应该这样做:

RSpec.configure do |config|
  # ensures tests are run in order
  config.order = 'defined'

  # initiates Watir::Browser before all tests
  config.before(:all) do
    @browser = Watir::Browser.new $BROWSER
  end

  # executes Utilities.create_screenshot if an exception is raised by RSpec 
  # and the test is tagged with the :first metadata
  config.around(:each) do |example|
    example.run
    Utilities.create_screenshot(@browser) if example.exception && example.metadata[:first]
  end
end

This configuration requires the first test be tagged with metadata: 此配置要求使用元数据标记第一个测试:

describe Thing, :first do
  it "does something" do
    # ...
  end
end

This way, you'll only take a screenshot at the beginning of your run for a failing test, and not after every failing test. 这样,您只需要在运行开始时为失败的测试截屏,而不是在每次失败的测试后截屏。 If you'd rather not mess with metadata (or prefer your tests are run in random order), you could do something like this: 如果您不想弄乱元数据(或者更喜欢按随机顺序运行测试),则可以执行以下操作:

RSpec.configure do |config|
  # initiates Watir::Browser before all tests
  config.before(:all) do
    @test_count = 0
    @browser = Watir::Browser.new $BROWSER
  end

  # executes Utilities.create_screenshot if an exception is raised by RSpec 
  # and the test is the first to run
  config.around(:each) do |example|
    @test_count += 1
    example.run
    Utilities.create_screenshot(@browser) if example.exception && @test_count == 1
  end
end

This works for me. 这对我有用。 Instead of begin/rescue in the before :all hook, 而不是before :all钩子before :all begin/rescue

config.after :each do
  example_exceptions = []
  RSpec.world.example_groups.each do |example_group|
    example_group.examples.each do |example|
      example_exceptions << !example.exception.nil?
      end
    end
  has_exceptions = example_exceptions.any? {|exception| exception}
  #Handle if anything has exceptions
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM