扫码阅读
手机扫码阅读

软件测试的权衡与取舍

112 2024-02-21

选择了某一方向上的决策,总是会相对应地限制事情在另一个方向上发展的可能性。

每个测试工程师都会遇到的权衡取舍问题,即:“在单元测试、集成测试、端到端测试,和其他类型测试之间的取舍”。

在现实世界中,我们通常需要把有限的资源用在最关键的地方,即将有限的资源(时间资源和人力资源)花在构建整个软件中最具有价值的部分上。因此,我们需要决定如何在单元测试、集成测试、端到端测试,或其他类型测试上分配资源比例。我将带你分析这些不同类型的测试究竟有何利弊,它们是否值得被投入更多时间。

单元测试和集成测试的终极目标是能够覆盖到软件中几乎所有的运行“路径”,即达到100%测试覆盖。但是在现实中,由于用来编写和测试代码的时间有限,我们往往无法达到这一目标。因此,为软件编写多少单元测试与集成测试,是在我们的日常工作中最为常见的一个权衡取舍问题。

针对单元测试的决策

对于单元测试,你需要决定测试代码的哪一部分。让我们考虑一个简单组件的单元测试。这个组件暴露了一个名为fun()的public方法。而组件内部定义的其他方法则通过使用私有访问修饰符被“隐藏”了起来,客户端无法调用。

这里你需要做出的决策是:是否要对私有方法也进行单元测试。如果不对它进行单元测试,那么这样的单元测试是一种仅覆盖public方法的黑盒测试。这种程度的单元测试通常已经足够完善。但有时,一些含有复杂逻辑的私有方法也值得被单元测试。在这种情况下,你可以考虑降低私有方法的访问修改器等级。

通过将可见性修改为public,就能够为那些本不应该公开的方法编写单元测试。这些公有方法对用户是可见的,因此你需要承担他们可能会直接使用这些方法的风险。

这里提到的两种单元测试方法没有对错,只有取舍,第二种方法给予了你更多的灵活性,然而,维护成本可能会相应地上升。

当然,你可以在这两者之间选择一个折中方案,即将你的代码包私有化。这样,当你的测试代码和生产代码在同一个包里时,你便不需要将代码公开,但是你可以在测试用例中使用这些方法。

单元测试与集成测试占比的决策

当测试系统的代码逻辑时,你需要决定添加的单元测试与集成测试之间的比例。

我们能够花费在开发系统各个特性上的时间是有限的,因此需要决定是否应该在单元测试或集成测试中投入的时间,我们需要决定如何在它们两者之间分配资源。

这两种测试方法各有利弊,“如何进行选择和分配?”便是你在编写代码时会遇到的,一个典型的权衡取舍问题。单元测试的执行较快,反馈时间也较短,所以整个调试过程也会相应花费较少的时间。

在大多数情况下,应用于软件系统的单元测试用例数量总是多于集成测试。开发者可以即时地得到单元测试的执行结果,因此可以在一定程度上保证生产力。并且,它们的执行速度也更快,代码的调试时间也相应地缩短。

如果你的代码库具有100%的单元测试覆盖率,当一个新的缺陷存在时,它极有可能会被其中的某个单元测试用例“捕获”。你便能够在这个测试用例所覆盖的对应方法中找到问题所在。

另一方面,在缺乏集成测试的情况下,你将无法了解到系统中各个组件之间的联系,以及它们之间是以何种方式被集成在一起的。系统使用的各类算法可以被单元测试很好地覆盖,但从更高的层次来看,却没有相应的测试能够保证当这些算法被整合在一起时,系统是否还能够正常工作。

最终,你会得到一个在较低代码层次上通过完整测试的系统,但是这个系统中组件却没有经过测试,因此,你无法保证在更高的层次上,系统还能够正常工作。而在现实生活中,你的代码应该同时使用单元测试与集成测试。

在一个真实的生产系统中,我们还会有在其他层次的测试。比如,可能使用端到端测试,来对业务场景进行整体验证。在更多复杂的架构中,我们可能需要首先启动多个微服务,这些服务互相连接以提供特定的业务功能。这种测试依赖于相应基础设施的正确配置,因此会花费更多时间,测试结果也会在较晚的时间得到。

另一方面,端到端测试会在更高层次上确保业务在端到端流程,以及系统功能上是正确的。当将该测试与单元测试和集成测试进行对比时,我们可以采用不同的维度进行分析:

  • 由于单元测试是独立于单个组件运行的,因此这些测试无法给予我们更多关于系统内其他组件,以及这些组件之间如何交互的信息。

  • 集成测试试图验证更多组件,以及它们之间在交互时的功能是否正确。然而,这些测试往往无法跨越提供特定业务功能的多个微服务。

  • 尽管端到端测试可以从整体上验证系统,但由于进行测试需要相关基础设施的支持,因此,我们可能需要启动全量微服务、数据库、队列等等,进行这项测试所花费的准备成本是很大的。

另一个我们需要考虑的维度是创建测试用例的时间成本。单元测试用例相对来说开发较为简单,因此我们可以在较短的时间内编写大量用例。而集成测试用例则需要花费相对更多的时间。最后,端到端测试则需要大量的前期准备时间来创建测试所依赖的基础设施资源。

在现实中,由于资源(预算、时间)是有限的,因此我们需要考虑这些限制性因素,以最大化地提高软件质量。通过使用测试,我们能够保障软件的质量,并减少缺陷的数量。同时,它还可以提供软件在未来长期的可维护性。

为此,我们需要选择使用的测试类型,并决定编写多少测试用例。由于资源的限制,我们需要在单元测试、集成测试,以及端到端测试用例的数量之间找到一个平衡点。通过分析这些测试类型的不同维度和优缺点,我们可以做出更加明智的决定。

值得注意的是,添加测试会增加软件的整体开发时间。我们想要添加的测试越多,需要投入的时间也就越多。有时,如果不事先约定好测试的开发与推进计划,那么这些测试的质量也难以保证。因此,应该像添加新功能一样的方式来规划测试的实施过程,而不是在功能完全开发好之后再“马后炮”。

以上内容来自新书《Software Mistakes and Tradeoffs》的第一章,如果你对软件研发过程中的各类权衡与取舍感兴趣,那么可以关注这本书,目前这本书刚由人民邮电出版社启动中文版的翻译工作,将由两位业界资深的技术专家陆明刚和胡世杰主笔翻译,而我会担任本书的技术审校,最快预计今年底或明年初能够与大家见面,让我们一起期待。

原文链接: https://mp.weixin.qq.com/s?__biz=MzkzNDM1MDU3Mg==&mid=2247484251&idx=1&sn=566a69b2483b60a0fec466a3f88882c8

关注软件研发行业效能提升与质量提升的工程实践,普及研发效能宣言的价值观、最佳实践与工程落地案例

14 篇文章
浏览 4688
加入社区微信群
与行业大咖零距离交流学习
软件研发质量管理体系建设 白皮书上线