【问题标题】:Setting up a test in rspec with multiple "it" blocks在 rspec 中使用多个“it”块设置测试
【发布时间】:2011-09-03 16:09:09
【问题描述】:

假设我有一个实例方法,它可以执行许多需要测试的不同事情,例如store#process_order。我想测试它是否向客户发送电子邮件,在订单表中添加一个条目,向信用卡收费等。在 rspec 中设置它的最佳方法是什么?目前,我正在使用 rspec 和 factory girl 我做这样的事情:

describe Store do
  describe "#process_order" do
    before do
      @store = Factory(:store)
      @order = Factory(:order)
      # call the process method
      @store.process_order(@order)
    end

    it 'sends customer an email' do
      ...
    end
    it 'inserts order to db' do
      ...
    end
    it 'charges credit card' do
      ...
    end
  end
end

但感觉真的很乏味。这真的是为我需要确保做几件不同事情的方法编写规范的正确方法吗?

注意:我对这是否是好的设计的答案不感兴趣。这只是我为解决我的问题而编造的一个示例 - 如何编写这些类型的规范。

【问题讨论】:

  • 如果它做了几个不同的事情,你应该有几个不同的测试,你会这样做。 DRY 不是规则!

标签: ruby-on-rails ruby rspec tdd bdd


【解决方案1】:

这是一个很好的方法,因为如果将来发生故障,您可以确定哪个元素损坏了。我完全赞成单独测试。我倾向于不检查插入到数据库中的东西,因为你是 Rails 功能。我只是检查对象的有效性。

这也是 RSpec 书中使用的方法。如果您不确定与 RSpec 相关的任何内容,我当然建议您阅读它。

【讨论】:

    【解决方案2】:

    我认为您正在做的事情很好,我认为这是 rspec 的使用方式。关于您的应用的每条语句(规范)都有自己的块。

    您可以考虑使用before (:all) do,这样订单只需处理一次,但这可能会引入对规范运行顺序的依赖性。

    如果您愿意,您可以将 describe "#process_order" 中的所有代码合并到一个大的 it 块中,但是这样它的可读性就会降低,并且当规范失败时,rspec 会为您提供更少有用的错误消息。去把raise添加到你的一个测试中,看看如果你按照你现在的方式做,你可以从rspec得到一个很好的错误消息。

    【讨论】:

      【解决方案3】:

      如果您想测试整个过程,那么我们谈论的是集成测试,而不是单元测试。如果您想测试做几件事的#process_order method,那么我希望这些事情意味着调用其他方法。因此,我将添加#should_receive 期望并确保涵盖所有路径。然后我会分别指定所有这些方法,这样我就有了一个很好的单元规范套件。最后,我肯定会编写一个集成/验收规范来检查所有这些部分是否一起工作。

      另外,我会使用#let 来设置测试对象,从而消除规范示例之间的依赖关系(它会阻塞)。否则,其中一个示例失败可能会导致其他示例失败,从而为您提供不正确的反馈。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-25
        • 2015-12-12
        • 1970-01-01
        相关资源
        最近更新 更多