单元测试:最佳实践 测试什么 为什么需要单元测试 模块化和依赖性 测试结构 何时不需要单元测试

2025-05-24

单元测试:最佳实践

测试什么

为什么需要单元测试

模块化和依赖性

测试结构

当不需要单元测试 

这篇文章最初发表在我的博客smartpuffin.com上。

我已经对我的代码进行单元测试很多年了。

在构建 GIS 系统,我们非常注重产品质量。用户的需求决定了应用的正常运行。我对所有关键和/或复杂的代码部分进行了 100% 的测试,涵盖了多种路径和极端情况。能够发现错误、修复错误,并为这种意外情况编写几个测试,并确保它不会再次崩溃,这真是太令人欣慰了。啊,美好的时光。

这是我多年来积累的最佳实践的集合。请注意:我假设你已经熟悉单元测试的概念。

测试什么

当然,你的资源有限。当然,测试所有东西需要耗费大量的时间。当然,你需要向项目经理解释单元测试及其好处,并与他们协商。这就是为什么你需要确定优先级。

确定优先顺序的最佳方法是考虑业务需求。

对于一些开发人员来说,这听起来可能有些奇怪。你可能会想:测试就是代码,与业务无关。

事实上,所有代码都与业务有关。最终,你编写代码是为了解决用户的问题,这就是业务需求。

但我跑题了。比如说,你还没考试,但你真的想开始。太棒了!

找出系统中最关键的部分。是客户的购买体验?是用户使用的工具?是数据流?还是复杂的数学计算?

确定这个地方,然后从那里开始。由于它是系统中最重要的部分,必须保证其正常运行,因此你完全有理由花时间进行单元测试。

为什么需要单元测试

单元测试有助于确保代码正常运行。单元测试是进行回归测试的绝佳方法:每次更改代码时运行单元测试,确保一切正常。发现了错误?修复它并编写单元测试,确保不再发生错误。

对于已确定的重要代码部分,您需要编写单元测试以确保代码正常运行:

在基本情况下

当用户和其他代码按照预期执行时。

这些测试是最容易编写的 - 毕竟,我们都致力于成功:)。

  • 将适当的参数传递给您的函数并使测试期望适当的返回值。
在极端情况下

您想确保代码在极端情况下(即发生罕见情况时)能够正常工作。

  • 将 0 传递给你的数学函数。传递 -1。传递 INT_MAX。传递一个空字符串。
如果发生故障

你还需要验证代码是否正确破解。例如,如果财务操作失败,我们必须确保资金没有完全消失。

  • 传递一个 NULL 对象引用。执行一些会引发异常的操作。
  • 你认为这不可能,因为调用你函数的代码没有这样做?也许现在确实如此;但代码会改变。如果前端表单验证了所有输入,但明天有人重构了它,你肯定不希望后端意外失败。

 

用全面的单元测试覆盖最重要的代码后,您可以用更少的单元测试覆盖不太重要的代码。优先级!

模块化和依赖性

有时,第一步是准备代码进行单元测试。这时模块化就派上用场了!代码越模块化,测试就越容易。

确定依赖项并合理拆分后,剩下的就简单了。单元测试需要模拟依赖项,以确保只测试当前模块的行为。否则,你还会测试它所依赖的其他模块的行为。但这些模块值得单独测试。

您还可以决定测试带有依赖项的模块。虽然有些人可能会说这不再是单元测试(而是集成测试),但它仍然是测试,并且仍然有用。

测试结构

测试命名

测试方法的命名有多种方法。我认为最重要的是——名称应该具有描述性。尽可能描述性。长度最好在 200 个字符以内——越清晰越好。

小测试

由于所有测试都有非常清晰易懂的名称,您可以添加尽可能多的小测试,以应对各种极端情况。确保您的测试只测试一种场景。

文件夹结构

对我来说,当测试项目结构与主项目结构重复时,效果最明显。这样就可以轻松找到该模块的测试。

独立测试

确保你的测试彼此之间不依赖。如果需要,在每个测试的开始和结束时执行清理步骤——单元测试框架中通常有专门的方法来执行此操作。

更改代码 - 运行测试

有时我听到有人问:我如何知道在编辑代码时要运行哪些测试?

全部运行!

由于测试的文件夹结构与主代码的文件夹结构重复,因此很容易找到与您的更改相关的测试包。

当你执行模块化步骤,并将它们精简时,你已经确保了它们运行速度。因​​此,你可以经常运行测试包,例如在开发过程中和推送之前。

添加代码 - 编写测试

根据您的业务需求,需要修改哪些重要的代码?那就写个测试吧。

修复 bug?那就写个测试。养成习惯!测试是代码的重要组成部分,所以要努力保持测试的更新,这样能帮你节省很多时间。

如果测试数量超过代码数量也没关系

事实上,这是意料之中的!

如果对一段代码进行多次测试,那就太好了——这意味着你检查了很多情况。

花时间编写测试没关系——有时甚至比编写代码还要多。测试是关键业务部分的安全网,记得吗?

当不需要单元测试 

在我的项目中,我们没有对所有代码进行单元测试。对于某些代码,我们特意决定不这样做。那么,什么时候不需要呢?

当您的代码不是至关重要并且您的业务可以承受系统该部分的一些错误时。

当使代码可测试和编写测试的工作量过大,而手动测试所需的工作量较少时,您需要在计划维护项目的时间段内累计估算所需的工作量。

当存在无法抽象的依赖项时:你将其从所有其他模块中移出到一个模块,但你无法将其从该模块中移除。在这种情况下,你可以对所有其他模块进行单元测试,但这个模块必须保持原样。一个常见的例子是使用当前时间戳的模块。

当它是一个原型、一个概念验证或实验代码时,您需要尽快开发它,而且您可能无论如何都会将其丢弃。

最后但同样重要的一点是 - 当你确定 你的代码是最好的时:)

文章来源:https://dev.to/ice_lenor/unit-testing-best-practices-27ec
PREV
React 教程通常会跳过的概念
NEXT
对抗冒名顶替综合症的实用建议 冒名顶替综合症会损害你的名誉 冒名顶替综合症会降低你的自尊心 战斗!战斗!战斗! 妙语