特别是我担心这种情况:
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()函数。
在这种情况下,单元测试将 错误地报告成功 。我在测试设计上做错了吗?
答案 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
以返回成功/失败指示(或在失败时抛出异常),或者您需要对目标的环境进行更多检查以确定成功或失败。