Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 在TDD中,如何确保测试本身不';不要过时(并且错误地报告成功)?_Unit Testing_Tdd - Fatal编程技术网

Unit testing 在TDD中,如何确保测试本身不';不要过时(并且错误地报告成功)?

Unit testing 在TDD中,如何确保测试本身不';不要过时(并且错误地报告成功)?,unit-testing,tdd,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(

我特别担心这种情况:

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


在这种情况下,单元测试将错误地报告成功。我的测试设计有没有做错什么

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

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


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

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

在这个阶段,您的测试大多会失败(红色),然后您可以执行真正的代码使它们通过(绿色),最后,清理并重构,使用您的测试作为指导,判断您是否有任何问题

了解更多信息-这是TDD

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

int getGrade() const { return grade; }

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

因此,实际上这意味着引入新变量“extra”可能会影响该类周围以前编写的所有测试。@Wartin:是的,不应该吗?但实际上,您应该从测试中驱动一些东西,而测试是由API驱动的;如果你添加了一个变量,但你永远无法测量该变量的效果,那么测试就不可能也不应该被它伪造。目前没有
getExtra()
,而且
extra
对类中的任何内容都没有影响,因此@slugster建议,现在的测试非常好。一般来说,是的:随着类的增长,它的测试将需要适应新的条件。我认为在这种情况下,您真正想要测试的是复制的对象与原始对象相等。这可能建议对equals()进行测试(当然,这取决于语言),当类发生更改时,这将是一个更自然的地方。我的草案解决方案是再添加一个测试,以验证自上次以来结构/类的数据大小没有更改。如果已更改(即添加/删除/更改类型的成员变量),则需要检查整个测试套件。更新:我的草案解决方案不起作用,因为由于数据对齐,结构的大小可能大于其成员大小之和。