发布于 2026-01-06 8 阅读
0

兄弟,你到底有没有做过单元测试啊?单元测试可是火箭科学啊。

兄弟,你到底有没有做过单元测试啊?

单元测试是火箭科学

我并非总是测试我的代码,但如果测试,我会选择在生产环境中进行。

单元测试是火箭科学

很多程序员都不写单元测试。主要原因是他们不明白为什么要花时间做这个。他们觉得这纯粹是浪费时间,对吧?

我以前也是这样,后来我的代码开始在生产环境中崩溃,而且是在一些大型且备受瞩目的项目中。所以,我开始寻找方法,让自己对自己的代码和提交更有信心。

单元测试是第一个答案,但我花了一段时间才正确地编写出来。

什么是好的单元测试?

要编写一个优秀、可靠且值得信赖的单元测试,你需要:

  • 理解你要测试的内容。这听起来可能很傻或者很明显,但事实并非如此。阅读方法,理解它的作用、方式和原因。如果你不知道它应该做什么或不应该做什么,又如何测试它呢?

  • 避免过度使用模拟对象。模拟对象虽然能让编写测试变得容易,但并非最佳实践。只有在别无选择的情况下才使用模拟对象,例如用于 API 调用。而且,请不要对被测类进行桩化!

  • SEAT。设置、练习、断言、拆卸。对每个测试重复此操作。

  • I/O。专注于数据转换。定义初始状态,运行测试,断言输出结果。过程中发生了什么,或者它是如何发生的,都与你无关。

  • 确定测试范围并坚持执行。一个方法可以包含任意数量的测试,但尽量将测试按用例场景分开。
    你想断言一个方法能够将数组转换为 JSON,并且抛出异常?没问题,那就写两个独立的测试!

代码覆盖率真的重要吗?

简而言之:不,并非如此

我听很多人说应该追求 100% 的代码覆盖率。但这其实是个坏主意。
别误会,代码覆盖率越高越好。但这不应该是你的主要关注点,也不应该是你的目标。

在为某个方法编写测试之前,我会问自己几个问题:

  • 该方法是否会转换数据?
  • 我可以在不模拟方法输出的情况下编写这个测试吗?
  • 该方法是否返回任何值?
  • 我可以对结果做出断言吗?

如果这些问题中任何一个的答案是否定的,那我可能就不会出题了。

代码覆盖率达到 100% 并不代表代码就经过了充分测试。

你不可以过去 !

你不可以过去 !

代码由公共方法组成,没错,但也包含私有方法和受保护的方法。
我们应该对它们进行测试吗?

当然不是。但某种程度上来说,是的!

它们通常包含业务逻辑,所以,是的,需要测试它们。但是,与公共方法不同,私有方法不需要专门的测试。
私有方法的目的是被同一个类的公共方法调用。让我们在测试中应用同样的逻辑。私有方法和受保护方法应该通过公共方法的测试来进行测试。

永远做第一

我习惯于按照 FIRST 原则编写测试,但还有其他方法,例如 AAC。
我假设作为一名开发人员,如果 FIRST 不适合你,你知道如何使用 Google 找到其他方法!

时间旅行博士

  • 速度:测试应该轻量级且速度极快。否则,我会劝阻你或你的团队不要运行它。大型项目可能包含成千上万个测试和断言。
    设置、测试和清理工作都不应该超过几毫秒。

  • 独立性:测试之间不得相互依赖,也不得依赖于先前测试的状态。
    所有所需数据都应在当前测试中创建,并在测试结束后销毁。
    如果多个测试需要相同的数据,只需在设置过程中创建即可。

  • 可重复性:测试应该能够反复执行。时间、日期或时区不应影响测试结果。
    没错,你可以扮演时间领主,模拟时间(当然,除非时间点是固定的 ;-))。
    记住,如果测试失败,唯一合理的理由应该是方法没有按预期工作,或者测试本身有误。好了,就这些!

  • 自验证:无需人工检查即可确认测试是否通过或失败。

  • 认真细致:不要偷懒。编写单元测试需要时间,有时甚至比编写方法本身还要花时间。

    • 测试每个使用场景
    • 不要局限于简单的价值观,要追求边缘价值观。
    • 如果这些方法能够处理批量数据,请使用大型数据集进行测试。
    • 异常和错误测试
    • 不要只测试成功。你还可以断言失败,而且你应该这样做!

结论

保持测试的简洁性,将其限制在特定的范围内,并专注于方法的输出。

单元测试只是完整测试周期的第一步。请看下面的金字塔图。

创意测试金字塔

文章来源:https://dev.to/juyn/do-you-even-unit-test-bro-434g