4

具体来说,我担心这种情况:

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() 函数。

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

4

2 回答 2

5

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

在这个阶段,您的测试大多会失败(红色),然后您可以编写真正的代码以使它们通过(绿色),最后,清理和重构,使用您的测试作为您是否失败的指南任何事物。

阅读有关red-green-refactor 的更多信息——它TDD。

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

int getGrade() const { return grade; }

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

于 2012-05-18T01:14:48.537 回答
0

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

解决这个问题的是编写另一个测试来检查复制后的新属性。测试真正告诉你copyFrom的是,当你调用它时,copyFrom 操作似乎成功了——它不能保证复制操作的范围,因为你需要制作单独的测试。

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

于 2012-05-18T01:03:30.630 回答