在TDD中,我如何确保测试本身不会过时(并错误地报告SUCCESS)?

时间:2012-05-18 00:47:37

标签: unit-testing tdd

特别是我担心这种情况:

1)我写了一个包含1个成员变量和一个复制函数的类

class MyClass
{
private:
int grade;

public:
void setGrade(int x) { grade = x; }
int getGrade() { return grade; }
void copyFrom(const MyClass* src) { grade = src->grade; }
}

2)沿着这些行编写单元测试

void testCopyFrom()
{
MyClass mc1;
MyClass mc2;
mc1.setGrade(-347);
mc2.setGrade(10);
mc2.copyFrom(&mc1);
TS_ASSERT_EQUALS(mc2.getGrade(), -347);
}

3)几个月后,我添加了第二个成员变量

private:
int grade, extra;

和(你猜对了!)忘了相应地更新copyFrom()函数。

在这种情况下,单元测试将 错误地报告成功 。我在测试设计上做错了吗?

2 个答案:

答案 0 :(得分:5)

TDD意味着先测试:在更改代码之前,您应该更新代码。在这种情况下,如果您决定添加extra,则应该围绕extra添加API测试(到目前为止,您没有,但也许您需要getExtra()等。 ),然后,当您添加和修改测试时,您会注意到需要向setExtra()添加getExtra()testCopyFrom()次来电。

在这个阶段,您的测试大多会失败(红色),然后您可以执行实际代码以使它们通过(绿色),最后,清洁up和 refactor ,使用您的测试作为指导,了解您是否已经破坏了任何内容。

详细了解red-green-refactor - TDD。

此外,您应将getGrade()标记为const,即

int getGrade() const { return grade; }

这意味着您可以使用const指针或对MyClass实例的引用来获得成绩。

答案 1 :(得分:0)

在这种特殊情况下,测试错误 - 它正在执行(并报告)您设置的内容。单元测试并不关心目标的实现 - 它并不关心你是否添加了第二个属性。

选择此内容的是编写另一个在复制后检查新属性的测试。 copyFrom测试真正告诉你的是copyFrom操作在你调用它时似乎成功了 - 它不能保证复制操作的范围,因为你需要制作单独的测试。

另一种看待这种情况的方法:只是因为你调用了一个函数并且它返回而没有抛出异常,这本身并不表示成功或失败 - 它只是返回给调用者。您需要更改copyFrom以返回成功/失败指示(或在失败时抛出异常),或者您需要对目标的环境进行更多检查以确定成功或失败。