当前位置: 首页 > 科技观察

不加端到端的集成测试,改成契约测试

时间:2023-03-21 00:50:38 科技观察

众所周知,QA最初是手动执行测试用例的。开发者每修改一个版本,QA都得重新手动测试一遍。不断增加,人工测试重复的工作量越来越大。为了摆脱重复的QA工作,提高工作效率,将重复的测试用例自动化。自动化测试使QA工作向前迈进了一大步。本文所说的端到端集成测试(简称集成测试)是指系统集成后的自动化测试,即系统或模块实际组装后的测试运行。许多团队使用端到端的UI来测试集成后系统的行为。这样的工具有很多,比如Seleniumwebdriver等等。端到端集成测试反馈修复周期比较长,运行速度慢,测试运行不稳定,有时随机失败,维护成本也高。它不像单元测试。单元测试测试的是一个特定的方法或API,定位准确。它使用Mock机制并且运行速度非常快(以毫秒为单位)。由开发商在本地执行,反馈修复及时,成本低。因此,我们将大部分可以在单元测试中覆盖的用例放在单元测试覆盖率中。只有单元测试无法测试的(例如模块或API之间的连接)才会被端到端集成测试覆盖。至此,测试又向前迈进了一大步。但是,随着业务的不断扩展,产品功能的不断增加,系统架构越来越复杂,端到端的集成测试成本越来越高,测试用例越来越多.集成测试已经成为快速验证的障碍。区。在如今的持续集成开发模式中,开发团队会频繁进行集成,每次集成都会通过流水线(Pipeline)快速验证,准备好部署包,然后发布。然而,集成测试的这些问题会严重影响或阻碍产品的快速发布。那么问题来了,如何解决集成测试存在的问题,让测试更上一层楼呢?其实早在几年前,著名的敏捷和TDD专家JBRainsberger就提到过。集成测试是一个骗局”,使用契约或协议测试来测试集成系统行为是正确的!JBRainsberger认为您编写的集成测试中有2-5%与单元测试重叠,或者与其他地方集成存在重复测试,当集成测试失败时,你不知道发生了什么,也不能及时准确定位问题。JBRainsberger认为应该使用契约测试而不是集成测试。那么,什么是合同测试?它能解决集成测试的这些问题吗?契约测试是验证服务的提供者是否以预期的方式与服务的消费者进行交互。简单的说就是Consumer和Provider的整合。contract就是契约和契约,是Provider和Consumer之间的交互方式。契约测试通常基于消费者驱动契约(ConsumerDrivenContracts,消费者驱动契约测试工具包括PACT)。消费者驱动的合约测试分为两个阶段:消费者生成合约,开发者在消费者端编写测试时mockProvider,运行测试生成合约文件;提供商验证合约,开发者直接拿着合约文件在提供商端跑测试验证。第一阶段:Consumer生成合约第二阶段:Provider验证合约如何使用PACT编写合约测试,这里不再赘述。详情请参考PACT范例。集成测试的特点:真实安装测试,测试更贴近真实使用;可见性强,易于理解;(例如:看集成测试运行关键业务,业务人员或客户会安心。也可以代替验收测试)模块实际调用,测试运行缓慢,在秒级或分钟级,反馈修复周期慢,成本高;问题定位难,安装多个子模块测试后,很难定位是哪个模块的问题;真实安装或环境搭建不稳定,容易导致随机测试失败;高昂的沟通成本需要不同模块团队之间的协调;与底层测试或集成测试会有重复,并且集成测试中的某些路径已被单元测试覆盖。合约测试的特点:由开发者编写,使用Mock机制,无需真实调用即可在本地运行,运行速度快,毫秒级修复反馈周期短;Provider和Consumer之间的验证容易定位问题,兼容底层测试或其他合约之间没有重复;无需部署真实集成环境,稳定,成功率高;通讯成本低。(比如增加一个消费端导致服务端API的修改,服务端开发者不必去所有其他消费端开发者去沟通确认是否会受到影响,并且直接运行合约测试就可以知道结果。)可见开头提到的端到端集成测试运行慢、不稳定、修复反馈周期长等问题,可以通过契约测试来解决或改进。举个例子,假设一个社交聊天产品(简称TWChat)的结构如下:服务端、客户端、邮件通知服务三部分组成。架构图通常的测试策略:大部分底层单元测试+少量上层端到端集成测试。我们以TWChat注册场景为例。注册账号的工作流程是:客户端将注册的账号信息提交给服务器,服务器在处理账号时会调用邮件通知服务发送通知,完成注册。底层单元测试用例单元测试客户端单元测试:验证注册表中各个Field的各种输入组合,验证正确性等;(例如:边界值、null、中英文数字的各种组合、合法和非法输入等)服务器端服务单元测试:验证注册数据表的各种输入组合能否成功入账服务器端的DB表,非法重复的会有相应的错误码;邮件通知服务器端单元测试:各种输入合法的不同邮箱,保证通知邮件能正常发送,并返回正确的code。输入非法或空邮箱,确保有对应的错误码。上层端到端集成测试用例集成测试一个注册连通性的happypath测试用例,输入所有必填项提交,验证注册成功,并收到成功通知邮件。在上面的集成测试中,必填项的输入实际上是和单元测试重复的,邮件通知发送功能也是和单元测试重复的;而且这次集成测试失败了,我们也无法定位是客户端的问题,还是服务端的问题,还是Notify服务的问题。另外,集成测试是所有子模块(服务端、客户端、通知微服务)真正的产品安装包部署完成后才能运行的测试。反馈修改周期长,不稳定,容易出现随机故障等将集成测试替换成契约测试用例契约测试TWChat客户端Consumer和TWChat服务端Provider增加契约测试,确保TWChat服务端提供接口给客户端符合预期(参见PACT示例)。在TWChat服务器Consumer和电子邮件通知服务提供者之间添加一个契约测试,以确保电子邮件通知服务按预期与TWChat服务器交互(参见PACT示例)。合同测试、单元测试和其他测试之间没有重复。它只是简单地验证Provider和Consumer是否以预期的方式进行交互,定位是否准确;无需部署真实的系统环境,Mock机制,无需真实的API调用,运行速度快,反馈及时,修复周期短,成本低。在这种情况下,自动化测试流水线运行得更快,产品安装包从产品流水线中产生的速度也更快。因此,显然契约测试确实是正确的选择。微服务架构下合约测试的重要性例如随着TWChat业务的扩展,TWChat钱包、TWChatAndroid、TWChatiOS等服务方和消费者都连接到TWChat服务器。TWChatAndroid端修改时,如果仍然按照之前的集成测试方式,必须真正将服务端和所有客户端集成进行测试,确保不受影响,才能生成产品安装包并发布。这里的集成测试已经成为流水线的聚集地和产品发布的阻塞区。如果将集成测试流水线换成契约测试,我们将契约测试放在自己的流水线(pipeline)上,每次代码提交都会触发相应产品流水线上的契约测试。当TWChatAndroid客户端的ConsumerAPI被修改时,Android客户端在pipeline上运行以Android客户端为Consumer,server为Provider的合约测试。如果测试通过,将生成产品安装包;如果合约测试失败,则需要相应地修改服务器。服务器端修改后,即可生成Android客户端的产品安装包。合约测试解耦后可以看出,不是每次TWChat安卓端的修改都需要在消费者端和服务端集成后验证后再打包,而是每一个都可以独立打包,产品解耦,大大节省了时间,提高了产出。数据包频率。并非所有的端到端集成测试都适合契约测试契约测试相对于端到端集成测试有很多优势,但并不是所有的场景都适合契约而不是集成测试。例如:合同测试不能做安全或性能测试。契约测试采用Mock机制,没有更贴近真实环境的集成测试,业务人员无法接受,可见性差。合约测试根据不同服务使用的协议不同,验证合约的复杂度也会不同。当复杂度过高时,需要权衡是否需要增加契约测试。因此,用契约测试代替端到端的集成测试也不是绝对的,要视情况而定。一般来说,当你添加一个端到端的集成测试时,如果不是特别的,只需更改契约测试即可。【本文为专栏作者“ThoughtWorks”原创稿件,微信公众号:Thinkworker,转载请联系原作者】点此查看该作者更多好文