如何编写“脏”单元测试?

时间:2012-06-28 15:46:36

标签: unit-testing

我正在阅读Code Complete。在那本书中,Steve McConnell警告说“开发人员测试往往是'干净的测试'。”开发人员倾向于测试代码是否有效(干净测试),而不是测试代码中断的所有方式(脏测试)。

如何编写代码中断方式的测试?我的意思是,我可以编写错误输入的测试,并确保它被正确阻止。但除此之外,我应该考虑哪些事情?麦康奈尔在这里意味着什么?我对基本的单元测试很满意,但试图掌握它。

3 个答案:

答案 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);
    }
}

快乐路径测试只是假设所有依赖项(outputFileProviderlogValidatorlogWriter)都有效并且写入确实正在发生。但是,在此过程中可能会破坏的可能性很高,而且那些路径也应该进行测试。像:

  • outputFileProvider无法获取输出文件
  • outputFile原来无效
  • logValidator因自身异常而失败
  • logWriter无法撰写

仅举几例!单元测试不仅仅是检查快乐路径,更不用说通常就是这种情况。

答案 2 :(得分:1)

<{3}}的Elisabeth Hendrickson有一个Test Obsessed,其中列出了各种的测试方法。该文档广泛涉及测试,但“数据类型攻击”这一部分有许多具体的例子,“不愉快的路径”单元测试可以看到。

例如,以下是她关于测试路径和文件的方法的想法:

  

长名称(&gt; 255个字符)   
名称中的特殊字符(空格*?/ \ |&lt;&gt;,。()[] {};:'“!   @#$%^&amp;)
不存在已存在
无空格
最小空间
写保护
不可用
已锁定
在远程机器上损坏