有近两周没有在公众号中发表文章了,看过我以前公众号的读者都知道,公众号中近期在连载《RobotFramework接口自动化系列课程》,本来计划每周更新一篇,最近因为博主在带一个新项目,实在是没空抽出时间来,因此向公众号中对连载课程一直期待的读者说声抱歉。json
因为最近带微服务的项目,而对于微服务其实也是近从14年才流行起来,对于这块目前网上的干货内容仍是较少,借着机会,小结一下知识点。因此今天也先不打算连载《RobotFramework接口自动化系列课程》,若是读者对连载的课程比较热衷的话,能够在留言板下面给笔者留言,若是读者反馈较多的话,博主也会适当加快调整课程分享节奏。c#
下面就给你们浅聊一下微服务架构下的契约测试。安全
Microservice微服务是一种架构风格,咱们能够把每个微服务视作一个用一组API提供业务功能的组件,且服务之间会有不少依赖关系,以下图所示: 服务器
这些服务之间可能由一个团队或者相互独立的团队开发和维护,而且它们在系统内部相互依赖,在这种状况下,接口的开发和维护可能会带来一些问题,例如服务端调整架构或接口调整而对消费者不透明,致使接口调用失败。架构
注:关于微服务的基本组件组成及介绍,后面考虑单独抽离一篇文章进行介绍,本文就不过多说了~框架
例如, 咱们想测试某微服务架构中的某一个服务时,好比下图第一排中间的服务,如:
由于它和其余服务都存在交互,通常咱们有两种方式:maven
部署全部的服务来实现端到端测试。ide
在集成测试中Mock其余服务。微服务
下面分析一下这两种方式优缺点:工具
对比分析 | 优势 | 缺点 |
---|---|---|
第一种方式:部署全部服务 | 一、模拟生成环境 二、能够真实地测试服务交互 |
一、测试其中一个服务,不是不布署所有服务,包括各基础设施 二、要运行很长时间 三、不能及时给予测试反馈 四、测试环境被一个测试服务锁定,别人没法同时使用。 |
第二种方式:Mock其它服务 | 一、测试反馈快 二、没有基础服务依赖要求 |
一、服务的实现方建立的Stubs,可能实现与这个无关 二、没法模拟真实数据交互环境 |
常规咱们开发的项目主要由服务提供方约定接口,虽然提供方架构调整或改变接口以前一般会通知消费者,但可能仍是会存在遗漏。
当一个Service已经同时被多个使用者调用用的时候,怎么保证service的修改对其它全部使用者形成影响都被感知到呢?
那么契约测试的引出就是为了解决这类问题的最佳方案!
契约测试 ,又称之为 消费者驱动的契约测试(Consumer-Driven Contracts,简称CDC),根据 消费者驱动契约 ,咱们能够将服务分为消费者端和生产者端,而消费者驱动的契约测试的核心思想在因而从消费者业务实现的角度出发,由消费者本身会定义须要的数据格式以及交互细节,并驱动生成一份契约文件。而后生产者根据契约文件来实现本身的逻辑,并在持续集成环境中持续验证。
后文中消费者驱动的契约测试统一用cdc来代替。
cdc核心原则:
cdc是以消费者提出接口契约,交由服务提供方实现,并以测试用例对契约进行产生约束,因此服务提供方在知足测试用例的状况下能够自行更改接口或架构实现而不影响消费者。
cdc是一种针对外部服务的接口进行的测试,它可以验证服务是否知足消费方期待的契约。 它的本质是从利益相关者的目标和动机出发,最大限度地知足需求方的业务价值实现。
API测试和单元测试,更强调的是覆盖API内部逻辑。
契约测试,更强调是组件之间链接的正确性,除了保证组件内部,还要保证组件间的调用是正确的,也就是服务API之间的调用。
单元测试 | 单元测试针对代码单元(一般是类)的测试,单元测试的价值在于能提供最快的反馈。另外好的单元测试还能够帮助你改善设计,在你的团队掌握TDD的前提下,单元测试能辅助重构,帮助改善代码整洁度。 |
---|---|
API测试 | API测试是针对业务接口进行的测试,主要测内部接口功能实现是否完整,好比说内部逻辑是否是正常,异常处理是否是正确。 |
契约测试 | 契约测试实际上是为了测试服务之间链接或者说接口调用的正确性,为了验证服务提供者的功能是否是真正可以知足消费者的需求。它其实体现了测试前移的思想,把原本要经过集成测试才能验证的工做化做单元测试和接口测试,用更轻量的方式快速进行验证。 |
集成测试 | 它从用户的角度验证整个功能的正确性,测的是端到端的流程,而且加入用户场景和数据,验证整个过程是否是OK,它的价值业务价值最高,是验证一个完整的流程。 |
联调成本太高,要双方开发到某一阶段后放在同一个环境上才能进行,要同时把握双方的进度,形成资源和时间上的浪费。
对于接口的变更把控至关困难。因为接口变更是广泛存在的,尤为对于调用关系复杂的接口,一旦发生变更,若是没有一套机制进行控制,验证的成本巨大。
接口不匹配”是指服务依赖于彼此间的接口进行通讯,如何保证改变一个服务的接口会对其余全部依赖服务是否形成形成影响。
在发生契约变化时,提供一种可当即被服务端和消费端发现的方式。
下降服务集成的难度,把服务集成这个过程分解成了单元测试和接口测试来作,它从消费者的需求为出发点,把消费者的需求做为你的测试用例驱动出一份契约,而后验证提供者端的功能。
经过使用契约测试,接口调用双方协商接口后就能够并行开发,而且在开发过程当中就利用契约进行预集成测试,不用等到联调再来集成调通接口,一旦成熟,在保证质量的前提下,联调的成本能够减低到几乎为0。
由于契约的存在,让接口的变更有迹可循,即便变更也能够确保变更的安全性和准确性。
经过契约测试,团队能以一种离线的方式(不须要消费者、提供者同时在线),经过契约做为中间的标准,验证提供者提供的内容是否知足消费者的指望。
Consumer: 微服务接口的调用者
Provider: 微服务接口的提供者
契约文件: 是由consumer端和provider端共同定义的接口规范,包括接口访问的路径,输入和输出数据。在具体的实施中,是由consumer端生成的一个json文件,并存放在pact broker上
Pact Broker: 保存契约文件的服务器
注:一般在工程实践上,当消费者根据须要生成了契约以后,咱们会将契约上传至一个公共可访问的地址,而后生产者在执行时会访问这个地址,并得到最新版本的契约,而后对着这些契约来执行相应的验证过程。
第一步在消费者端Consumer端写一个对接口发送请求的单元测试,在运行这个单元测试的时候,Pact会将服务提供者自动用一个MockService代替,并自动生成契约文件,这个契约文件是Json形式的。
第二步在Provider端作契约验证测试,将Provider服务启动起来之后,经过pact插件能够运行一个命令,好比你是用maven,就是mvn pact:verify,它会自动按照契约生成接口请求并验证接口响应是否知足契约中的预期,因此能够看到这个过程当中,在消费者端不用启动Provider,在服务提供端不用启动Consumer,却完成了与集成测试相似的验证。
基于消费者的业务逻辑,驱动出契约
其实现步骤以下所示:
一、使用Pact的DSL,定义Mock提供者,如localhost:8080
二、将Mock地址传给消费者并对Mock的提供者发送请求。
三、使用Pact的DSL,定义响应内容(包括Headers、Status以及Body等)。
四、在消费者端 使用@PactVerification运行单元测试(Pact集成了JUnit、RSpec等框架),生成契约文件。
五、当运行测试后,Pact框架记录消费者的名称、发送的请求、指望的响应以及元数据,将其保存为当前场景下的契约文件,一般命名为[Consumer]-[Provider].json,例如 orderConsumer-orderProvider.json
六、契约文件生成后,咱们能够将其保存在文件系统或者Pact-Broker(Pact提供的中间件,用来管理契约文件)中,以便后续提供者使用。
基于消费者驱动出的契约,对提供者进行验证
在提供者端,咱们不须要写任何验证的相关代码,Pact已经提供了验证的接口,咱们只须要作好以下配置:
一、为提供者指定契约文件的存储源(如文件系统或者Pact-Broker)。
二、启动提供者,运行PactVerify(Pact有Maven、Gradle或者Rake插件,提供pactVerify命令)。
三、当执行pactVerify时,Pact将按照以下步骤,自动完成对提供者的验证:
构建Mock的消费者。
四、根据契约文件记录的请求内容,向提供者发送请求。
五、从提供者获取响应结果。
六、验证提供者的响应结果与Pact契约文件定义的契约中是否一致。
传统状况下作集成测试须要把服务消费者和服务提供者两个服务都启动起来再进行测试,而Pact作契约测试时将它分红两步来作,每一步里面都不须要同时启动两个服务。
一、测试解耦,就是服务消费与提供者解耦,甚至能够在没有提供者实现的状况下开始消费者的测试。
二、一致性,经过测试保证契约与现实是一致性的。
三、测试前移,能够在开发阶段运行,并做为CI的一部分,甚至在开发本地就能够去作,并且能够看到一条命令就能够完成,便于尽早发现问题,下降解决问题的成本。
四、Pact提供的Pact Broker 能够自动生成一个服务调用关系图,为团队提供了全局的服务依赖关系图。
五、Pact提供Pact Broker这个工具来完成契约文件管理,使用Pact Broker后,契约上传与验证均可以经过命令完成,且契约文件能够制定版本。
六、使用Pact这类框架,能有效帮助团队下降服务间的集成测试成本,尽早验证当提供者接口被修改时,是否破坏了消费者的指望。
七、Pact目前仅支持REST HTTP 通讯,但对于RPC的通讯机制,暂不支持。
注:写到最后,夜也深了,若是你以为本文对你有点启发或者做用,欢迎打赏支持一下~
若是你想全面进阶测试技术,给你们推荐一个全栈测试工程师技术修炼专栏《软件测试52讲》,笔者本身也要订阅学习,专栏内容很是不错,值得学习!
详细见:原文连接
新开了一个知识星球:【测试开发学苑】,在这里不但能够参与有趣且有意义的话题讨论,还能够获得任何与测试和开发相关问题的解答,欢迎你们加入,共同成长。