在Sale.c中,我们从GetTotal中返回total,并在BuyItem中更新之:
#include "Sale.h"
static int total = 0;
int GetTotal()
{
return total;
}
void BuyItem(char* barCode)
{
total = 199;
}
现在两个测试都通过了。
在每一个新的测试通过以后,我们总是暂停一下,检查代码以确保其清晰。我们看到在sellOneItem中存在字符串字面量“a123”以及魔术数字199,并且感觉代码并没有尽其可能地清晰。因为测试将会发展演化并将连同被测代码一起被维护,我们希望它们能够充当关于如何操纵Sale函数的优秀的文档。我们坚信可以良好沟通的代码远远胜过往代码里添加注释,因为注释很快就会过时。我们向测试代码里引入局部变量:
TEST(Sale, sellOneItem)
{
char* milkBarcode = "a123";
int milkPrice = 199;
BuyItem(milkBarcode);
CHECK(milkPrice == GetTotal());
}
现在我们可以继续前进并编写第三个预期失败的测试。注意已经有复用milkBarcode 和milkPrice的常量声明的需求了,因此我们将它们移出sellOneItem,并将其声明为static。
TEST(Sale, sellTwoItems)
{
BuyItem(milkBarcode);
BuyItem(milkBarcode);
CHECK(2 * milkPrice == GetTotal());
}
正如意料,它失败了:
Failure: "2 * milkPrice == GetTotal()" line 29 in SaleTest.cpp
存在一处失败。
在Sale.c中创建正确的产品代码看上去很简单。不是简单地将total设为milk的价格,我们将价格计入total:
void BuyItem(char* barCode)
{
total = total + 199;
}
我们再一次编译运行测试并预期成功。这一次有点让人惊讶,因为得到了同样的错误。
挠了挠头之后,我们怀疑static total可能没有被初始化。我们经由测试(而非调试器)来探究答案:
TEST(Sale, sellTwoItems)
{
CHECK(0 == GetTotal());
BuyItem(milkBarcode);
BuyItem(milkBarcode);
CHECK(2 * milkPrice == GetTotal());
}
哎呀,这一次我们收到了两处失败反馈。第一处失败确定了我们的怀疑:在sellTwoItems起始处,total没有被初始化:
Failure: "0 == GetTotal()" line 27 in SaleTest.cpp
Failure: "2 * milkPrice == GetTotal()" line 30 in SaleTest.cpp
我们非常喜爱TDD给予的快速反馈!
TestHarness的工作方式是每一个TEST都假定彼此独立。实际上,你无法保证测试将以任何特定的顺序进行。(这真的给我们引来了一些问题,参见)每一个测试都需要构建其自己的设置。
我们憎恶一整天的调试劳动起因于一个测试在不知情的情况下处理某个先前的测试残留的问题。然而,如果你遵从“只编写刚好够用的代码使得测试通过”的原则的话,你将被强迫加入更多的测试。通常这些附加的测试会揭露诸如此类的隐秘问题。
对于Sale例子来说,我们编写刚好够用的代码来处理一件且仅一件商品的销售问题,这将强迫我们为销售两件商品编写测试,而这暴露了我们的错误。为了修正这个问题,我们引入一个初始化函数,每一个测试 — 并且因此每一个将使用Sale的客户程序,都将必须调用它:
static char* milkBarcode = "a123";
static int milkPrice = 199;
TEST(Sale, totalNewSale)
{
Initialize();
CHECK(0 == GetTotal());
}
TEST(Sale, sellOneItem)
{
Initialize();
BuyItem(milkBarcode);
CHECK(milkPrice == GetTotal());
}
TEST(Sale, sellTwoItems)
{
Initialize();
CHECK(0 == GetTotal());
BuyItem(milkBarcode);
BuyItem(milkBarcode);
CHECK(2 * milkPrice == GetTotal());
}
在Sale.h中声明好Initialize之后,我们将其定义添加进Sale.c中:
void Initialize()
{
total = 0;
}
所有测试都从