什么是契约测试?

契约测试是一种用于独立检验每个应用程序之间集成问题的技术,验证系统发送或接收的格式化数据,是否匹配“契约”文档。对于通过HTTP协议进行通信的程序,这些“消息”将是HTTP的请求和响应,而对于使用队列的程序,则是队列中传递的消息。实际上,契约测试最简单的一种实践方式是,通过检查上下游的所有调用与返回是否与实际结果相同。

契约测试非常适合于任意两个需要通信的服务:比如一个API服务器和一个web前端,一个服务和它的下游服务。契约测试不单单适用于单服务器-客户端模式,也同样适用于如今的微服务体系。契约测试是微服务开发和部署杀手级的应用。

为什么需要契约测试?

试想如下场景,一个Web应用程序,其中团队A负责开发产品前端,B团队负责产品服务端开发。项目是敏捷模式,在项目开始时,两方团队会在会议上定义所有需求,以及前后端协作、数据传递的方式。之后每个团队熟悉需求后,开始创建用户故事,接下来开发团队基于任务紧锣密鼓的进行产品功能研发。等前后端开发完成后,会在后面的迭代中安排进行联调、集成测试,验证产品前后端功能匹配。但随着A团队的开发进行,发现必须对API行为进行改造,团队成员会对API文档进行相应的更新,同时通知团队B进行调整。测试团队则会基于最新的API文档进行测试用例的设计,进行产品功能验证。

在这个流程中已经暴露出了很多问题:

  1. API文档的更新很有可能没有通知到不同团队的开发人员
  2. 测试团队基于API文档进行测试,文档很有可能不是最新的
  3. 在整个开发周期中,要等到集成环境部署成功,才能够进行产品功能验证
  4. 在多版本API中更难保证需求、功能验证正确

一旦发现上面的问题,都需要花费大量的时间在问题定位、修改、部署、验证上,所以我们需要一种能够较早期、较快速暴露出产品间行为不匹配的手段,一种能从客户端(终端、最终消费者)验证产品功能是否匹配预期的手段。

消费者驱动的契约测试

消费者驱动的契约测试有消费者和提供者两个方面。

消费者:

利用另一个应用程序的响应或数据来完成其工作的应用程序。

对于使用HTTP的应用程序,消费者始终是发起HTTP请求的应用程序(例如web前端)。

对于使用队列的应用程序,消费者是从队列中读取消息的应用程序。

提供者:

一种应用程序(通常称为服务),通常通过API为其他应用程序提供功能或数据。

对于使用HTTP的应用程序,提供者是返回响应的应用程序。

对于使用队列的应用程序,提供者(也称为生产者)是将消息写入队列的应用程序。

消费者和提供者之间的合同称为契约。每个契约都是相互作用的集合。

对于HTTP协议,契约可以包含两个方面:

  • 预期的请求 – 描述消费者预期发送给提供者的内容
  • 期望响应 – 描述消费者希望得到的响应内容。

对于消息队列,应包含:

  • 期望消息 – 描述消费者想要使用的消息内容。

编写契约测试的第一步是定义消费者与提供者的这种相互作用。

消费者测试

流程如下图:

  1. 使用契约语法,将预期的请求和响应定义到模拟服务中。
  2. 消费者运行测试代码,向模拟提供者发送真实请求。
  3. 模拟提供程序将实际请求与预期请求进行比较,如果比较成功,则返回预期响应。
  4. 消费者测试代码接收返回,确认响应内容正确无误

契约测试只有在每个步骤都没有错误时,才算成功。

提供者验证

流程如下图:

在提供者验证流程中,每个请求都被发送到真实的提供者,并将其生成的实际响应与消费者的预期响应进行比较。

契约测试 Vs 集成测试

集成测试 契约测试
API配置 可以配置 不可配置
部署检测 可以检查 不需部署、无法检查
API版本测试 可以 可以
本地调试 不可以 可以
环境问题 可以检查 无法检查
问题反馈时间 定位慢 定位快
问题定位难易程度 难以分析 分析简单

首先,契约测试不能取代集成测试。但它可以取代一些现有的集成测试的场景,使测试左移,在开发阶段尽可能快的暴露出产品行为问题,为软件开发生命周期提供更快的反馈。

在集成测试中,我们需要验证API所在的上下文,例如环境体系结构、部署过程等。

在契约测试中,我们需要测试API的细节,其中包括与API结构、内容和错误响应和一些边缘情况。

下一步

在本章节中,我们学习了契约测试的含义以及它在微服务架构中的作用。契约测试可以减少与集成问题相关的反馈时间,从而降低团队的成本。

在接下来的章节中,您将了解更多有关契约测试和PACT的最佳实践。