| 2022-04-26
单元测试仍然在开发人员和产品经理之间引起争议。这种测试既有反对者也有支持者。在本文中,我将重点介绍单元测试的主要优点。
什么是单元测试,为什么单元测试很重要,以及它们如何帮助开发人员和企业主?有关这些问题的答案以及更多信息,请继续阅读。
让我们从定义开始:单元测试是一种软件测试方法,其中“单元”——软件的各个组件——被测试。开发人员为他们的代码编写单元测试以确保代码正常工作。这有助于在未来检测和防止错误。
有时开发人员会先编写单元测试,然后再编写代码。这种方法也称为测试驱动开发 (TDD)。在 TDD 中,将需求转化为特定的测试用例,然后改进软件以通过新的测试。在这种方法中,不会添加未被证明满足定义要求的代码。单元测试是类似的,因为它允许开发人员修改代码而不影响其他单元或整个产品的功能。
单元测试通常以函数的形式编写,并检查这些函数在各种场景中的值和行为。例如,让我们想象一个用于两个数字相除的函数:开发人员决定采用 TDD 方法,首先编写一个输入值“4”和“2”(4 除以 2)的测试,预期为“2”作为结果。另一个例子:当除数为零时,我们不期望函数会产生一个值——我们期望它会产生一个异常。我们可以预期该函数将通知某些组件尝试除以零。因此,我们测试两种情况:
- 在无效情况下,该函数会通知我们我们做错了什么(异常情况)
- 该功能将识别这种无效情况并记录它
另请阅读:如何管理产品开发生命周期的三个层面
单元测试的八个优点
一些开发人员低估了编写单元测试的重要性。以下是单元测试的五个好处,您在形成自己的观点之前可能需要考虑这些好处。
任何错误都可以轻松快速地找到
包含测试的代码比没有测试的代码更可靠。如果未来的更改破坏了代码中的某些内容,开发人员将能够立即确定问题的根源,而不是通过笨拙的代码库来查找问题。
最佳实践建议开发人员首先在本地运行所有单元测试或一组测试,以确保任何编码更改不会破坏现有代码。但是,请考虑人为因素:开发人员可能会在进行更改后忘记运行单元测试,并将可能无法工作的代码提交到公共分支。为避免这种情况,许多公司采用持续开发方法。为此使用了持续集成工具,允许开发人员自动运行单元测试。因此,代码中任何不需要的更改都将被冷的逻辑机器检测到。
检测非工作代码的速度取决于用于持续集成的工具。测试可以设置为以特定时间间隔运行一次性检查,也可以立即实时运行以查看更改。
简而言之,单元测试帮助开发人员立即发现问题,然后快速修复它们。由于发现错误所花费的资源更少,团队可以进入项目的下一阶段。
另请阅读: 自上而下集成测试策略的 7 个步骤
单元测试节省时间和金钱
在他的《代码完成》一书中,Steve McConnell 分享了一张表格,其中包含错误以及在产品生命周期的不同阶段修复错误的成本。该表显示,越早检测到缺陷,其纠正成本就越低。
在编写单元测试时,在软件构建阶段会发现许多 bug,这会阻止这些 bug 转移到以下阶段,包括产品发布之后。这节省了在开发生命周期后期修复错误的成本,也为最终用户带来了好处,他们不必处理有错误的产品。此外,您将从改进的测试时间估计中受益匪浅,节省大量时间和资源。
单元测试是极限编程不可或缺的一部分
单元测试是极限编程方法论的先决条件。极限编程本质上是一种“测试所有可能破坏的东西”的策略。使用这种方法编写单元测试使开发和代码重构更简单,集成更容易,并创建活文档。这将我们带到了下一点……
单元测试提供文档
单元测试是产品的一种活文档。要了解一个模块或另一个模块提供了哪些功能,开发人员可以参考单元测试来了解模块和整个系统的逻辑的基本情况。单元测试用例表示携带有关软件组件的适当或不适当使用的信息的指标。因此,这些案例为这些指标提供了完美的文档。
R2:可重用和可靠
在单元测试环境中,产品的各个模块彼此隔离,并有自己的职责范围。这意味着代码更可靠——它已经在封闭环境中进行了测试——因此是可重用的。可重用代码对所有人来说都是双赢的:它干净、高效且一致。所有这些都通过单元测试加速。
单元测试有助于衡量性能
如果您能够在软件投入生产之前找出可能的软件中断点并且用户自己发现它们,那不是很神奇吗?单元测试可以提供这样的机会,并且可以防止为寻找不存在的问题的解决方案而进行不必要的努力。例如,如果您处理散列列表,您可能需要检查如果列表增长,它将如何执行。增长速度未知。从这里你可能会做的是应用单元测试来尝试不同概率水平的场景——从非常可能到荒谬。如果您已经确定散列列表中的项目数在任何情况下都不会超过 10,000,那么在 100,000 处您就已经准备就绪并且可以停止。你已经证明你的软件能力已经足够好了,不需要再花更多的时间去测试了。
单元测试提高了代码覆盖率
好的,所以软件单元测试很棒,但是需要多少测试覆盖率?美国软件工程师 Robert C. Martin,也被称为 Uncle Bob,认为测试覆盖率的目标应该是覆盖 100% 的代码。开发人员对这个问题的看法不同:一些人支持完整的代码覆盖策略,而另一些人则认为这种做法是多余的——这个话题对于本文的目的来说太冗长了。无论如何,在编写单元测试时,您可以使用许多工具来确定项目、单独模块或功能的覆盖率的总百分比。这些工具还能够以图形方式显示测试涵盖的代码部分,并指示代码中最适合编写单元测试的部分。
在活动代码编写阶段了解是否会执行特定行或者您是否可以轻松删除它是非常有用的。如果您有有效的单元测试,您可以立即获得覆盖率指标,并确定代码行是否相关。如果不是,请考虑通过另外一项测试来扩展您的代码覆盖率。如果您的测试套件已经考虑了所有可能的场景,请消除不必要的代码。然而,需要更多测试是圈复杂度增加的标志。
单元测试降低代码复杂度
圈复杂度是一种定量度量,您可以使用它来准确了解程序及其代码的复杂程度。单个代码块中隐含的路径越多,复杂度就越高。即,当源代码中没有控制流语句时,复杂度为1,而使用“if”语句时,复杂度逐渐上升到2或更高。可以想象,这就是实现完美的单元测试覆盖成为一项艰巨任务的地方。代码的条件语句越多,代码块就越复杂。
一旦创建单元测试变得繁琐,它表明代码也可能过于复杂。 但是如果没有单元测试客观地回答你的代码是否有效的问题,你所拥有的只是你自己的假设。有了单元测试,你就有了具体的证据。
质量软件中的单元测试结果
上面列出的所有因素都是相互关联的,这意味着单元测试无疑有助于改进您的软件。单元测试一开始可能看起来是一个乏味的过程,但从长远来看,它的好处是显而易见的。单元测试确保所有代码在部署之前都符合质量标准。这确保了质量至上的可靠工程环境。在产品开发生命周期的整个过程中,单元测试可以节省时间和金钱,并帮助开发人员更高效地编写更好的代码。
参考文章: