我们正在尝试使用TDD来创建我们的系统,而且我们已经找到了能够找出正确的TDD行动方案的情况。
我们已将文件IO隐藏在接口之后,如下所示:
public interface IFileIo
{
byte[] Read(string fileName);
void Write(string filename, byte[] data);
}
现在我们正在创建一个InMemoryFileIo
,我们可以用它来代替我们用于制作的真实SystemFileIo
类。
我们希望确保此InMemoryFileIo
正常工作,并且可能存在我们想要使用它来代替实际文件系统的情况,因此它应该是&#34;生产质量&#34;。< / p>
问题是,按照TDD方式执行所有操作&#34;,我们如何为.Read()
或.Write()
创建测试,他们不依赖于每个.Read()
或.Write()
其他
为了测试.Write()
是否正常工作,我们首先需要成功调用.Read()
,同样地,测试.Read()
是否正常工作,我们需要之后致电.Write()
。通过这样做,我们实际上创建了两次相同的测试(排列,然后写入,然后读取,然后断言)。
假设我们有两个测试,一个测试put
,另一个测试get
。如果这些功能中的任何一个不起作用,那么两个测试都会失败。这违反了&#34;测试应该只有一个失败的理由&#34;
此处的示例适用于文件IO,但在使用数据库时我们遇到了同样的问题(测试(index) Width Height Scale Name
0 640 360 1 "SD"
1 1080 720 2 "HD"
2 1920 1080 3 "FHD"
没有struct Resolution
{
int Width;
int Height;
int Scale;
std::string Name;
};
)。
答案 0 :(得分:2)
整个问题归结为你如何定义你的&#34;单位&#34;。就我个人而言,有必要考虑一个&#34;单位&#34;作为一个连贯的行为集而不是单个方法调用。
Roy Osherove将单位定义为:
单元测试是一段自动化的代码,它调用系统中的一个工作单元,然后检查有关该工作单元行为的单一假设。工作单元是系统中的单个逻辑功能用例,可以由某个公共接口调用(在大多数情况下)。工作单元可以跨越单个方法,整个类或多个类一起工作,以实现可以验证的单个逻辑目的。
所以最后,抛开所有指导方针,如果分开阅读/写作责任没有意义,只需要组合测试它们。一般来说,当我觉得没有干净/简单的方法可以通过后门验证测试结果时(无论是可以嘲笑的合作者,还是一些状态验证,......),我可以毫无问题地进行一些操作。公共API的其他功能。这些通过公共API运行组件的测试往往不如使用后门进行验证的那些脆弱。