测试金字塔 (Test Pyramid)是一套使用单元测试,集成测试和端到端测试来构建自动化测试体系的方法。
如下图所示,在金字塔的最下方是单元测试,中段是集成测试,最上方是端到端测试。单元测试实现的成本最低,运行速度最快,是毫秒级的。集成测试的实现成本比单元测试高,因为要跟外部系统连接,所以运行速度比单元测试要慢1-2各个数量级。端到端测试最符合用户的完整体验,从 UI 开始通过 API 直达系统内部代码,因为涉及的环节更多,所以实现成本更高,运行速度比集成测试更慢。
测试金字塔理论推荐单元测试应该是数量最多,覆盖范围最大的测试种类。道理很简单,单元测试成本低,运行速度快,在发现问题的时候解决问题也最快。集成测试数量次之,最后才是昂贵的端到端测试。由于端到端测试经过的环节更多,所以通过端到端测试发现的问题,解决起来用时更多。
单元测试
单元测试是一种由开发者实现的白盒测试。在测试金字塔里,单元测试是自动化测试体系的基础。一般使用代码覆盖率来评价单元测试是否达到了测试的要求,但是在实践中开发团队往往发现很难达到指定的代码覆盖率。开发工程师写的单元测试和测试工程师编写的测试用例也很难匹配,跟产品经理的业务描述差得更远。
这里的一个重要原因是许多开发者把程序简单地理解为增删改查(CRUD),而没有围绕业务逻辑来编写代码。对外部服务没有构建“以我为中心”的模型,编写代码的时候直接使用要依赖服务定义的模型,这样在编写单元测试时就会因为模拟某些服务难度太高不得不放弃,只能使用集成测试来验证代码的正确性。
我们可以借鉴《领域驱动设计》里的分层架构,以及六边形架构来构建抽象的领域模型,并且使用单元测试来验证模型实现了产品经理的业务描述。这样我们就可以使用面向对象知识围绕业务构建领域层,把外界服务看做各种连接到模型的“端口”。在编写单元测试时,就不会遇到无法模拟其他服务的问题。
总结一下,我们的单元测试应该构建在“领域层”之上,以验证领域模型对业务描述的正确性为主要目标。
单元测试是否可以连接数据库?
单元测试是系统内部的测试,单元测试不能跨越系统。数据库是另外一个系统,跨系统的测试属于集成测试的范畴,所以单元测试中是不可以连接数据库的。单元测试要遵循 FIRST 原则,其中的 “F” 就表示要快。单元测试的范围在系统内部不访问外部系统才可能快。访问数据库会把毫秒级的测试时间,提升到几十甚至数百毫秒以上。这显然是集成测试的运行时间水平。
集成测试
集成测试是验证系统和系统之间的相互调用是否符合预期的测试。因为要跨越系统,所以和单元测试相比集成测试运行起来要慢1到2个数量级。
当发现问题时,问题可能会出在集成测试连接的任意一个系统中,开发者需要排查每一个系统直到找到问题为止,而在单元测试中发现问题时只需要排查本系统,所以集成测试相比单元测试排查问题用时也更多。
开发者在设计集成测试时可以限定要集成的系统范围,这样就可以把测试重点放在开发者关心的系统上。集成测试往往以 API 调用的方式进行,开发者编写测试脚本按顺序调用 API,检查结果是否符合预期。
集成测试是系统之间的测试。数据库也是一种系统
端到端测试
端到端测试以 UI 为起点,模拟用户使用系统的场景,从 UI 输入验证系统的输出是否符合预期。因为涉及到 UI,端到端测试必然会跨系统,又因为开发者只能控制 UI 部分的输入顺序和数量,所以开发者不能控制端到端测试中被调用的 API 的顺序和数量,在发现问题时不光要检查各个可能要涉及的系统,还要考虑 API 可能被调用的顺序和数量,排查问题的难度比集成测试更高。
在运行时间上,UI 测试模拟用户的输入而不是像集成测试那样直接调用系统 API,所以运行时间类似于人类反应的时间,与集成测试相比端到端测试整体运行时间又有数量级级别的下降。
端到端测试也包含了部分探索性测试和人工测试。
端到端测试的输入从UI开始
端到端测试在性能测试上更能反映系统在真实世界的运行情况
如果以集成测试的方式来做性能测试,开发者可以按照指定的顺序调用API,模拟在规定时间内调用 API 的数量下系统的响应能力,但是在真实世界,用户是通过 UI 来驱动系统的,UI 页面往往包含各类信息,这类信息会并发地以不同顺序调用系统的 API,这样在用户流量大的情形下,不同 API 被纠缠在一起以不同的顺序和数量传递到不同的系统里。
在上图中,用户打开“新浪财经”页面会调用页面UI,要闻,突发,股市指数,天气预报等10几个系统。这比单纯的集成测试要调用的系统数量上要多,调用顺序由UI页面结构决定,每次页面调整都会导致 API 调用顺序的改变。显然端到端测试要比集成测试复杂。
和集成测试相比,基于端到端测试实现的性能测试,结果可能会和开发者的预期差距更大,但是可能会发现更多问题。
如何使用测试金字塔来构建自动化测试体系
基于对测试金字塔中 3 种不同种类测试的特点的分析,考虑到运行速度和实现成本,我们推荐开发者以单元测试为自动化测试的基础,以尽可能低的成本发现尽可能多的问题,通过集成测试检查系统间的相互调用问题,辅以端到端测试优化用户体验来构建自动化测试体系。
结论
本文通过比较单元测试、集成测试和端到端测试在实现成本,负责范围和纠错时间的区别和联系,介绍了测试金字塔的概念,以及以按照单元测试、集成测试和端到端测试的顺序构建自动化测试体系的必要性。
感谢每一个认真阅读我文章的人,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!