138

别再加端到端集成测试了,快换契约测试吧 – ThoughtWorks洞见

 6 years ago
source link: http://insights.thoughtworks.cn/contract-test/?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

别再加端到端集成测试了,快换契约测试吧

2017年11月19日 by 李春辉 4 Comments

正如大家所知,最初QA都是手动执行测试用例,开发人员每修改一个版本,QA就要手动测试一遍,随着功能的不断增加,手动测试重复的工作量越来越大。为了解脱QA重复性劳动,提高工作效率,重复执行的测试用例被自动化了。自动化测试让QA的工作前进了一大步。

500120067-1024x683.jpg

本文讲的端到端集成测试(简称集成测试)是指系统集成后的自动化测试,是系统或模块真实组装后运行的测试。很多团队用UI端到端来测系统集成后的行为,这类工具很多,比如有Selenium webdriver等。端到端的集成测试反馈与修复的周期比较长、运行速度慢,测试运行不稳定,有时随机失败,维护成本也很高。它不像单元测试,单元测试测具体一个方法或API,定位准确,采用Mock机制,运行速度非常快(毫秒级),又是开发人员在本地执行,反馈修复及时,成本较低。

于是,我们把绝大部分能在单元测试里覆盖的用例都放在单元测试覆盖,只有单元测试测不了的(比如模块或API之间连通性),才会通过端到端的集成测试来覆盖。此时,测试又前进了一大步。

但是,随着业务的不断拓展、产品功能不断增加,系统架构越来越复杂,端对端集成测试的成本越来越高,测试用例也越增越多,集成测试又成了快速验证的阻塞区。在当今持续集成的开发模式中,开发团队会频繁集成,每次集成都会通过流水线(Pipeline)快速验证、准备部署包、进而发布。然而,集成测试的这些问题会严重影响或阻碍产品快速发布。

那么问题来了,怎么解决集成测试的现有问题,让测试再前进一大步?

其实,早在几年前,著名的敏捷和TDD专家JB Rainsberger就提到了。

“集成测试是个骗局”,正确的是应该用一种契约或协议测试来测试集成后的系统行为!

JB Rainsberger认为你写的2-5%的集成测试和单元测试有重复,或者和其它地方的集成测试存在重复,而且当集成测试失败时,你也不知道发生了什么,不能及时准确定位问题。

JB Rainsberger认为应该让契约测试来替代集成测试,那么,什么是契约测试?它是否能解决集成测试的这些问题?

契约测试是验证服务的Provider是否按照期望的方式与服务的Consumer进行交互,简单的说是Consumer与Provider两者之间的集成。

而Contract即合同、契约,就是Provider与Consumer的交互方式。

契约测试通常是基于Consumer驱动的(Consumer Driven Contracts,基于Consumer驱动的契约测试工具有PACT)。基于Consumer驱动的契约测试分两个阶段:

  1. Consumer生成契约,开发者在Consumer端写测试时Mock掉Provider,运行测试生成契约文件;
  2. Provider验证契约,开发者拿契约文件直接在Provider端运行测试进行验证。

1-Consumer.png

第一阶段:Consumer生成契约

2-Provider.png

第二阶段:Provider验证契约

如何用PACT编写契约测试,这里就不赘述了,实例详情请参见PACT an example

集成测试的特点

  1. 真实安装后测试,测试更接近真实使用情况;
  2. 可见性强,容易理解;(比如:看一遍运行关键业务的集成测试,业务人员或客户会觉得很放心。也可以替代验收测试)
  3. 模块真实调用,测试运行慢,秒级别或分钟级别,反馈与修复的周期慢,成本高;
  4. 问题定位难,多个子模块组合安装后的测试,很难定位是哪个模块出的问题;
  5. 真实的安装或环境搭建,不稳定,容易导致测试随机失败;
  6. 沟通成本高,需要不同模块团队间的协调工作;
  7. 与底层测试或集成测试会有重复,集成测试中有的路径已经被单元测试覆盖。

契约测试的特点

  1. 开发人编写,采用Mock机制,开发本地就可以运行,没有真实调用,运行快,毫秒级修复反馈周期短;
  2. Provider与Consumer两两之间的验证,容易定位问题,而且与底层测试或其它契约之间没有重复;
  3. 不需要部署真实的集成环境,稳定且成功率高;
  4. 沟通成本低。(比如一个Consumer端的加入导致服务端API修改,服务端开发人员不必跑去找所有其它Consumer端开发人员沟通确认是否会被影响,直接运行契约测试就能知道结果。)

由此可见,开篇谈到的端到端集成测试运行慢、不稳定、修复反馈周期长等等问题,都能通过契约测试得到解决或改进。

假如某社交聊天产品(简称TWChat)的架构是这样的:服务端、客户端、邮件通知服务三部分组成。

3-architecture-diagram.png

通常的测试策略:底层绝大部分的单元测试+少量上层端到端集成测试。

用TWChat注册场景来举例说明吧。注册一个帐号的工作流是:客户端把注册帐号信息提交给服务端,服务端处理帐号时,会去调用邮件通知服务发通知,并完成注册。

底层单元测试用例

4-unit-testing.png
  1. 客户端的单元测试:验证注册表各个Field的各种输入组合、以及检验正确性等;(比如:边界值、空、中英数各类组合、合法与非法输入等)
  2. 服务端的单元测试:验证注册数据表的各种输入组合可以成功存放于服务端帐号DB表中,且不合法的、重复等会有相应的错误码;
  3. 邮箱通知服务端的单元测试:输入合法的各类不同的邮箱确,保证能正常发出通知邮件并返回正确码,输入不合法的邮箱或空邮箱确保有相应的错误码。

上层端到端集成测试用例

5-Integration-Testing.png

一条注册连通性的Happy path测试用例, 输入所有必填项提交,验证注册成功,收到成功通知邮件。

以上的集成测试,必填项输入其实是与单元测试重复,邮件通知发送功能与单元测试也有重复;再者,这条集成测试跑失败,我们并不能定位是客户端的问题、服务端问题、还是通知服务的问题。加上集成测试是把所有子模块(服务端、客户端、通知微服务)真实产品安装包部署以后才能运行的测试,反馈、修改周期长,不稳定容易随机失败等等。

集成测试换成契约测试用例

6-PACT-an-example.png
  1. TWChat客户端Consumer与TWChat服务端Provider加一条契约测试,确保TWChat服务端按期望提供给客户端接口(参见PACT an example)。
  2. TWChat服务端Consumer与邮件通知服务Provider之间加一条契约测试,确保邮件通知服务按照预期与TWChat服务端交互(参见PACT an example)。

契约测试与单元测试以及其它测试之间没有重复,它是单纯验证Provider与Consumer之间按预期的方式交互,定位准确;不需要部署真实的系统环境、Mock机制、没有真实API调用,运行非常快、反馈及时、修复周期短、成本低,在这种情况下,自动化测试流水线运行更快了,产品流水线出产品安装包也更快。因此,显然契约测试才是真正对的选择。

微服务架构下契约测试的重要性

例如,随着TWChat业务的扩大,TWChat钱包,TWChat安卓端,TWChat iOS端,以及其它的服务方与Consumer方接入TWChat服务器。

当其中TWChat安卓端修改后,如果还按照之前的集成测试方式,就得把服务端与所有的客户端真实的集成到一起测试,确保都没有被影响才能生成产品安装包并发布,这里的集成测试成了流水线(pipeline)的一个聚集地,也成为了产品发布的阻塞区。

7-pipeline.png

集成测试流水线

假如,换成契约测试,我们把契约测试放在各自的流水线(pipeline)上,每次代码提交触发相应产品流水线上的契约测试,当TWChat安卓客户端Consumer API修改,在安卓客户端的流水线(pipeline)上运行安卓客户端为Consumer与服务端为Provider的契约测试,测试通过,生成产品安装包;如果契约测试失败,服务端需要相应修改,则本次TWChat安卓端的安装包需要在TWChat服务端修改后,方可生成安卓客户端的产品安装包。

9-Consumer-API.png

契约测试解耦后

由此可见,并不是每一次TWChat安卓端的修改都要全部Consumer端与服务端集成后验证才出包,而是各自可以独立出包,产品解耦,大大节省时间,提高出包频率。

并非所有端到端集成测试都适合换成契约测试

契约测试相比端到端集成测试有很多优势,但并不是所有场景都适合契约而非集成测试。

  1. 契约测试无法做安全或性能测试等。
  2. 契约测试采用Mock机制,所以没有集成测试更接近真实环境,也不能给业务人员做验收,可视性差。
  3. 契约测试基于不同的服务使用的协议不同,验证契约的复杂度会不同,复杂度过高时,需要权衡是否有必要加契约测试。

所以,把端到端集成测试要换成契约测试也不是绝对的,视情况而定。

总的来说,当你追加端到端集成测试的时候,如非特殊,快换契约测试吧。


更多精彩洞见,请关注微信公众号:思特沃克


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK