Ruby RSpec-嵌套的before:all和before:each块如何交互?

Ruby RSpec-嵌套的before:all和before:each块如何交互?,ruby,rspec,Ruby,Rspec,我在使用RSpec和Selenium/Capybara/SitePrism实现一些Web用户界面自动化时遇到了一个问题。它与代码中出现的before:all和before:each子句的组合有关,尤其是在我的spec\u helper文件中 到目前为止,我一直在一次针对一个规范文件运行rspec。每个等级库文件都需要一个spec\u helper文件,其中包括以下内容: spec_helper.rb: RSpec.configure do |config| config.before

我在使用RSpec和Selenium/Capybara/SitePrism实现一些Web用户界面自动化时遇到了一个问题。它与代码中出现的
before:all
before:each
子句的组合有关,尤其是在我的
spec\u helper
文件中

到目前为止,我一直在一次针对一个规范文件运行rspec。每个等级库文件都需要一个
spec\u helper
文件,其中包括以下内容:

spec_helper.rb:
  RSpec.configure do |config|
    config.before(:all) do
      # 1) Code to configure WebDriver and launch Browser is here
    end
  end
test_a_spec.rb:
  describe "Page A" do
    before :all do
      # 2) Log in to web site, maybe load the test page in question
    end
    it "does this thing" do
      # 3) Test this thing
    end
    it "does that thing" do
      # 4) Test that thing
    end
  end
由于各种原因,等级库文件本身在块之前包含自己的
。其中大多数包含以下内容:

spec_helper.rb:
  RSpec.configure do |config|
    config.before(:all) do
      # 1) Code to configure WebDriver and launch Browser is here
    end
  end
test_a_spec.rb:
  describe "Page A" do
    before :all do
      # 2) Log in to web site, maybe load the test page in question
    end
    it "does this thing" do
      # 3) Test this thing
    end
    it "does that thing" do
      # 4) Test that thing
    end
  end
只要我对单个规范文件运行RSpec,这就可以正常工作。当我尝试标记一些示例,然后运行整个spec文件夹时,我遇到了一个问题。
spec\u helper.rb
中的
before:all
块并没有像我想的那样在每个文件前加前缀,而是在开始时运行一次。第一次之后的所有规范文件都希望
spec\u helper
启动一个干净的浏览器,并自己进行部分登录,但是浏览器不干净,已经登录,所以这不是很好

spec\u helper.rb
中的
before:all
更改为
before:each
似乎是自然的解决方案,我这样做了,突然我的测试立即失败,错误称
机架测试需要机架应用程序,但没有提供任何
。这发生在我的一些测试中,但不是全部,通过消除过程,我意识到只有测试之前有自己的
:所有的
块都失败了。spec文件中的
before:all
似乎取代了
spec\u帮助文件中的
before:each
。因此,它试图在启动浏览器之前登录

这让我很烦恼。我非常恼火。我假设了两件事:

  • 我假设
    before:each
    before:all
    处于同等地位,事实上,从某种意义上说,它就像一个
    before:all
    加上更多。在我看来,
    before:all
    将取代
    before:each
    的想法很奇怪

  • 我假设所有这些
    之前的
    块都以合理的方式嵌套。也就是说,一个
    before:all
    块应该在它下面的所有东西之前触发一次,这意味着在
    before:each
    块的每次迭代中触发可能包含
    before:all
    块的每个
    块。此外,如果
    before:each
    包含一些代码,然后下面的描述语句在
    before:all
    之前有一个
    before:each
    代码,则
    before:each
    代码仍应在
    before:all
    代码之前触发。也许它真的做到了,我只是现在不确定

问题:

1) 我的
spec\u helper
文件实际产生了什么样的行为?例如,如果我采取同样的行为,并将其放入某个规范文件本身,那会是什么样子?
before:each
和浏览器启动代码是否会以某种隐式
描述
块的形式围绕spec文件中的所有代码?
before:each
是否插入到最外层的descripe块中,因此必须与spec文件的
before:all
块竞争

2) 我可以通过放弃以前所有的
:我测试中的所有
块来“解决”这个问题,但我喜欢事情的灵活性,因为这是UI自动化,速度是一个因素,我真的不想打开一个新的浏览器并为每个描述登录,尽管我知道这将是保持每个测试与其他测试分离的理想方法。我必须/想这样做吗


谢谢

要解决问题中尚未涉及的部分,如中所述,
require
方法不会重新加载以前加载的任何文件。这与
load
方法形成对比,该方法在使用文件内容的任何地方都像“复制/粘贴”一样

我并不是说,如果您将所有的
requires
更改为
loads
,您将获得与运行单个文件相同的结果,因为可能存在其他全局状态影响您看到的行为。

RSpec文档()提供了一些关于before块如何交互以及它们的运行顺序的非常有用的信息,但是它们建议避免before(:context)[aka before(:all)]


仅供参考,请注意后块的运行顺序与前块的运行顺序相反。

我觉得处理
require
vs
load
可能不是正确的选择,我也不确定它是否会改变行为。我原以为
spec\u helper
对不同的spec文件的作用会有所不同,但显然没有。
spec\u helper
中的配置显然将应用于
rspec
认为是运行一部分的示例和示例组,而不管它们位于哪个文件中。谢谢,我同意更改为
load
可能不是正确的选择,而且可能不会改变任何东西。其他答案是否不足以解决您的其他问题?简言之,您可以在配置中使用
before(:suite)
进行“每次RSpec调用一次”操作,在配置中使用“before(:all)`进行“每次顶级示例一次”示例操作。这些操作不会“竞争”“在示例级别调用前使用
;它们是相互补充的。我得出的结论是,最好只使用
before:each
,避免
before:all
,就像它是魔鬼一样。我相信我在写这个问题时产生困惑的主要原因与
spe的方式有关