繁体   English   中英

具有多个断言的RSpec单元测试

[英]RSpec unit test with multiple assertions

首先,我知道在单元测试中有多个断言是不好的做法。

但有时你需要测试一些原子事务。 作为一个简化示例,让我们来看一些具有Account类的银行应用程序:

class Account 
  attr_accessor :balance

  def transfer(to_account, amount)
    self.balance -= amount
    to_account.balance += amount
    Audit.create(message: "Transferred #{amount} from #{self.number} to #{to_account.number}."
  end

end

在这种情况下,我想一起检查3件事:

  1. 来源帐户余额按amount减少
  2. 目标帐户余额按amount增加
  3. 插入审计记录

测试@account.transfer方法的最佳方法是什么?

在这种情况下,我想一起检查3件事:

我认为你真正想要的是在某些条件下描述这些事物的行为,从而确保行为符合你的规范。 这可能意味着事情一起发生; 或者它可能意味着某些事情只发生在一组条件中而不是其他条件中,或者一个异常导致一切都回滚到其原始状态。

除了让事情变得更快之外,在一次测试中拥有所有断言是没有魔力的。 除非您面临严重的性能损失(通常在全栈测试中发生),否则每次测试使用一个断言要好得多。

RSpec可以直接提取测试设置阶段,以便为每个示例重复:

class Account 
  attr_accessor :balance

  def transfer(to_account, amount)
    self.debit!(amount)
    to_account.credit!(amount)
    Audit.create!(message: "Transferred #{amount} from #{self.number} to #{to_account.number}."
  rescue SomethingBadError
    # undo all of our hard work
  end

end

describe Account do
  context "when a transfer is made to another account" do
    let(:other_account} { other_account }
    context "and the subject account has sufficient funds" do
      subject { account_with_beaucoup_bucks }
      it "debits the subject account"
      it "credits the other account"
      it "creates an Audit entry"
    end
    context "and the subject account is overdrawn" do
      subject { overdrawn_account }
      it "does not debit the subject account"
      it "does not credit the other account"
      it "creates an Audit entry" # to show the attempted transfer failed
    end
  end
end

如果“快乐路径”中的所有三个测试都通过,则它们全部“一起发生”,因为初始系统状态在每种情况下都是相同的。

但是,您还需要确保在出现问题时不会发生任何事情,并且系统会恢复到原始状态。 有多个断言可以很容易地看到它按预期工作,并且当测试失败时,它们究竟是如何失败的。

每次测试多次断言并不总是坏习惯。 如果多个断言验证了相同的行为,那么它就没有问题。 尝试在同一测试中验证多个行为时存在问题。 当然,每次测试有多个断言存在一些风险。 其中之一是您可能会意外地从以前的测试集中保留值,这会以奇怪的方式使先前的测试无效。 此外,当一个断言为假时,所有其他断言都不会被执行,这可能会导致难以理解发生了什么。 但是要合理,你可以有多个断言断言相同的行为,最好是短行程,没有额外的设置。

在你带来的简单案例中,我会使用多个断言,因为它非常简单。 但当然它可以变得更复杂,比如负余额,不同类型的账户和东西。 那么最好使用一个(最好的)断言进行不同的测试。 我会像这样组织它:

  • 1测试当前账户的行为(最简单的情况);
  • 1到方法可以有的每个不同的路径(例外,负平衡等);
  • 1在每种可能性中测试审计;

  • 1测试当前to_account的行为(最简单的情况);

  • 1到该方法可以具有的每个不同路径。 (例外,负余额等);
  • 1在每种可能性中测试审计;

由于Audit测试非常简单,无需额外设置,因此您还可以使用Account和to_account进行测试。

暂无
暂无

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

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