【问题标题】:Dependent tests in rspecrspec 中的依赖测试
【发布时间】:2025-12-17 20:20:04
【问题描述】:

我编写功能测试,我需要做一些测试,这些测试取决于之前测试的通过情况。假设我有一个按钮,可以打开一个窗口,其中有一个函数。也就是说,为了检查这个功能,我需要首先检查按钮的正确操作(即打开窗口或没有功能)。因此,我需要这样做,如果单击按钮时测试失败,则测试未运行以检查功能窗口。单独编写测试 - 对我来说不是一种选择。我想看到这样的东西:

describe "some tests" do
  open_result = nil

  it "should check work button" do
    click_to_button()
    open_result = window_opened?
    open_result.should == true
  end

  if open_result

    describe "Check some functional" do

      it "should check first functional"

      it "should check second functional"

    end

  end

end

我知道这种方法不适用于 rspec。这只是对我想看到的内容的简单描述。使用rspec可以实现吗?如果没有,有没有其他方法(宝石等)

【问题讨论】:

  • 我认为这可能是题外话,因为有 sqa.stackexchange.com

标签: ruby testing rspec automated-tests


【解决方案1】:

RSpec 被设计为 单元测试 框架,因此从中获得完美的功能测试行为可能有点困难。在 RSpec 的哲学测试中,必须是独立的。当您使用 autotest 时,这一点尤其重要:在这种情况下,执行顺序确实是不可预测的。悲伤但真实。

当然,您可以使用全局($a 或实例(@a,此处不确定) 变量在测试之间保存一些状态。无论如何,您需要将if 移动到it 块中,以便及时执行。您可以使用pending 关键字来中断测试而不会失败,以防不满足前提条件。

但是

我确信最好的解决方案是避免golden hammer 反模式,而不是在单元测试框架中编写功能测试。您不想测试一些单独的功能。您确实想测试场景。所以我建议尝试一些场景测试套件。

看哪,Cucumber!用法很简单:

  1. 在 Ruby 中定义参数化场景步骤,在 RSpec 样式中定义期望
  2. 用自然语言编写场景(是的,不仅是英语,甚至是俄语或其他语言——正则表达式的力量就在你身边)

在您的情况下,您将在features/step_definitions/gui_steps.rb 中拥有类似

Given /I pushed a button "(.*)"/ do |name|
    @buttons.find(name).click() # This line is pseudo-code, you know
end

以及用于检查窗口打开等的类似内容(请参阅examples)。然后你可以以任何方式组合定义的步骤,例如你的两个场景可能看起来像

Scenario: Feature 1
    Given I pushed a button "go"
    And I focus on opened window
    When I trigger "feature 1"
    Then I should se "result 1" in text area

Scenario: Feature 2
    Given I pushed a button "go"
    And I focus on opened window
    When I trigger "feature 2"
    Then I should se "result 2" in text area

在这两种情况下,如果场景的某个步骤失败(例如我专注于打开的窗口 - 如果它没有打开),后续步骤不会执行 - 只是如你所愿。作为奖励,您会得到一个非常详细的输出结果,说明发生了什么以及在哪一步(参见网站上的图片)。

好消息是您并不总是需要自己定义所有步骤。例如,当您测试一个网络应用程序时,您可以使用 webrat 步骤来处理典型的事情,例如 When I go to url/a/b/cThen I should see text "foo" on页面。我不知道你用的是哪个 GUI 测试框架,但可能已经有步骤了,所以我建议你在 Cucumber %framework name% 上 google。即使没有,编写一次这些步骤也不会比尝试从 RSpec 制作 Cucumber 更困难。

【讨论】:

  • 尽管我们讨厌用“不要那样做”来回答问题,但 Cucumber 是一个更好的钉子锤。很好的解释。
  • 除了语言之外,这与将步骤编写为方法并从 vanilla rspec 测试中按顺序调用它们真的有什么不同吗?
  • @Frederick,“除了语言,”不,但语言很重要。 Rspec 是用于测试的 DSL。 Cucumber 是一种用于测试的元 DSL:它是一种 DSL,可以让您轻松编写特定于您正在测试的内容的 DSL。这似乎是一个狡辩,但它对您思考和编写测试的方式产生了巨大的影响。
  • @FrederickCheung,简而言之,与从不同 RSpec 规范调用方法相比,使用 Cucumber 的主要优点是 (1) 测试的可读性(和可写性),以及 (2) 失败消息的信息量和清晰度。那是因为 Cucumber 不仅是一个元 DSL,它背后还有一些逻辑。在你尝试之前可能看起来并不重要,但相信我,当一个人尝试它时,他不再想发明一辆已经有自行车的自行车。
  • "使用全局 ($a) 或实例 (@a..." -- 如果在示例中设置 @a,则在示例之间设置 @a 将不会被共享。但是,设置 $a 可以识别跨示例