4

对于消息传递应用程序,我们有一些相当长的集成测试。现在,要运行给定场景,必须按特定顺序执行 20 或 30 个步骤,因为步骤 N 依赖于步骤 N-1 期间创建的数据。

因此,它们目前被组织在一个“它……做”的例子下:

describe WidgetController do
  describe "long opt-in opt-out scenario" do
    it "can complete the full sequence" do
      # create an account factory with trait account_type
      # create manager factory for the account
      # 5 people factories opt-in to that account
      # 1 person then opts out
      # a manager creates and sends a broadcast
      # the one opt-out does not get the message
      # the four opt-ins get the message
      # verify the format of the message

每个步骤都有一个或两个断言来验证该步骤做了正确的事情。因此,目前我们在一个it...do示例中有 40 多个断言,这完全掩盖了实际测试的内容。

我们可以在每个步骤中插入一条puts语句来将描述推送到输出,但是如果我们的 N 步骤可以像 N rspec 示例一样处理肯定会更好。

有没有办法将 N 个顺序集成测试步骤组织为 N 个单独it...do的示例,以便 (a) 它们按顺序运行,并且 (b) 在步骤之间保持状态,以及 (c)(理想情况下)允许我们继续使用随机种子顺序我们运行的其他测试?

4

2 回答 2

0

我会将测试与准备测试分开以使其更清洁。这意味着在您的示例中,这是一项长期测试:

  # create an account factory with trait account_type
  # create manager factory for the account
  # 5 people factories opt-in to that account
  # 1 person then opts out
  # a manager creates and sends a broadcast
  --> no asserts until now, because that is test preparation

您可以将其放入before(:all)然后进行单独的测试:

 before(:all) do
     # no asserts here, just the steps to do it
     # create an account factory with trait account_type
     # create manager factory for the account
     # 5 people factories opt-in to that account
     # 1 person then opts out
     # a manager creates and sends a broadcast

     # so in the end you got:
     @people = ...
     @manager = ...
     @opt-ins = ...
     @opt-out = ...
     @broadcast = ...
 end

 it "should not send the message to the opt-out" do
     # the one opt-out does not get the message
 end

 it "should send the message to the four opt-ins" do
     # the four opt-ins get the message
 end

 it "should have the right message format" do
     # verify the format of the message
 end

此外,您还应该测试before(:all)单独测试中的步骤:

it "should be able to create an account with account_type" do
     # create an account factory with trait account_type
     # assert it worked
end

it "should be able to create a manager for an account" do
     # create an account factory with trait account_type
     # no assertion that it worked (that is tested before)

     # create manager factory for the account
     # assert manager got correctly created
end

it "should be able to opt-in to accounts" do
     # create an account factory with trait account_type
     # no assertion that it worked (that is tested before)

     # 5 people factories opt-in to that account
     # assert that it worked
end

it "should be able to opt-in to accounts" do
     # create an account factory with trait account_type
     # 5 people factories opt-in to that account

     # 1 person then opts out
     # assert that it worked
end

有一个小的代码重复,但这使测试更简单,更清晰易读,这就是我要这样做的原因。

最后,要组织您的测试,请使用shared_context. 因此,如果您需要在不同的测试/文件中准备相同的东西,请将它们包含为shared_context

# spec/contexts/big_message_broadcast.rb
shared_context "big message broadcast" do
    before(:all) do
         # no asserts here, just the steps to do it
         # create an account factory with trait account_type
         # create manager factory for the account
         # 5 people factories opt-in to that account
         # 1 person then opts out
         # a manager creates and sends a broadcast

         # so in the end you got:
         @people = ...
         @manager = ...
         @opt-ins = ...
         @opt-out = ...
         @broadcast = ...
     end
end

# spec/.../some_spec.rb
describe "long opt-in opt-out scenario" do
     include_context 'big message broadcast'
     it "should not send the message to the opt-out" do
         ...
     end
     ...
end

这样你就可以简单地使用include_context 'big message broadcast'它来准备任何你喜欢的地方。

于 2014-12-27T12:04:56.270 回答
0

您可能想尝试使用Capybara Test Helpers,这是一个封装和模块化集成测试的库。

通过将不同的步骤封装到单独的测试辅助方法中并给它们起描述性的名称,测试应该变得更容易阅读

另一个优点是,一旦您将流程拆分为不同的方法,您只需启用它即可获得增量输出。

输出

于 2020-11-30T22:19:57.837 回答