複数のアサーションを使用したRSPECユニットテスト
-
21-12-2019 - |
質問
まず私はそれが単位テストに複数の主張を持つことが悪い練習であることを知っています。
しかし時々あなたはいくつかの原子的取引をテストする必要があります。簡略化された例として、アカウントクラスを持ついくつかの銀行アプリケーションを取り上げましょう。
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つのことを一緒にチェックしたい:
- 原料アカウント残高は
amount
によって減少しました
- 宛先口座残高は
amount
の増加
- 監査レコードが挿入されています
@account.transfer
メソッドをテストする最善の方法は何ですか?
解決
この状況では、3つのことをまとめたいと思います。
あなたが本当に望むことは、特定の条件下でこれらのことの動作を説明することであると主張したいと思います。したがって、行動があなたの仕様を満たすことを確実にします。それは物事が一緒に起こることを意味するかもしれません。あるいは、ある一連の条件で、他の条件でのみ起こるだけで、または例外が元の状態にロールバックされることを意味するのは何らかの意味があります。
物事をより速くする以外は、あるテストにすべてのアサーションを持つ魔法はありません。 あなたが深刻なパフォーマンスペナルティに直面していない限り(フルスタックテストで頻繁に起こるように)、テストごとに1つのアサーションを使用することははるかに良いです。
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
.
「幸せな道」の3つのテストがすべて渡された場合、それらはすべて初期のシステム状態がそれぞれ同じであるため、すべて「まとめて」。
しかし、何かがうまくいかないときにが起こらないこと、そしてシステムが元の状態に戻ることを確実にする必要があります。複数のアサーションを持つことで、これが予想どおりに機能し、テストが失敗したときに、閉じてが失敗した
他のヒント
テストごとの複数のアサーションは必ずしも悪い練習ではありません。複数のアサートが同じ動作を検証した場合、問題はありません。同じテストで複数の動作を検証しようとすると問題が発生します。 もちろん、テストごとに複数のアサートを持つリスクがいくつかあります。そのうちの1つは、前のテストセットから誤って、前のテストを知っている方法で値を変更することがあります。 また、1つのアサートが偽の場合、左のすべての左端は実行されません。これは何が起こるのかを理解することが困難になります。しかし合理的なことで、あなたは同じ行動、好ましくは短いもの、そして追加のセットアップなしで複数のアサートを持つことができます。
あなたが持ってきた単純なケースでは、それはとてもシンプルなので私は複数のアサートを使うでしょう。しかしもちろん、否定的なバランス、さまざまな種類の口座やもののように、もっと複雑になることがあります。それから、1つの(優先的に)アサートで異なるテストを使用することをお勧めします。私はそれがこのように整理するでしょう:
- 1現在のアカウントの動作をテストする(最も簡単な場合)
- 1の異なるパスからメソッドが持つことができます(例外、マイナス バランス等);
-
1これらすべての可能性の監査をテストする
-
1現在のto_accountの動作をテストする(最も簡単な場合)。
- 1の異なるパスからメソッドが持つことができます。 (例外、否定的です バランス等);
- 1これらの可能性すべての監査をテストする
監査テストはかなり簡単で、追加設定が不要なので、アカウントやto_accountと一緒にテストすることもできます。