簡體   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