契约测试白话篇:业务中的契约测试

382 阅读5分钟

​我正在参加「掘金·启航计划」

一、前言

上文带大家认识了契约测试《契约测试(上):什么是契约测试》,文章偏理论,后台收到很多感兴趣的小伙伴留言,对生产者、消费者这些概念比较模糊。还有小伙伴留言 为什么平常测试中没接触过契约测试呢?契约测试是项目测试必须进行的吗?

鉴于这些问题,今天加更一篇,结合业务场景给大家以白话的方式再科普一下。

上文说了,谈及契约,必包含生产者、消费者、契约本身。

  • 生产者:被调用者/消息发送者

  • 消费者:调用方/消息订阅者

  • 契约:双方约定的调用规范

那么契约包含哪些内容?

  • 若以HTTP接口为例,契约就包含HTTP请求的method、request body、request-header、response body、response-header等。

  • 若以消息为例,契约就包含消息Topic、eventCode、消息体等

  • 若以TR服务为例,契约就包含上下文内容、请求体、响应等

二、业务场景举例

以淘宝购物 下单支付为例,对于用户来说就是添加商品到购物车,然后输入支付密码发起支付,然后收到支付成功的通知,就等待发货了。

但是背后的技术实现还是挺复杂的,涉及到跨域调用,消息的发送与监听,可以参考下面的服务调用关系简图。

编辑

大家可以看到,收单域和收银域直接是有服务调用和消息订阅关系的,那么如何保证收单调用收银服务时,收单的请求报文是符合当前业务契约约定的,以及收银给收单发送的消息中消息体的报文是遵守契约约定的,则需要测试同学进行测试。

“唯一不变的就是变化”。随着业务的迭代,契约需要持续测试。大家肯定都经历过项目迭代的痛苦,过程涉及到接口契约升级,契约中的每个字段的增减都可能影响存量业务(开发设计的实现逻辑要做好向下兼容非常重要‼️)。

编辑

三、契约测试究竟测什么

编辑

我理解广义的契约测试包含两部分:

1.接口调用前的报文是否遵守契约约定,即你调生产者的时候,给它的“物料”是不是对的。

2. 如果1的报文没问题,则要验证消费者调用生产者后,返回的报文是否符合预期的。

其实不难发现,我们平常做接口测试理论上也是契约测试的内容,那是因为我们是默认调用生产者的请求报文都是正确的,就是符合契约规定的那样的,所以我们更多关注生产者的响应。

而狭义的契约测试更多只关注1那部分,其实这也是有原因的,我说个场景大家就清楚了。例如收单域对下单支付接口做了改造,需要做收单域内测试,因此我们需要mock掉收银域的支付接口,既然是mock,不管你发送的请求体request是什么内容,收银支付响应的内容肯定都是预期结果。但是问题来了,如何测试收单域组装调用收银的支付接口request逻辑的正确性?即下图红色部分的逻辑,所以契约测试就应运而生了。而我认为契约测试是接口测试的补充。

而我认为通常所说的契约测试是狭义的说法。

编辑

下面通过表格梳理下契约测试与其他测试的差异:

​编辑

四、为什么有些同学没接触过契约测试?

契约测试往往应用于微服务架构,微服务应用是一系列自治服务的集合,每个服务只负责完成一块功能,这些服务共同合作来就可以完成某些更加复杂的操作。与单体的复杂系统不同,开发者需要开发和管理一系列相对简单的服务,而这些服务可能以一些复杂的方式交互。

注:进一步了解微服务。具体可以查看这两篇文章《全链路测试不是银弹》《浅谈Mock平台设计思路

单体架构调用链路相对比较简单,接口间请求报文的契约更多在于单应用内部,基本上开发的单测用例就可以已经覆盖到。因此测试同学没必要重复测试,只需要重点关注接口调用的响应即可。

注:单体架构中,测试更注重系统测试(前后端联调测试);但是值得注意的是,在提测前前后端开发联调也是契约测试的一部分。

契约可以在单域,也可以在域间。域内往往是单应用内相互调用方法之间的约定,域间往往是应用间的接口契约。

域内的契约测试其实已经通过开发单元测试覆盖,不用测试同学重复测试;而域间的契约则需要测试同学覆盖。