契约测试只能验证返回值类型和格式吗

是的
既然如此,它的意义在哪里呢?我就是带着这样的疑问进了现在的项目组 - API, Application Programming Interface

在解释这个回答之前,让我们先来回顾两个测试问题:

为什么单元测试需要Mock?

mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法

如果容易构造且获取,那就可以不用Mock而直接用于测试中了。而且单元测试的目的是为了测试自己的函数功能,

为什么需要集成测试?

集成测试,也叫组装测试或联合测试。在单元测试的基础上,将所有模块按照设计要求(如根据结构图)组装成为子系统或系统,进行集成测试。

文中指的就是将两个模块组装成子系统的简单集成测试。

仔细想一下,如果是单元测试Mock+集成测试好像就可以解决很多外部服务依赖问题了,但这里有个问题,Provider如何知道自己的实现满足了Consumer的需求呢?

契约测试

在Martin Fowler的ContractTest中,了解到契约测试要解决的痛点是 - 减少双方约定的契约(API文档)有非预期的破坏

在Pact的实践中,相当于有两个Mock Service,一个是Mock Provider,另一个是Mocker Consumer。


契约测试只能验证返回值类型和格式吗_第1张图片
Pact Interaction.png

当Consumer端写测试时,用的是Mock Provider,这跟通常意义下的Mock Server是一个意思,即针对固定请求,返回使用的最小Response,也就是说,你不关心的字段可以不用测试,只返回自己需要的内容,同时生成契约并放到公有的地方,这里Pact用到的是Broker。

契约测试只能验证返回值类型和格式吗_第2张图片
Provider Verification.png

接着,Provider端会将契约从公有地Broker上拿下来,由Mock Consumer将契约中的请求发给真正的Provider,并验证真正的返回结果和契约中预期的返回结果是否匹配,并将结果回传至broker。可能只有类型、格式和数量的校验,但也足够了,其他的细节测试可以有Provider的功能测试来覆盖。

Broker中会收集Consumer端share过来的契约,也是一个展示Verify结果的地方。


契约测试只能验证返回值类型和格式吗_第3张图片
Pact Broker.png

其中Latest pact published是Consumer最近的一次发布的时间,Last Verified是Provider端最近的一次verification的时间

当broker中verify的结果有失败时,Consumer和Provider双方都需要警觉了,肯定是契约被某一方破坏了,或者Consumer的需求变了,或者是实现变了,或者是人为的错误,但Pact的目的是发现问题并达成一致,从而继续推进。

理想情况下,如果Consumer需求有变动就先去找Provider商量,或者Provider端有升级前找各Consumer协商,就不会发生问题了,测试的核心是以防万一,在万一发生的情况下,如何快速知道已经出错,并快速制定解决方法而不至于导致更坏的结果。

在解释了单元测试、集成测试和契约测试之后,我们来看看不同,

单元测试 (简单的)集成测试 契约测试
目标 构造数据,测试自己某个模块的功能是否正常 调用外部服务API,测试是否能正常连接 双方校验,任何一方发生变动,既契约的被破坏,都会警觉
范围 单元测试是模块的自测,可以写在任何地方,不管是Consumer还是Provider,不管是前端还是后端 集成测测试是测试下游服务能否调通,无论Cosumer还是Provider都有下游服务,都可以有集成测试,测试的是不同的东西 发生在服务和服务之间,但测试和维护的都是同一个东西,且有反馈

场景1

团队在做API,供整个企业之后使用,他们需要构建监控,日志,登录,购买商品,支付等服务。

其中,如果监控和日志这些是用微服务自己做,那就可以使用契约测试,其他服务会消费它
如果登录,支付这些集成第三方的成熟的身份认证系统,或支付系统,就可以使用集成测试。

场景2

团队在做API,供整个企业之后使用,他们需要构建监控,日志,登录,购买商品,支付等服务。

同样的场景,如果所有的服务都是自己来构建,那就可以使用契约测试将所有的服务都管理起来。

场景3

大厂提供API供很多企业使用。通常会比较稳定,鲜少会改变。

如果想引入契约测试,Consumer端需要提供契约,Provider端需要构建Broker和进行验证测试。

误区一
契约测试的理想国是Provider端不需要写测试,所有Consumer的用例总和构成了Provider端测试的全部集合。这句话的弊端就在于provider端太寄希望于Consumer了,这就相当于让测试相信开发一样,不是说开发不可信,是以防万一。

误区二
曾经觉得,可以将契约测试中的Consumer测试结合到一起,既替换单元测试中的Mock。却忽略了单元测试在测试金字塔中是属于最底层的,代价小,效率高,所以case覆盖会很多,如果与契约测试结合到一起,会造成冗余及滥用。

写在最后

回到最初的问题,确实契约测试的验证会比较简单,但它的优势就是监督双方或多方,在问题发生时,触发沟通或交流来达成一致,从而避免真正的问题发生,它的出现不是为了取代谁,而是关注点的不同 - 关注契约关注双方。

你可能感兴趣的:(契约测试只能验证返回值类型和格式吗)