eBay 工程师:API 变革面临挑战,契约测试能否成为解决方案?

news2025/1/18 17:01:58

近年来,随着微服务架构的广泛采用,契约测试(Contract Testing)越来越受欢迎。在这篇文章中,我们将分享我们在 eBay 的契约测试的经验。

在微服务架构中,服务通常通过远程过程调用或异步消息进行整合。测试微服务集成的传统方式是通过端到端的集成测试。不过,由于外部的依赖性,集成环境可能是不稳定的,这会让端到端测试变得很脆弱,效率也很低。这在现实世界的场景中是很常见的。

我们 eBay 的 Notification Platform 团队面临的另一个挑战是,我们的 API 被许多领域的团队所使用。在发展我们的服务 API 的同时,保持与所有消费者的兼容性是我们的一个基本原则。在这篇文章中,我们将介绍在 eBay,我们是如何通过采用契约测试来解决上述挑战的,以及我们为将消费者驱动的契约测试工作流程深度整合到 eBay 的开发生态系统而构建的工具。

编译整理|TesterHome 社区
作者|Xiaoye Wang, Simon Wang, Daphne Huang, David Van Couvering and Qingyuan Liu

01 寻求解决方案

我们的主要目标是探索一种可靠的方式来演化 API,并具有向后兼容性。由于我们的 API 是基于 OpenAPI 规范的,我们评估了通过 OpenAPI 模式进化与语义版本确保 API 兼容性的可能性。这种方法完全由服务提供者管理。例如,即使数据属性的重命名不会破坏消费者的数据消费(例如反序列化),我们仍然需要保守地进行改变,因为我们不知道客户是否使用这个特定的数据属性。

OpenAPI 规范本身并没有反映出 API 消费者对模式的依赖程度。有时服务提供者不得不选择数据属性冗余来确保安全。这个解决方案也没有解决端到端测试问题的脆弱性。

我们需要一种方法来使消费者的依赖关系正规化,就像提供者的 API 规范一样。我们首先研究了 BDD(行为驱动开发)的方法,即用一种特定领域的语言(在我们的例子中是 Gherkin)将 API 消费者的需求正式化为行为规范。基于由 API 消费者和提供者共同定义的 BDD 规范,我们可以实现提供者一方的测试用例,以涵盖我们单元测试中 API 行为的验证。这似乎填补了消费者和提供者之间的信息空白。

但是,如果消费者在没有更新行为规范的情况下改变需求怎么办?我们如何保证消费者的行为始终与规范一致?使用 BDD 来确保 API 的向后兼容性,在很大程度上仍然依赖于执行该过程的技术人员。这种方法只在那些理想的情况下起作用,即一切完全按计划进行(即 API 供应商的功能测试用例可以始终覆盖所有消费者行为)。

鉴于 BDD 方法的缺陷,我们研究了另一种方法来解决这个问题:契约测试。在这种情况下,契约是消费者和提供者之间关于 API 行为的最小协议。根据不同的实现方式,消费者可以在他们的测试用例中针对模拟(或存根)明确设置 API 预期值,这些预期值随后可以被翻译成与编程语言无关的中间文件,描述契约的交互。然而,API 提供者需要在提供者的验证测试中满足所有消费者契约。通过利用契约测试,我们可以建立一个系统的工作流程,使这个过程可执行,并及早发现兼容性问题。

契约测试提倡基于预定义的契约而不是真正的端到端交互,对集成点进行孤立的单元测试的想法,使其相对快速和稳定。

02 契约测试框架

在 Notification Platform 团队中,我们评估了两个流行的契约测试框架:Spring Cloud Contract 和 Pact。

契约可以是提供者驱动的,也可以是消费者驱动的。在提供者驱动的方法中,契约是由 API 提供者定义的;API 消费者端单元测试依赖于从契约中导出的 API 存根。这在多组件系统的隔离测试中有时很有用,因为应用开发者同时控制着提供者和消费者。组件之间的交互可以用存根来模拟,而且双方之间没有通信间隙。

消费者驱动的契约从消费者的角度记录每一次交互。不同的消费者可能有不同的要求,而提供者有义务履行所有的契约。与生产者驱动的契约相比,这是一种更广泛接受的服务测试范式,可以在保持向后兼容性的同时发展服务。

消费者驱动的工作流程

Spring Cloud Contract 最初是作为一个提供者驱动的框架建立的,但是可以通过预定义的工作流程实现消费者驱动的契约测试:

图 1:Spring Cloud Contract 中消费者驱动的契约测试工作流程

1.服务消费者从共享契约库中克隆,然后在特性分支中添加新的契约或修改现有的契约。

2.服务消费者从定义的契约中生成存根,将存根安装到本地文件系统中,并使用本地生成的存根编写测试案例。

3.在测试用例通过契约验证后,服务消费者可以创建一个契约的拉动请求,从特性分支到主分支。

4.服务提供者实现 API 以满足消费者定义的契约,编写验证测试以确保实现满足契约,然后合并拉动请求。

5.然后,服务提供者可以将生成的存根的最终版本发布到远程存根库中。

6.消费者将他们的存根依赖从特性分支更新到发布的版本。

如上图所示,我们看到该工作流程需要多个步骤,并涉及双方之间的来回沟通。最重要的是,契约是人工管理和维护的。对于一个有多个消费者的 API 来说,所有的团队都需要在一个共享的契约库上合作,并遵循预定义的文件夹结构来组织契约文件。这在沟通和维护方面增加了额外的复杂性和成本。

Pact 的工作流程要简单得多:

1.服务消费者使用 Pact 提供的 mock DSL 来定义服务预期。

2.Pact 契约定义 DSL 也会生成一个可以在单元测试中使用的工作 mock。在消费者通过单元测试后,mock 文件被上传到 Pact Broker。

3.Pact Broker 会针对服务提供者重复所有存储的契约,并将响应与契约进行比较。

图 2:Pact 中消费者驱动的契约测试工作流程

Pact 引入了一个叫做 Pact Broker 的契约管理系统(商业版本叫做 Pactflow)。Pact Broker 解决了 Spring Cloud Contract 中手动管理的共享契约库的许多缺点,并使契约测试更适用于跨团队协作的场景。

在 eBay 的 Notification Platform 团队中,我们首先在 Spring Cloud Contract 中实现了所有的测试案例。然而,在了解了 Pact 并评估了这两个框架后,我们发现 Pact 中的工作流更适合我们的协作场景,于是我们用 Pact 重新实现了所有的测试案例。

HTTP 集成

在 Spring Cloud Contract 中,用户通常用 Groovy(或 Yaml、Kotlin 或 Java)DSL 定义 HTTP 服务契约。Groovy 契约 DSL 非常具有表现力和灵活性,但 IDE 的工具支持相对较弱(如契约定义 API 的自动完成);开发人员需要参考文档来处理稍微复杂的用例。Spring Cloud Contract 主要针对 JVM 技术栈,与 Spring 生态系统结合得更紧密。虽然它声称通过 Docker 容器支持其他技术栈,但用户体验会有很大不同。

另一方面,Pact 为主要的编程语言提供本地 API 绑定。API 消费者使用 Pact 契约 DSL 来定义单元测试中的 API 预期。Pact DSL 将 API 行为预期转化为本地可用的模拟服务,并可用于测试案例。通过测试用例后,记录的契约文件将被转移到 Pact Broker。提供商将重放所有的契约,以确保没有任何一个契约被破坏。Pact 的本地 API 绑定导致了更好的 IDE 工具支持,但学习起来有一定的难度。

Pact 还提供了一个状态管理 API,用于控制每个交互的前、后条件。与 Spring Cloud Contract 不同的是,提供者验证测试不是自动生成的,但 Pact 提供了库来自动完成大部分工作。

根据我们的经验,Spring Cloud Contract 就像一个辅助库,使你能够在 Spring 中实现契约测试。它与 Spring 有更紧密的集成,并且基于 Java 生态系统中流行的库。然而,Pact 是一个全功能的契约测试解决方案,它有自己的一套库和契约管理工具和规范。

消息集成

Spring Cloud Contract 支持广泛的集成:Apache Camel、Spring Integration、Spring Cloud Stream、Spring AMQP、Spring JMS 和 Spring Kafka 等等。消息传递支持在很大程度上是基于 Spring 的消息传递抽象的。在消费者方面,生成的存根可以由方法或消息触发,或通过 StubTrigger 接口手动触发。如果用户在契约中指定由消息触发,消费者的测试用例实际上可以由真正的消息触发,这更接近于模拟真实的集成。

然而,Pact 采取了不同的方法:它抽象了消息媒介,专注于用模拟消息对消息处理逻辑进行单元测试。实际处理程序的预期参数数据类型和模拟消息的数据类型之间可能存在差距。

总结一下消息契约的测试支持,Spring Cloud Contract 为 Spring 消息抽象提供了无缝集成,也可以模拟真实的消息交互,而 Pact 则很灵活,但需要一点手工集成的操作。

03 eBay 的契约测试

契约初始化程序项目(The Pact Initializer Project)

一个正确实施的契约测试工作流程需要在整个应用开发过程的各个阶段与 Pact Broker 进行互动。Pact 初始化项目由 eBay 的应用平台团队建立,是一套引导性服务,用于将 Pact 契约测试框架集成到 eBay 的开发生态系统中。

图 3:契约初始化程序的架构概述

1.Pact Initializer 门户网站为契约测试环境设置收集配置元数据。在开发人员输入所需的配置后,后端初始化服务被触发。

2.后台初始化服务解析配置元数据,生成相应的初始化任务并触发事件。

3.任务执行器也会将执行结果发送到分析后端,以便监测和进一步分析。

统一的提供者验证服务

当消费者改变契约时,提供商只需要验证与新变化的兼容性。Pact 提供了一个 webhook,将每个消费者与它的提供者验证 CI/CD 作业绑定。然而,对于每个消费者来说,他们需要重复地为 Pact Broker 设置服务账户和验证配置,以触发验证过程。我们可以使用代理服务来管理每个验证的共同步骤,并将消费者从管理这些配置中解放出来。

图 4:一个统一的验证服务,用于触发提供者一方的验证过程

1.服务消费者使用 Pact Initializer Portal 来初始化环境。

2.验证服务存储配置元数据。

3.服务消费者向 Pact Broker 发布契约变更。

4.Pact Broker 检测变化并将变化转发给验证服务。

5.验证服务从数据存储中读取目标验证作业信息并触发 CI 作业。

04 契约测试最佳实践

选择合适的框架

可以说,这两个框架都可以在实现契约测试工作流程方面有不错的表现,选择最佳框架有几个考虑因素:

● 应用程序栈。非 Java 应用可以直接使用 Pact,它提供了原生的 API 绑定,而且用户体验更好。如果你的应用是基于 Spring 的微服务,Spring Cloud Contract 可能是有用的,并且与 Spring 的生态系统有更紧密的整合。

● 协作的规模。如果你与多个团队或项目合作,Pact broker 可以把你从契约管理的麻烦中解救出来。

● 消费者驱动或供应商驱动。Spring Cloud Contract 允许定义一个提供者驱动的工作流程,有时这很有意义:要么同时拥有消费者和提供者的应用程序,要么提供者可以单独定义 API 行为(如公共 API)。

稳健性原则

对你发送的东西要保守,对你接受的东西要宽松。在契约测试的背景下,这意味着消费者代码应该只向提供者发送他们真正依赖的请求参数,而来自提供者响应的额外数据属性不应该破坏消费者。

专注于通信契约而不是功能

契约测试位于单元测试和服务集成测试之间。它并不试图取代功能测试,它取代了对真实提供者的响应的依赖,以验证通信数据格式。契约测试应该只关注集成点,而不是业务逻辑(即供应商的响应是否符合业务需求)。这些领域应该由供应商的功能测试来覆盖。

BDD 是对契约测试的良好补充

如上一段所述,契约测试不应测试供应商的特性或功能。BDD 是一种很好的方法,可以正式确定消费者的需求,并强制执行提供者的功能测试覆盖。因此,它是契约测试的一个很好的补充。

避免不必要的严格的断言

消费者应该松散地验证数据属性,而不是严格地验证,以增强测试案例的稳健性。例如,如果你不依赖数据属性的长度,断言该属性不是空的比断言该属性有固定的长度更可维护。通常,消费者依靠的是响应的结构,而不是值的内容。

总结

在这篇文章中,我们比较了不同的契约测试框架,并分享了我们在 eBay 的采用经验。我们相信契约测试对于测试微服务架构中的集成点是很有价值的,并且有效推动业务发展。


MTSC2023 中国互联网测试开发大会(上海站),将于2023年7月15日在上海举行,在为期1天的时间里,主办方将邀请一线技术专家、资深行业大咖与大家齐聚一堂,针对当前热门行业话题以及最新的落地实践,进入深入探讨与分享,为各方合作伙伴搭建行业交流平台。详细大会信息请参考TesterHome社区微信公众号最新信息发布。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/532589.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

测试管理的能力和素质

测试管理是软件开发中至关重要的一环,测试管理员需要具备一系列的能力和素质来确保项目成功交付。以下是测试管理者需要具备的能力和素质: 1. 技术能力 测试管理员需要对软件测试技术有深入的了解,包括测试策略、测试计划、测试用例设计、测试…

OLED 液晶屏显示模块(0.96寸)

OLED模块例程 一、OLED 简介: OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。因为具备轻薄、省电等特性&#xff…

互联网用户之间如何传输大文件

互联网用户之间如何传输大文件? 现在的工作,基本上都离不开互联网,网络越来越发达,互联网传输大文件时常发生,但是有没有一款合适的大文件传输工具,很伤脑,下面整理了一些互联网用户之间如何传…

USB SS-PHY Tuning

1 USB 3.0 PIPE PHY 1.1 USB 3.0 PHY USB 3.0 PHY PIPE wrapper PCS SerDes 1.2 SS PHY电流源 CML电流源串联在NMOS管的Source中,电流是16 mA,所以差分电压摆幅是16 mA x (50 // 50) x 2 800 mV。 1.3 PIPE PHY数据线宽度 DWC_usb3_databook_2.50a.p…

涂鸦智能生活App SDK:全量级灵活定制,让你的App更具差异化

之前一期,我们介绍过涂鸦 OEM App 开发方案(点击查看往期介绍),它集品牌 UI 自定义、服务、运营、商城营销于一体,无需代码,开发者点选拖拽即可快速配置想要的常用功能,最快 10 分钟即可完成一款…

【敬伟ps教程】历史工具、画笔、橡皮擦

文章目录 历史工具面板上的操作按历史记录选项历史记录画笔历史记录艺术画笔 画笔工具画笔基本操作画笔预设画笔面板 铅笔工具背景橡皮擦魔术橡皮擦 历史工具 窗口–历史记录 历史记录是从上到下是操作步骤,编辑时会有很多历史记录,点击下方删除按钮可删…

产线故障ar远程协助系统为运维提供可视化的画面

说起AR增强现实技术,其适为企业设计、生产、装配、销售和运维所有链条提供更优的解决方案,今天为您具体介绍AR远程专家协助技术应用工作制造中的好处。 1、设备、产线发生重大故障,需要厂家派人来现场,停工损失巨大; 2、借助手机进…

【PyQt】PyQt学习(三)QWidget介绍

概述 QWidget 类是所有 Qt GUI 界面类的基类,是 PyQt 程序中的最小元素,也就是所有可现实的控件的基类。一个继承自 QWidget 的类可以在屏幕上绘制自身,这是因为 QWidget 继承了 QPaintDevice 类,该类用于将控件绘制在屏幕上。每一…

leecode每日一题 1054 距离相等的条形码

题目描述 在一个仓库里,有一排条形码,其中第 i 个条形码为 barcodes[i]。请你重新排列这些条形码,使其中任意两个相邻的条形码不能相等。 你可以返回任何满足该要求的答案,此题保证存在答案。 示例 1: 输入&#xf…

JS逆向 -- 分析某站aid、cid、w_rid和sid的加密过程

接上节课内容 JS逆向 -- 分析某站buvid3和_uuid的加密过程 JS逆向 -- 分析某站b_lsid值加密过程 一、清除cookie信息,刷新网页,ctrlf搜索sid,这样找到的数据是在url里或者响应信息里面,全局搜索找到的一般都是在js里面的数据&a…

ChatGPT生成Excel统计公式——检查数据是否满足要求

背景需求 有一张表格如下,需要统计每个用户是否在第一到第三周中,每周发文数量都大于等于两篇,是的话给出Yes,否的话给出No 操作流程 给出描述,让ChatGPT生成对应的公式,条件如下: 在excel中…

【保护和自动控制 JDX-1000信号继电器 机械保持、电复归 JOSEF约瑟】

名称:信号继电器;型号:JDX-1000系列;品牌:JOSEF约瑟;额定电压:110、220VDC/AC;起动电流:3mA;稳定电流:2A;功率消耗:不大于…

TH2822D手持式 LCR数字电桥产品资料

TH2822D是一款手持式LCR数字电桥,可测量电容、电感和电阻,具有高精度、高灵敏度、低功耗和易于携带等特点。TH2822D适用于生产、现场维修和科研等多个领域。 TH2822D手持式LCR数字电桥的主要特点如下:1. 标准源四终点测量方法,准…

【优秀!44个HCIA-Datacom知识点总结】

1、IPV4地址的组成部分?IP地址长度?表达形式?如何区分网络位和主机位? 组成部分:网络位主机位 IP地址长度:32bit 表达形式:点分十进制 区分:子网掩码区分,为1是网络位&am…

以云原生推动代际跃升,2023通明湖论坛云原生分论坛召开

5月12日,由神州数码主办,北京经开区国家信创园、中关村云计算产业联盟协办的2023通明湖论坛-云原生分论坛在京召开。本次论坛,以“抓住云原生机遇,推动我国信息基础设施技术代际跃升”为主题,聚焦以云原生为核心引领的…

vue2和elementUI 打造落日余晖登录页和滑块校验

文章目录 前言1 项目搭建2 依赖引入3 项目调整①vue-router② App.vue③ main.js 4 写登录页5 写滑块校验6 源码下载7 问题解决①项目一直报错② 背景图存在白边 前言 标题很夸张,实则是AI的功能,今天咱也搞一个登录页,其实满简单的一个东东…

Gigabayte-Z87-DS3H i3 4130电脑 Hackintosh 黑苹果efi引导文件

原文来源于黑果魏叔官网,转载需注明出处。(下载请直接百度黑果魏叔) 硬件型号驱动情况 主板Gigabayte-Z87-DS3H 处理器英特尔酷睿i3 4130 Haswell已驱动 内存4x4GB DDR3/1600Mhz金士顿已驱动 硬盘SSD 480GB PNY CS900已驱动 显卡英特尔高…

想学透OSPF,先搞懂这6个技术点再说

大家好,我是老杨。 OSPF,这玩意儿作为目前主流的IGP协议,主要是为了解决RIP的三大问题而出现的。 应用面非常广,认可度也高,毕竟的确是好用的。 也有很多正在学习的小友想找我讲讲,OSPF该怎么学。 基础的…

Beerus:基于Helios light client的Starknet Stateless Client

1. 引言 前序博客: Helios——a16z crypto构建的去中心化以太坊轻节点 Beerus为基于Helios light client构建的Starknet Stateless Client,开源代码实现见: https://github.com/keep-starknet-strange/beerus(Rust&#xff09…

食饮品牌如何用Social Power抓住消费者心智?

2023 Foodaily创博会 2023.05.14-2023.05.16 数说故事将深度参与Foodaily创博会(第八届Foodaily FBIC全球食品饮料创新大会),和食饮品牌一起玩转Social Power,抓住消费者心智,用一种很新的方法营销与创新。 作为食饮…