我正在阅读Code Complete。在那本书中,Steve McConnell警告说“开发人员测试往往是'干净的测试'。”开发人员倾向于测试代码是否有效(干净测试),而不是测试代码中断的所有方式(脏测试)。
如何编写代码中断方式的测试?我的意思是,我可以编写错误输入的测试,并确保它被正确阻止。但除此之外,我应该考虑哪些事情?麦康奈尔在这里意味着什么?我对基本的单元测试很满意,但试图掌握它。
答案 0 :(得分:6)
我认为你走在正确的道路上。测试证明代码工作会调用具有合理,有意义和预期输入的方法,程序处于正常状态。虽然打破代码的测试试图考虑关于那段代码的“开箱即用”,因此使用任何无意义或意外的输入。
恕我直言,重要的是了解两个思维过程是非常不同的。当开发人员以TDD方式编写代码时,他倾向于关注代码中要实现的各种功能,以及用于证明此功能或用例如指定工作的测试。以这种方式创建的测试是McConnell所说的“干净测试”。
考虑如何破解一段代码需要一个非常不同的思考过程和不同的经验。它需要从不同的角度查看您的方法和API,例如暂时放下你对这些方法和参数的目标的了解,并只关注技术上可行的来处理它们。还要考虑此方法正常工作所需的所有 - 通常是隐含的 - 前提条件或依赖项。它是否依赖于从DB读取的配置参数?它是否写入文件系统?它是否会调用另一个组件,期望它事先已正确初始化?它是否使用大量内存?它是否在GUI上显示消息?...如果其中一个或多个不成立,该怎么办?
所有这些都会导致一些重要问题:您的方法应如何处理此类脏案?它应该崩溃吗?抛出异常?尽可能继续?返回错误代码?记录错误报告?...所有这些小或大的决定对于正确一致地定义方法或API的合同实际上非常重要。
Kent Beck谈到在同样的意义上穿着“开发者帽子”和“测试帽”之间的转换。以这种方式流畅地切换观点和思维过程需要练习和经验。
答案 1 :(得分:1)
clean test 最有可能的作者是仅验证方法执行happy path的测试。
测试快乐路径通常是最简单的,人们可能会认为,因为它起作用,他们完成了编写测试的工作。这种情况很少发生。考虑:
public void SaveLog(string entry)
{
var outputFile = this.outputFileProvider.GetLogFile();
var isValid = this.logValidator.IsValid(outputFile);
if (isValid)
{
this.logWriter.Write(outputFile, entry);
}
}
快乐路径测试只是假设所有依赖项(outputFileProvider
,logValidator
,logWriter
)都有效并且写入确实正在发生。但是,在此过程中可能会破坏的可能性很高,而且那些路径也应该进行测试。像:
outputFileProvider
无法获取输出文件outputFile
原来无效logValidator
因自身异常而失败logWriter
无法撰写仅举几例!单元测试不仅仅是检查快乐路径,更不用说通常就是这种情况。
答案 2 :(得分:1)
例如,以下是她关于测试路径和文件的方法的想法:
长名称(> 255个字符)
名称中的特殊字符(空格*?/ \ |<>,。()[] {};:'“! @#$%^&)
不存在已存在
无空格
最小空间
写保护
不可用
已锁定
在远程机器上损坏