专栏首页DevOps时代的专栏华为专家 | 轻量化微服务测试实践

华为专家 | 轻量化微服务测试实践

前言

在我过去工作的这十年间,IT行业经历了很多的变迁,从单体架构到微服务架构,从传统组织到敏捷组织,我正好都有不同的体验,现在我在华为任软件架构师,华为有各种各样的产品线,我的工作职责之一是帮助产品团队构建软件工程能力,以及落地Cloud Native、微服务还有DevOps的相关实践,另外我同时也是几本书和资料的译者或作者。

我之前在比较早的传统团队里面去做研发工作时,测试主要采用手工的方式,其实这种日子是比较苦的,可能一直要加班到深夜,正式上线的时候还会提心吊胆,担心哪些功能会挂掉。

后来引入了自动化测试后,对我们的服务质量有很大提升,这时你在这个团队工作的时候是会比较舒服的,做完任何代码上的变更以后,你可以在本地运行大部分的测试,然后在流水线上自动运行测试,直到最后你可以在上线的时候有足够的信心保证系统功能不会因为所修改的代码而产生比较大的破坏。

接下来我会从以下四个方面和大家分享微服务自动化测试方面的实践:

微服务测试面临的挑战。 微服务测试策略。 轻量化微服务测试实践。 轻量化微服务测试总结。

一、微服务测试面临的挑战

1、微服务架构带来的新问题

微服务架构其实在解决了一些旧问题的同时也带来了一些新问题,比如微服务数量不断膨胀的情况下,如果不能有效降低每个微服务的开发和测试成本的时候,那么随着数量的攀升,你的总体成本会越来越大,直到最后不可承受。

另外,微服务之间以轻量化通信的方式进行调用,这种互相调用关系也会随着微服务架构的演化变得越来越复杂,有时这些复杂的依赖关系,即使是在团队中工作很久的人也不能一下子说清楚,所以可想而知新人上手的成本是比较高的。

2、自动化测试如何落地

而我们在去做微服务测试的时候,往往发现这样的问题,就是许多团队,首先去实现了架构上的解耦和代码上的拆分。但是我们认为,微服务测试其实是跟DevOps是一样的,它也需要各个方面的协同配合,比如说架构技术、工程实践和组织结构,这三方面要协同发力,才有可能让微服务测试顺利落地。

比如说微服务架构的可测试性方面,我们发现有些时候代码会写得比较死,你的测试就没法去测,你想通过配置或者环境变量的方法都没法调整,又比如说架构上面如果没有充分解耦,你会发现做单元测试的成本会比较大,往往改动代码后需要改写很多单元测试。

工程实践方面,需要考虑持续集成流水线,测试策略方面使用的成熟度,以及测试工具是不是足够轻量化。

组织结构方面,包括测试相关人员角色分工以及如何进行协作,在微服务测试下,其实更加强调团队的每一个成员都要去关心质量,后面会讲到每一种角色是怎么去参与到具体测试活动中的,以及如何进行分工和协作。

3、如何应对这些挑战

怎么样去应对这些挑战呢?我认为主要从这几个方面去考虑:

第一自动化,自动化的最大意义是帮我们减少重复工作,并且提供快速反馈机制。 第二轻量化,选择和使用工具时,尽量保持简单,选用成本低的工具。 第三可视化,从使用者的角度理解这个系统怎么工作的,然后帮助客户和你的团队人员降低沟通和学习成本。 第四去测试化,“去测试化”不是说不要测试,是减少只负责手工测试的专职测试人员,我们提倡开发更专注自己的代码质量,我们的开发要更多地参与到测试工作中来,不仅是单元测试,一些API测试都可以由开发去做。

二、微服务测试策略

微服务测试策略,其实要解决的就是我们要去测什么和怎么测的问题。如果我们从对微服务架构的系统化思考角度去看的话,微服务系统的搭建过程,类似于搭积木的过程,会经历模块开发、模块集成、到服务集成直至最终系统的过程,那么我们测试时也是遵循先底层后上层、从局部到整体的过程

系统工程中有这样一个定律,一个线性系统,即复杂度随着系统的规模线性膨胀的一个系统,它的可靠性等于各个组件的可靠性之乘积,如下图这样一个三组件的系统,虽然每个组件有高达90%的可靠性,但系统整体的可靠性只有70%多。

而一个复杂的微服务系统它的可靠性可能更低,因为组件之间有调用关系,会变成一个更加复杂的非线性系统。那么在微服务的测试过程中,我们该怎样制定合理的测试策略?是不是存在一些合适的模式适于我们去进行测试?

我们还是从微服务架构的特点出发,我们可以把每一个微服务视做一个用一组API提供业务功能的组件。

这个过程中我们应该测试什么?

第一部分是API内部逻辑,这部分可以通过API测试和单元测试去覆盖。

第二部分是组件之间连接的正确性,除了保证组件内部,还要保证组件间的调用是正确的,也就是API之间的调用,我们可以用契约测试去覆盖。

做完这些后我们还需要保证集成后的整个系统,从用户角度来使用的端到端流程是否正确,在通常意义下用集成测试去做。

下面我们对上面这个案例中所使用到的测试方法进行详细介绍。

  • 单元测试

单元测试针对代码单元(通常是类)的测试,单元测试的价值在于能提供最快的反馈。另外好的单元测试还可以帮助你改善设计,在你的团队掌握TDD的前提下,单元测试能辅助重构,帮助改善代码整洁度。

  • API测试

API测试是针对业务接口进行的测试,主要测内部接口功能实现是否完整,比如说内部逻辑是不是正常,异常处理是不是正确。

API测试的主要价值在于接口相对比较稳定,不像界面会经常变化,也不像底层代码也会经常变化,所以API测试比较容易编写,维护成本也相对低一点。在这方面做一些投入的话,它的性价比更高一些。

  • 契约测试

契约测试其实是为了测试服务之间连接或者说接口调用的正确性,为了验证服务提供者的功能是不是真正能够满足消费者的需求。

它其实体现了测试前移的思想,把本来要通过集成测试才能验证的工作化作单元测试和接口测试,用更轻量的方式快速进行验证。

  • 集成测试

集成测试其实是业务价值最大的测试,但是它实施起来并不容易。它从用户的角度验证整个功能的正确性,测的是端到端的流程,并且加入用户场景和数据,验证整个过程是不是OK,它的价值业务价值最高,是验证一个完整的流程。但因为需要验证完整流程,在环境部署、编写测试方面就实施成本比较高。

对于以上这些测试方法,我们看一下在实际工作中该如何组织这些测试?

因为你不可能把每一部分的测试都做得非常厚,就需要去制定合理的微服务测试策略,去划分清楚每一部分的投入该是多少,每一部分的用例比例是多少。

下面我们重点介绍一下微服务测试策略中的模式与反模式。

1,模式:金字塔型

我们知道理想的测试模式是测试金字塔,但是它对团队能力要求是比较高的。具体来讲,测试金字塔从下至上分别是单元测试,API测试、契约测试、集成测试。

我们在运行测试时,会先运行底层的测试,再去运行上层的,因为这样更容易定位问题发生的位置。

上层的测试业务价值更大,因为这是进行一个整体的大范围的测试。对于上层的集成测试编写成本较高,一个个去编写会比较复杂,而下层的单元测试会更加容易写,一般来说,越到下层越接近开发,越到上层则越接近业务,所以往往在下层是倾向于去开发人员去实现,而上层倾向于测试人员去实现。

金字塔型模式中底层的单元测试和API测试是最多的,随着越往上走,测试范围越来越大,集成测试占比最少。这样的一种测试模式,总体的自动化率、测试运行时间、投入产出比会达到一个理想的值。

它的优点,第一就是容易快速定位问题,从下面开始测,很容易找到哪块出现问题,另外也可以实现很高的自动化率跟自动化收益率。

它的限制因素则是对团队的能力有较高要求,起步阶段的团队不容易一下实现这种理想的测试策略。

2、反模式:倒金字塔型

在现实工作中,我们会看到倒金字塔型的测试模式,出现这种情况的原因是什么呢?

第一有可能是交付压力比较大,没时间写底层的单元测试跟API测试。

第二对自动化投入不足,主要是忙着交付了,对自动化的投入和重视程度是不够的。这种反模式的缺点显而易见,首先运行是比较慢的,有可能整个业务跑下来要好几个小时,其次自动化率比较低,因为上层的测试是不太容易被自动化的,而且也不容易快速定位问题,因为集成测试是大范围的测试。

3、反模式:沙漏型

还有一种反模式是沙漏型的,上下都有一些测试,集成测试有一些,单元测试有一些,但是中间层比较薄,这有可能是由于开发测试归属不同部门,开发做开发的,测试做测试的。

这种模式下自动化收益率是比较低的,因为中间层的API测试跟契约测试相对性价比比较高,而这里缺乏对中间层的投入。

另外有可能存在重复用例,因为开发和测试之间缺乏良好的沟通,会导致单元测试跟集成测试之间有一些用例是重复的。

4、模式:纺锤形

对于起步阶段的团队来说,其实更推荐一种更为适合的模式,即纺锤型。

在没有足够能力把单元测试做厚之前,我们先将重心放在中间层的测试上,因为第一中间层投入产出比较高,有很成熟的工具,可以实现比较高的自动化率。

第二它可以去帮助你增强开发跟测试之间的协作,因为这一层需要开发跟测试一起去定义,开发知道内部实现的细节,测试知道业务场景,这比较适合增强两者之间的协作。所以这种模式我们是比较推荐起步阶段的团队去做的。

5、纺锤型向金字塔型过渡

当你按照这种模式实施了一段时间以后,需要向理想型的金字塔型过渡的时候,要关注以下三个方面:

  • 第一开发与测试互相传递能力
  • 第二大家一起去关注设计跟代码的质量
  • 第三让用例逐步下沉,最后逐步过渡到理想型。

关于度量,我们建议不要仅仅用单一的指标去度量,比如说有些团队只关心代码覆盖率,甚至追求百分之百的覆盖,其实这个是比较片面的,我们去度量的时候,要关心以下几个方面:

第一是用例比例,每一层的用例比例是多少。 第二是测试覆盖率。 第三是测试总运行时间,因为经过优化以后,总运行时间一定是越来越少。 第四还有代码指标质量指标,反映代码的质量和整洁度。

三、轻量化微服务测试实践

1、工程实践:单元测试

单元测试方面

第一,单元测试并不要去追求100%的代码覆盖率,刚才也是讲了,其实应该综合去衡量。

第二,对细粒度业务进行单元测试,不是非要对一个类或者是一个函数去做非常细粒度的测试,不是绝对的代码单元,可以是一个业务单元。要做好单元测试应该先从学习设计代码开始,然后从精选一部分核心代码开始,而不是一下子对所有的代码要去补全单元测试。在单元测试中,应该使用Mock的外部服务和数据库,或使用内存数据库。

单元测试主要有以下一些工具。

  • 单元测试框架:Junit、TestNG
  • Mock工具:Mockito、PowerMock、EasyMock
  • 内存数据库:HyperSQL DB、H2
  • Testing With BDD:Spock Framework

2、工程实践:API测试

API测试的最佳方式是开发与测试协作完成,开发测试一起定义这个API测试怎么去做,一开始要先从接口的定义和管理开始,如果是对单个API进行测试,对这个接口测试过程中的一些外部服务应该是Mock的,这个过程中是可以使用真实的数据库,但是不要调用真实的外部服务。

以下这两个工具都是Swagger系列的,可以帮助进行API接口的设计和测试,帮助降低对API接口学习的难度。

另外推荐一个工具ServiceComb,它其中有两个组件swagger-generator-jaxrs和swagger-generator-springmvc,可以基于API接口的代码自动生成Swagger接口文件,不过前提是使用的是jaxrs或者springmvc实现的接口。

这个工具在使用时会去扫描接口代码类、方法和注解,从而生成Swagger接口文件。

很多团队以前并没有用Swagger的情况下,后期手工去补写Swagger接口文件,成本比较高,用这样一个小工具,可以帮助你减轻这方面的负担。

刚才说到API测试,可以去Mock,推荐使用一个轻量级的桩服务生成工具moco。

用起来就两步,第一步依据接口信息编辑一个json文件,第二步用一条命令就可以以通过jar包将你需要的桩服务运行起来。

它还提供了跟JUnit/Gradle/Maven等工具集成的插件,另外提供了丰富的API设计函数,用这些函数可以灵活编写实现丰富的接口功能,满足你对接口mock的需求。

3、工程实践:契约测试

再讲一下契约测试的实践,契约测试其实最重要的价值在于降低服务集成的难度。

我们刚才说了集成测试做起来是比较难的,而契约测试是把这个过程分解成了单元测试和接口测试来做,它从消费者的需求为出发点,把消费者的需求作为你的测试用例驱动出一份契约,然后验证提供者端的功能是否满足这份契约。

这个过程中,对外部服务也是同样是Mock的,在这个过程中可以使用真实的数据库,但不要调用真实的外部服务。

契约测试有一个很好的工具叫Pact,它的设计思路是比较巧妙的。传统情况下做集成测试需要把服务消费者和服务提供者两个服务都启动起来再进行测试,而Pact做契约测试时将它分成两步来做,每一步里面都不需要同时启动两个服务。

  • 第一步在Consumer端写一个对接口发送请求的单元测试,在运行这个单元测试的时候,Pact会将服务提供者自动用一个MockService代替,并自动生成契约文件,这个契约文件是Json形式的。
  • 第二步在Provider端做契约验证测试,将Provider服务启动起来以后,通过pact插件可以运行一个命令,比如你是用maven,就是mvn pact:verify,它会自动按照契约生成接口请求并验证接口响应是否满足契约中的预期,所以可以看到这个过程中,第一步不用启动Provider,第二步不用启动Consumer,却完成了与集成测试类似的验证。

使用Pact做契约测试的好处:

第一是使测试更加轻量化,将集成测试转化为了单元测试+接口测试。 第二是测试解耦,就是服务消费与提供者解耦,甚至可以在没有提供者实现的情况下开始消费者的测试。 第三是一致性,通过测试保证契约与现实是一致性的。 第四是测试前移,可以在开发阶段运行,并作为CI的一部分,甚至在开发本地就可以去做,而且可以看到一条命令就可以完成,便于尽早发现问题,降低解决问题的成本。

另外刚才我们提到契约测试里面有一个契约文件,那么契约文件其实是两个测试之间唯一的一个耦合点,怎么管理和共享这个契约文件?

一种简单办法就是手工copy,但不够自动化,那么推荐的实践是使用PactBroker这个工具来完成,使用PactBroker后,契约上传与验证都可以通过命令完成,契约文件可以制定版本,而且可以从契约文件去解析出来这个接口的相关的信息并可视化地展示出来,形成了一个具备可读性的API接口描述文档,任何人可以很轻松看懂它。

还有一个好处是它可以帮助你自动生成一个服务调用关系图,其中描述了消费者对接口的调用方式,这个图如果让人工去维护这样一份文档会存在过期的问题,而且也不是那么容易绘出来的。通过PactBroker自动生成服务调用关系图,任何一个新人进到项目来看到这个图就很容易理解这个系统是怎么工作的。

最后推荐一个资料《Pact中文参考指南》,这个其实是对Pact官方文档的翻译,网址也很好记,www.pact.net.cn,这里面包括了这几方面内容:

第一是Pact怎么工作的,它的工作原理。 第二是各种语言下的实现和及使用的指南,现在支持很多种语言。 第三是最佳实践,怎样更好地做契约测试。

还有FAQ及其他技术细节的问题,在这个指南都有包含了,大家有兴趣可以去读一下。

4、工程实践:集成测试

最后讲一下集成测试,集成测试是从用户角度去验证完整的流程,我们建议尽量少做集成测试,提倡测试前移,能用下层的测试测到同样功能的话,尽可能用下层的测试去做。做集成测试的时候有这么几点需要注意:

第一是环境部署问题,可以用基础设施即代码这样的工作,把环境部署的过程,用代码去描述,这样就可以去自动化管理部署的过程。 第二也可以考虑一些方法,提高自动化水平,比如说录制工具。 第三集成测试我们一般使用真实的数据库和加入了用户场景的数据。

集成测试方面我们推荐这样的一些工具,如Docker和Docker-Compose,你只需要写一份Docker-Compose的文件,就可以保证多容器应用用一个Docker-Compose命令一把拉起来。

有很多部署自动化的工具,我们最常用的还是shell脚本,一是简洁,二是不需要安装,三是很多技术人员已经有编写脚本的能力。然后还有一些集成测试和验收测试自动化的工具,包括SeleniuM和Cucumber,这些都是比较好的工具。

5、组织实践:角色划分与如何协作

上面是讲了一些工程实践,但是我们刚才提到了,微服务的测试不光是从工程实践和架构技术方面去进行优化,还需要考虑到组织实践的优化,就是在测试活动中,相关角色是如何去划分和进行协作的,这个也是至关重要的。

我们列出了在微服务测试活动中一些相关的角色,以及这些角色所负责的具体的职责、具体工作,以及和测试相关的能力需求。

  • 第一个角色是开发,它的主要职责是去实现功能,那么他在测试活动中的具体工作就是编写代码和单元测试,在API测试和契约测试这端,我们刚才推荐了比较适合开发和测试两者去共同完成,所以也希望开发参与到API测试跟契约测试里面去。传统的开发我们只关心代码怎么去编,它的测试意识其实是比较薄弱的,在我们的转型过程中会希望能够让开发去更加的关注质量,去有更多的一些测试方面的能力提升。
  • 第二个角色是自动化测试工程师,他的主要工作是帮助其他团队成员更好地去做自动化测试,他会去主导制定测试策略,要从头到尾去看测试策略是否合理,要去选择一些比较适合的轻量化和自动化的工具,或者去自研一些合适的自动化工具,所以它的主要职责就是帮助团队构建自动化测试能力。那么其实对这个角色的要求也是比较高的,一是需要熟悉整个系统的部署架构,二是他要有一定的自动化测试和开发能力。
  • 第三个角色是测试工程师,测试工程师的主要工作是对具体业务测试需求进行实现,他在自动化测试工程师搭出来的这个平台的基础上,去实现具体的业务测试,去编写测试脚本,然后还要包括少量的手工测试,当然随着你的自动化率越来越高,手工测试会越来越少。我们希望他能够跟开发一起去共同参与API测试和契约测试,随着不断转型,其实测试工程师也需要有一定的开发能力,这样的话可以通过自动化的方法去降低测试工作的成本,比如说测试用例的生成,或者测试脚本的编写,可以通过自动化工具,或者自己开发的一些小工具去实现。
  • 第四个角色是需求分析师,传统意义上认为这个角色只负责定义需求就好了,但是在转型过程中,其实也需要他能够更多地去参与到整个测试过程中来。他主要进行验收测试,因为他代表了用户的需求,我们一般会在上线前组织验收测试的过程,那么这个需求分析师的角色就是类似于产品经理的角色,他会主导验收测试。

我们整个测试活动中不管角色怎样划分,最终目的还是希望各个角色更好地协作,打破部门墙的限制。

四、轻量化微服务测试总结

最后做一个总结。一开始我们讲了微服务下测试工作所面临的一些挑战,这些挑战来源于微服务架构的特点,所以我们要去应对这些挑战的话,就是需要先从对微服务架构的系统化思考入手。

刚才我们讲了如何对微服务架构进行拆解,然后我们讲了各个测试类型,以及各种测试的范围、价值和意义,然后分析了根据团队的实际情况,应该怎么选择合适的测试策略,逐步从起步阶段开始,将你的测试策略优化到比较理想的模式。

最后讲了工程实践和组织实践,包括每种测试类型下我们应该做的事情和不应该做的事情,还推荐了一些轻量化的测试工具。

组织实践方面,我们讲了测试活动中各个角色如何去划分,如何去进行协作,协作过程中,我们最终的目的还是希望能够打破部门墙的限制,希望每个角色能够参与到这个测试活动中来,共同把微服务测试的工作做好。

END

本文分享自微信公众号 - DevOps时代(DevOpsTimes),作者:张桐

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-09-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • DevOps 测试在企业中如何落地?

    互联网时代,企业越来越注重产品的快速迭代与交付,当然产品质量也是举足轻重。企业在有限的资源情况下,快速的步调意味着更多的挑战,本次演讲重点在于测试人员如何无缝连...

    DevOps时代
  • 开发高质量软件的5大原则

    多少次的惨痛教训告诉我们,在软件应用发布维护版本或者补丁之前,应该避免使用其最新版本。虽然每个人都知道初始发布版本V和稳定发布版本V.n之间存在软件质量鸿沟,这...

    DevOps时代
  • 软件测试金字塔

    ? “测试金字塔”是一个隐喻,它告诉我们将软件测试分成不同颗粒度的桶,也给出了我们应该在这些组中进行多少次测试的想法。尽管测试金字塔的概念已经存在了一段时间,...

    DevOps时代
  • 菜鸟小白的测试基础理论总结(一)

        今天我们看一看测试的理论知识,在学习测试理论知识之前我们先看看什么是测试?

    菜鸟小白的学习分享
  • 软件测试思想浅谈

    张树臣
  • 设计测试策略

    我便有了想法重新写一篇文章,体系性的介绍一下相关的内容。我那已经达到 800+ 篇的博客,正好缺失这样的一篇文章。

    Phodal
  • 第 8 章 软件测试

    love丁酥酥
  • 【测试】软件测试知识点-期中复习1

    1.2简述软件测试V模型的流程 需求分析——概要设计——详细设计——编码——单元测试——集成测试——系统测试——验收测试

    瑞新
  • 【测试】软件测试知识点-期中复习2

    1.1常见的软件测试模型有哪几种 V模型、双V模型(W模型)、H模型、X模型 1.2简述软件测试V模型的流程 需求分析->概要设计->详细设计->编码->...

    瑞新
  • 10年软件测试工作总结

    张树臣

扫码关注云+社区

领取腾讯云代金券