• 0
  • 0
分享

  背景

  在现代的开发模式中,基于微服务的开发模式越来越常见,但是随着项目规模的扩大,服务与服务之间的依赖越来越密切,当不同的开发团队去开发不同的服务时,服务的提供者的变动会影响到众多消费它的消费者,为了保证系统的正确性和一致性,这将需要大量的沟通成本和代码修改的时间成本。

  之前遇到的某个客户内部就是因为服务与服务之间依赖过多,且存在各种的物理依赖,再加上其他种种原因,使得在集成测试时bug激增。对于他们而言集成测试需要依赖于各个服务版本的一致性以及真实的物理环境,因此他们的集成测试通常需要用上几个小时才可以完成,这就使得整体的效率大大缩减。除此之外,在集成测试中发现的问题也会使得他们花很长的时间去定位到问题所在。

  相似的问题在平时的开发过程中也是经常遇到,由于依赖方的接口变更导致在系统集成时频频出错,整体的代码又不得不再加修改,这就使得开发的进度迟迟无法向前推进。

  为了解决这类的问题,契约测试应运而生。契约测试不是一个新鲜东西,但在实际项目经历中发现用好契约测试真的会大大增强开发的效率,因此写下这篇文章来简单总结一下契约测试的一些内容。

  首先什么是契约测试

  契约测试是一个为确保两个独立的系统或者微服务能够兼容并可以相互通信的一个方法,契约测试分为两种,一种是服务提供者驱动的,另一种是消费者驱动的。如下图所示,左侧是一个服务的消费者,右侧是一个服务提供者,消费者调用提供者的接口并消费数据的交互过程会被记录成一份契约,在契约中包含了服务的提供者和消费者是谁,以及消费者对服务的提供者的期望(如请求的参数和返回的结果)。服务的提供者会根据这份契约去反复验证自己是否能够满足消费者的需求,这也就是所谓的消费者驱动。

1-1.png

  契约测试主要是为了验证服务层提供的数据是否能够消费者正常使用,它不会深入去测试服务的行为,而只是专注于测试服务的输入与输出,因此相比于沉重的集成测试而言,契约测试会更加的轻巧,快速。契约测试形式上类似于API级别的UT,但其本质上还是个集成测试,比API测试在金字塔的位置更靠顶端,所以容易导致契约测试的数量增加和不稳定性增加。

  契约测试具体是如何实践的

  接下来我们分别从代码和流水线设计两方面来阐述一下具体的契约测试的实践:

  代码层面:

  为了完成契约测试,我们可以借助一个叫pact的工具。pact是一个代码优先的用来支持契约测试的一个工具,它目前支持java,python,go等主流的开发语言。

  Pact中的一些基本概念:

  ·Contract: 契约文件,在Pact中也叫做pact,可以保存在本地,也可存在broker中?

  · Provider: 真正运行的生产者服务?

  · Consumer: 接收生产者发出的数据?

  在pact中,consumer和provider分别做了不同的事:

  Consumer端:

  consumer端会做这么几件事:

  · 首先使用pact dsl定义它消费的接口的request和response,并注册到mock server中?

  · 然后consumer端的测试会发送一个真实的请求到pact起的一个本地的mock server?

  · 接着pact会去对比实际的request和expected request 是否一致,如果一致则返回expected response?

  · 最后consumer会去确认这个返回值是否正确 上面所有步骤都pass后,整个的consumer测的pact测试才算结束,此时consumer定下的契约会被发布到一个叫pact broker的地方进行契约的统一管理。?

  Pact broker是pact提供的一个专门用来统一管理契约的一个服务,在这个服务中,开发者们可以清晰的看到所有的服务提供者和消费者的详细信息。

1-2.png

  总的来说,cousumer端的主要功能是生成契约(文件的载体),验证request和response的工作是可选的,借由consumer端的集成测试的形式,确保生成的契约的确是consumer真正期望的,通俗来讲,就是“测试测试的测试”。

  Provider端:

  在provider端,pact会mock出一个consumer并发送请求给provider端真实运行着的进程,provider在接受到请求后会根据自己的代码实现将真实的response返回给pact,接着pact会拿着这个response去和pact broker上获取到之前consumer定义的契约并进行比对,如果provider能够满足契约,则验证通过。

1-3.png

  当consumer和provider的测试都通过后,产品则就可以被部署到指定环境了。

  以上是消费者驱动的一个实践方式,消费者驱动的契约测试主要适用于以下场景:

  ·消费者和提供者都是可控的?

  · 消费者的需求变动能够变成提供者的需求?

  · 消费者数量不是很多,作为提供方能够管理的过来?

  符合以上的条件的场景下,比较适合使用消费者驱动的契约测试。消费者驱动的背景下,服务提供方可以基于消费者提出的契约快速做出反馈。

  然而,在实际的情况可能不是这么美好,之前遇到的客户,他们内部的部分情况恰恰违背了以上的场景。他们的产品极度依赖着一些外部的底层依赖,且底层的依赖变动频率较高,这使得他们会频频的在集成测试时发现底层已经发生了变动。在这种情景下,提供者驱动的契约测试更加适合。由服务的提供方来约定契约,然后众多的消费者去满足契约,当提供方发生变动时,消费方能够及时感知到并快速反馈。整体的实践流程只需将上方的consumer者和provider的操作进行转置即可。

  换句话说,消费者驱动和提供者驱动的区别在于谁去响应契约的变化。就如上方提到的,外部的提供者依赖是不可控的情况下,提供者驱动的模式会更加合适,相反则是消费者驱动的模式。

  流水线的设计

  当选择消费者驱动的契约测试策略时,作为一个consumer,它要做的就是去发布契约,告诉provider它的需求。那么作为provider,它就需要去检查自己的实现是否能够满足consumer的需求,那么当它的实现无法满足契约时,则此时的流水线契约测试阶段就应该显示fail,并告知对应的provider,让其快速做出修正 。如图所示,当consumer发布了新版本的契约,这将导致provider端的流水线fail,那么此时provider就会得知他们需要根据新的契约来修改实现了。

1-4.png

  而和消费者驱动相反,提供者驱动的设计则是当provider发布了一个新的契约之后consumer侧的流水线会变红,直到consumer将他们的代码根据新的契约修正后才可以进入后面的集成测试。

1-5.png

  契约测试带来的好处 

  (1) 测试的速度快,无需依赖多个系统之间的交互

  细心的同学通过上面的描述会发现,在契约测试时服务的依赖方式不需要被真实调用的,契约测试通过mock依赖的方式来模拟依赖方的行为,这就使得测试的速度得以大大提升

  (2) 可以并行开发

  由于mock的存在,使得服务的消费方和提供方可以根据事先定义好的契约进行并行开发

  (3) 发现问题后可以快速定位到问题:

  因为问题只会出现在当前测试的服务或者组件中,你甚至可以确切的知道是哪个api测试fail了

  (4) 在确定完契约之后,开发人员可以在本地就可以进行测试,无需将代码推至远端

  (5) 测试前移

  把本来要通过集成测试才能验证的工作化作单元测试和接口测试,用更轻量的方式快速进行验证,更早的发现问题使得后续的测试更加快速

  契约测试和其他测试的对比

1-6.png

  总结

  总体来说,契约测试是一个介于单元测试和集成测试的一个阶段,他关注的细粒度比单元测试更粗,但是又无法取代集成测试。尤其是当你的产品对环境依赖特别大的时候,集成测试还是必不可少的一部分,契约测试的存在只是为了让你在开发过程中的联调更加快速,集成时问题更少。


作者:Thoughtworks洞见    

来源:http://www.51testing.com/html/28/n-7792428.html

  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          •   测试人初到一个公司,往往公司的测试团队和规模已经完善,我们需要做的就是跟着公司的节奏走。因为相应的制度和流程已经完善,不需要额外操心太多与测试执行层面无关东西。  但是当流程和制度没有的情况下,我们应该怎么办呢?  本篇文章适用于初到一个公司、公司新引进测试流程,却不知道如何从0开始的同仁。以下是我近期的总结,方案有可能不是最完美的,但可以参考,有一定的借鉴作用。  整篇文章逻辑结构:  首先介绍什么是落地;  其次更为重要的思想;  最后经过这一年总结还有哪些不足之处,进而指出我打算接下来执行的方案。  何为落地  不知道大家接触过“落地页”这个词没有,我是在需求介绍文档里第一次见到这个...
            0 0 779
            分享
          •   填测试行业问卷,不仅能获得价值398元的测试资料,还可以参与我们的抽奖活动,快来参与一下吧。链接:http://vote.51testing.com/  测试用例设计的完整过程  一个项目启动后,开发会根据项目的需求文档(RFP:Request for Proposal)编写开发计划(SDP:System Development Plan)和系统需求说明书(SRS:System Requirement Specification);与此同时,测试根据需求文档,SDP和SRS来提取测试范围(或者测试需求),思考可能使用到的测试方法和测试工具,测试环境等,这些都会编写在测试计划文档里。  根据...
            0 0 869
            分享
          •   之前进行接口测试一直用印度的postman,后来发现一款国产神器ApiPost,完全可以秒杀postman这个印度货。必须安利一波!  1、可以便捷的生成格式规范的文档  记得以前当程序员的时候,每次写接口,基本都是自己大概一写,然后api地址和大致参数发群里就完事儿,剩下全靠前端猜,实在猜不出来了就喊两声:xx,那个yy参数是啥意思?  ApiPost的出现,解决了这个问题:很便捷的生成接口文档。而且更重要的是,这款软件生成的接口文档基本非常规范,并且支持多种格式。如下图:  这就是ApiPost越来越受欢迎的原因之一:可以便捷的生成格式规范的文档。  2、方便规范化开发文档的管理  后...
            0 0 1219
            分享
          • 一、软件测试工程师大致有4个发展方向:1、资深软件测试工程师一般情况,软件测试工程师可分为测试工程师、高级测试工程师和资深测试工程师三个等级。达到这个水平比较困难,这需要了解很多知识,例如C语言,JAVA语言,数据库,数据结构,软件工程,等等,但是你要在一家公司干3 -- 5年的话,在压力中这些技能你都会掌握!2、测试部门管理者小的如组长,大的如测试经理,这需要你有先天的优势,善于交流沟通,善于处理人际关系!不过做两年,你也会成为老油条的!3、测试书籍编写者出书也是很赚钱的,当你在这一行干了几年,积攒了足够的经验,可以把你的经验,具体做过的项目总结出来,现在关于软件测试的书很少,你要写本与众不...
            0 0 958
            分享
          • 摘要:许多敏捷软件开发中的自动化测试的工作都失败了,或者并没有发挥它们最大的潜力。本文研究分析了自动化测试也许不能满足测试人员和其他利益相关者期望的两个主要原因,然后列举了六个能够避免陷入这些陷阱的步骤。以下是在敏捷环境中成功实现测试自动化的方法。为了能够跟上因敏捷软件开发而不断缩短的发布周期,很多开发团队都采用了自动化测试的方法,从而不断保证每个软件版本都符合所需的质量水平。这是传统软件开发实践的一个重要转变:测试经常被卡在开发过程的最后,被视为了测试过程的负担,而并不是好处。因此,一个在采用敏捷软件开发,转变为DevOps文化并采用持续集成和持续交付的组织中工作的测试人员,必须对于如何有效...
            0 2 3203
            分享
      • 51testing软件测试圈微信