1.1.2 单元测试与集成测试的比例
计划测试任务时,你需要思考对你的系统而言,应该按什么比例分配单元测试与集成测试。通常情况下,选定一个方向会限制向另一个方向发展的可能性。而且,这种限制也许从该开发项目开始时便产生了。
大多数情况下,我们开发功能的时间都是“捉襟见肘”的,需要慎重考虑是否要投入更多的时间在单元测试或者集成测试上。现实场景中,我们应该充分结合单元测试和集成测试的优势,最大限度地发挥其效能,这也是为什么我们需要思考该按怎样的比例分配单元测试和集成测试。
这两种测试方法都是双刃剑,各有其利弊,你在编码时不得不做利弊权衡。单元测试的优点是速度更快,反馈时间更短,因此调试流程通常也更短。图1.1展示了这两种测试的优缺点。
图1.1 单元测试、集成测试及其执行与反馈时间(速度)
图1.1所示为一个金字塔,这是因为通常情况下,软件系统中的单元测试比集成测试多得多。单元测试可以为开发者提供几乎即时的反馈,从而帮助提升开发效率。单元测试的执行速度更快,可以帮助减少代码调试的时间。如果单元测试100%覆盖了你的代码库,当一个新的缺陷被引入时,很可能某个单元测试能发现这个缺陷。你可以在单元测试覆盖的方法级别上精确定位该缺陷。
另外,如果系统缺少集成测试,你将无法判断组件之间的连接是否正常以及它们之间的集成是否成功。你的算法虽然经过充分的测试,但没有对更大场景进行覆盖。最终你的系统可以在较低的层级正确完成所有任务,但由于系统中的组件配合没有经过测试,无法在更高层级上确保系统的正确性。在实际项目中,你的代码应该同时包含单元测试与集成测试。
需要注意的是,图1.1仅关注了测试的执行与反馈时间。但实际生产系统中还会有其他层级的测试,如我们可能会做完整验证业务场景的端到端测试。在更复杂的体系结构中,我们可能需要启动N个相互连接的服务以提供对应的业务功能。由于搭建测试基础架构所需的开销较大,这类测试的反馈时间可能比较长。然而,它们能从更高的层级保障系统端到端流程的正确性。如果要用这些测试与单元测试或者集成测试做比较,我们需要从不同的维度进行分析。如图1.2所示,它们从整体角度而言对系统验证的效果如何?
单元测试仅在单一组件中隔离运行,无法提供系统中其他组件的信息,也无法验证单一组件如何与其他组件进行交互。集成测试的重要性此时就凸显了,它可以同时测试多个组件,验证组件之间的交互效果。不过,集成测试通常不会跨多个服务或者微服务验证某个业务功能。最后我们要介绍的是端到端测试,这类测试可以对系统进行完整的验证,由于我们需要串联起整个系统,该系统可能包含若干个微服务、多个数据库、多个消息队列等,测试涉及的组件数目是极其庞大的。
图1.2 单元测试vs集成测试vs端到端测试
我们还要考虑创建测试所需的时间。创建单元测试比较容易,只需花费比较少的时间就能创建大量的单元测试用例。创建集成测试往往需要更多的时间。最消耗资源的是端到端测试,创建端到端测试的基础设施需要大量的投入。
在实际项目中,我们的资金和时间往往是有限的,虽然我们秉持尽最大可能提升软件质量的原则,但也要考虑方方面面的限制。通过测试覆盖代码变更可以帮助我们发布更高质量的软件,减少缺陷数量,从长远来看,还可以提升软件的可维护性。在资源有限的情况下,我们不得不思考,该选择做什么类型的测试,以及做到什么程度。我们需要在单元测试、集成测试、端到端测试之间寻找平衡点,可以多维度分析特定类型测试的优势与劣势,帮助我们做出更合理的判断。
有一点特别重要,也需要特别强调,那就是添加测试会延长开发的时间。我们做的测试越全面,花费的时间就越多。如果不为这些测试任务分配时间,只是死板地限定项目交付日期,很难开展有效的端到端测试工作。因此,计划为产品添加新功能时,我们也需要考虑添加对应的测试任务,而不要奢望以事后弥补的方式解决问题。