| 2021-02-15
写测试时,应该是每个场景都应该在独自的测试用例中进行验证,它的好处在于:
- 逻辑更容易理解,因为在每个测试方法中需要理解的代码更少。
- 每个测试中的准备代码都比较简单,因为它只需要服务于一个场景。
- 一个场景的副作用不会意外地使后一个场景的假设失效或被覆盖。
- 如果一个测试中的一个场景失败,其他场景仍可以运行,因为它们不受失败的影响。
- 测试名称清楚地描述了每个场景,这使得理解有哪些场景更加容易。
下面就是一个不好的例子,因为你很难看出,它在测试什么场景?
TEST_F(BankAccountTest, WithdrawFromAccount) {
Transaction transaction = account_.Deposit(Usd(5));
clock_.AdvanceTime(MIN_TIME_TO_SETTLE);
account_.Settle(transaction);
EXPECT_THAT(account_.Withdraw(Usd(5)), IsOk());
EXPECT_THAT(account_.Withdraw(Usd(1)), IsRejected());
account_.SetOverdraftLimit(Usd(1));
EXPECT_THAT(account_.Withdraw(Usd(1)), IsOk());
}
事实上,它测试了三个场景,而不是一个场景。
- 我有 5 美元可以取出来
- 当透支 1 美元时,就会被拒绝
- 但是,如果我被允许透支 1 美元限额的话,我可以提取1美元。
所以,好的测试应该如下方所示,分为三个测试用例:
TEST_F(BankAccountTest, CanWithdrawWithinBalance) {
DepositAndSettle(Usd(5)); // Common setup code is extracted into a helper method.
EXPECT_THAT(account_.Withdraw(Usd(5)), IsOk());
}
TEST_F(BankAccountTest, CannotOverdraw) {
DepositAndSettle(Usd(5));
EXPECT_THAT(account_.Withdraw(Usd(6)), IsRejected());
}
TEST_F(BankAccountTest, CanOverdrawUpToOverdraftLimit) {
DepositAndSettle(Usd(5));
account_.SetOverdraftLimit(Usd(1));
EXPECT_THAT(account_.Withdraw(Usd(6)), IsOk());
}
有一个迹象能够表明您可能正在测试多个场景:
在对一个被测系统调用的输出进行断言之后,又对被测系统进行了另一个调用。
需要提示大家的是:
- 单元测试的场景通常由对被测试系统的单个调用组成。
- 集成和端到端测试用例的范围可能要大一些。
例如,Web UI在做发送电子邮件的测试时可能要打开收件箱,单击撰写按钮,编写一些文本,然后按发送按钮。
发表时间:June 11, 2018
原文作者:Ben Yu