我们听到的关于任何软件方法的口头禅是,它提高了可用性和质量,减少了开发和测试时间,并以更快的速度和更少的错误将产品推向市场。这些都是崇高的目标,但我还没有看到一种方法能带来软件开发的圣杯。
归根结底,编写单元测试的主要原因是为了证明正确性,而这只有当你写好单元测试*时才会发生。*单元测试本身不会直接提高你产品的可用性或质量。不管应用是否被证明是正确的,你仍然可以把它搞得一团糟——而且它肯定不能保证减少开发和测试时间(稍后会有更多的介绍)或者更快地将你的产品推向市场。
所以,让我们从一开始就明确和真实:单元测试可以用来验证正确性,任何与您的开发过程相关的副作用都必须与编写和维护有用的单元测试的努力相平衡。
写得好的单元测试会给你一个可测量的程度的信心,相信组成你的应用的无数方法会正确运行。客观地进行这种度量的最简单的方法是覆盖测试:应用中有多少百分比的方法编写了针对它们的单元测试?虽然这个问题没有直接说明一个方法是否应该被认为是一个单元(稍后讨论),或者测试是否有意义,但是它是一个你可以在任何时候进行的度量,可以作为你的应用正确性的基准。
单元测试是一个迭代的过程——单元测试总是会遗漏一些错误。但是,一段时间内报告的错误数量以及未解决和已解决问题的数量提供了关于应用运行状况的有意义的信息。虽然不可能说“通过单元测试,bug 的数量已经减少了 50%”,但是可以测量你的应用有多少 bug,因为单元测试覆盖不完整。当您编写单元测试来验证问题和修复时,您还可以测量与单元测试总数相比,您针对报告的错误编写了多少单元测试。
所有这些基准都给你的开发过程带来了一定程度的客观性。因此,单元测试的好处之一是,它为从开发人员到管理人员的每个人提供了客观的信息,这些信息可以反馈到开发过程中,以改进该过程。
另一个好处是可重复性,也称为回归测试。随着一个应用的成熟,我们希望确保现有的、工作的代码不被破坏。通过针对编写的方法编写单元测试,并在报告错误时添加单元测试,当添加新代码或更改现有代码时,所有这些都可以自动重新测试。当涉及到测试一个应用在一个小的或者重要的代码改变后是否仍然正确运行时,单元测试成为一个重要的时间减少工具。虽然单元测试不能取代可用性测试、性能测试、负载测试等等,但它确实有助于消除在常见问题上浪费的时间:“这在以前是有效的;为什么现在不呢?”
当一个方法中的所有进程线性执行时,很容易测试该方法是否在做正确的事情。然而,一旦您添加了一个if
语句或一个switch
语句,您就创建了圈复杂度,这是一种说您的代码现在有多个执行路径的奇特方式。最有用的单元测试是那些测试你的方法中出现的每一个代码分支的测试。编写这些类型的单元测试可能会很辛苦,但是非常值得,因为它们保证了至少每个代码分支都已经被执行,这不是验收测试、可用性测试或者质量保证部门(如果你有)执行的其他测试期间可能会发生的事情。