什么是契约测试?
契约测试是一种用于独立检验每个应用程序之间集成问题的技术,验证系统发送或接收的格式化数据,是否匹配“契约”文档。对于通过HTTP协议进行通信的程序,这些“消息”将是HTTP的请求和响应,而对于使用队列的程序,则是队列中传递的消息。实际上,契约测试最简单的一种实践方式是,通过检查上下游的所有调用与返回是否与实际结果相同。
契约测试非常适合于任意两个需要通信的服务:比如一个API服务器和一个web前端,一个服务和它的下游服务。契约测试不单单适用于单服务器-客户端模式,也同样适用于如今的微服务体系。契约测试是微服务开发和部署杀手级的应用。
为什么需要契约测试?
试想如下场景,一个Web应用程序,其中团队A负责开发产品前端,B团队负责产品服务端开发。项目是敏捷模式,在项目开始时,两方团队会在会议上定义所有需求,以及前后端协作、数据传递的方式。之后每个团队熟悉需求后,开始创建用户故事,接下来开发团队基于任务紧锣密鼓的进行产品功能研发。等前后端开发完成后,会在后面的迭代中安排进行联调、集成测试,验证产品前后端功能匹配。但随着A团队的开发进行,发现必须对API行为进行改造,团队成员会对API文档进行相应的更新,同时通知团队B进行调整。测试团队则会基于最新的API文档进行测试用例的设计,进行产品功能验证。
在这个流程中已经暴露出了很多问题:
- API文档的更新很有可能没有通知到不同团队的开发人员
- 测试团队基于API文档进行测试,文档很有可能不是最新的
- 在整个开发周期中,要等到集成环境部署成功,才能够进行产品功能验证
- 在多版本API中更难保证需求、功能验证正确
一旦发现上面的问题,都需要花费大量的时间在问题定位、修改、部署、验证上,所以我们需要一种能够较早期、较快速暴露出产品间行为不匹配的手段,一种能从客户端(终端、最终消费者)验证产品功能是否匹配预期的手段。
消费者驱动的契约测试
消费者驱动的契约测试有消费者和提供者两个方面。
消费者:
利用另一个应用程序的响应或数据来完成其工作的应用程序。
对于使用HTTP的应用程序,消费者始终是发起HTTP请求的应用程序(例如web前端)。
对于使用队列的应用程序,消费者是从队列中读取消息的应用程序。
提供者:
一种应用程序(通常称为服务),通常通过API为其他应用程序提供功能或数据。
对于使用HTTP的应用程序,提供者是返回响应的应用程序。
对于使用队列的应用程序,提供者(也称为生产者)是将消息写入队列的应用程序。
消费者和提供者之间的合同称为契约。每个契约都是相互作用的集合。
对于HTTP协议,契约可以包含两个方面:
- 预期的请求 – 描述消费者预期发送给提供者的内容
- 期望响应 – 描述消费者希望得到的响应内容。
对于消息队列,应包含:
- 期望消息 – 描述消费者想要使用的消息内容。
编写契约测试的第一步是定义消费者与提供者的这种相互作用。
消费者测试
流程如下图:
- 使用契约语法,将预期的请求和响应定义到模拟服务中。
- 消费者运行测试代码,向模拟提供者发送真实请求。
- 模拟提供程序将实际请求与预期请求进行比较,如果比较成功,则返回预期响应。
- 消费者测试代码接收返回,确认响应内容正确无误
契约测试只有在每个步骤都没有错误时,才算成功。
提供者验证
流程如下图:
在提供者验证流程中,每个请求都被发送到真实的提供者,并将其生成的实际响应与消费者的预期响应进行比较。
契约测试 Vs 集成测试
集成测试 | 契约测试 | |
---|---|---|
API配置 | 可以配置 | 不可配置 |
部署检测 | 可以检查 | 不需部署、无法检查 |
API版本测试 | 可以 | 可以 |
本地调试 | 不可以 | 可以 |
环境问题 | 可以检查 | 无法检查 |
问题反馈时间 | 定位慢 | 定位快 |
问题定位难易程度 | 难以分析 | 分析简单 |
首先,契约测试不能取代集成测试。但它可以取代一些现有的集成测试的场景,使测试左移,在开发阶段尽可能快的暴露出产品行为问题,为软件开发生命周期提供更快的反馈。
在集成测试中,我们需要验证API所在的上下文,例如环境体系结构、部署过程等。
在契约测试中,我们需要测试API的细节,其中包括与API结构、内容和错误响应和一些边缘情况。
下一步
在本章节中,我们学习了契约测试的含义以及它在微服务架构中的作用。契约测试可以减少与集成问题相关的反馈时间,从而降低团队的成本。
在接下来的章节中,您将了解更多有关契约测试和PACT的最佳实践。