阅读 174

20210401 微服务测试简介

一、什么是微服务
      契约测试有生成者驱动的契约测试,也有消费者驱动的契约测试;二者之间的异同?消费者端的集成测试需要做到什么程度?微服务测试不仅仅是契约测试,比如端到端的测试等。微服务的前身,Peter Rounder 在云端计算博览会首次提出 Micro Web Service 这是最早的概念,但还不是微服务;直到 2014年,一个叫做 Martin Flow 的人和 James Lilies 共同提出微服务的概念;Martin Flow也是敏捷开发的创始人,在设计架构,软件开发,重构,面向对象分析等都是一个开创者的角色;国内在 2016年时,开始像这个方向迈进。微服务可以从两方面理解,微和服务,微狭义的讲,就是微小;亚马逊老板贝索斯曾经提出量披萨团队,单个服务的设计,所有人参与只需要两个披萨就可以;因为规模小,服务就简单。服务区别于系统,服务是一组相对较小,并且独立的功能单元,这是用户可以感知到的最小功能集。
1.微服务的具体定义
○ 从本质上来讲微服务是一种架构模式
○ 它是面向服务架构SOA的一种变体。(SOA面向服务型架构)
       ■ 本质上还是SOA,但是微服务不像SOA那样要求绑定具体的技术。微服务鼓励用恰当的技术去实现合适的服务,这样系统的扩展性会变得很强。
       提倡将单一应用程序划分为一组小服务,服务和服务之间相互协调配合,(比如食堂打饭,每个窗口是一个服务,窗口之间有相互联系)为用户提供最终的价值,本质上是SOA架构,但和SOA并不同。微服务架构下,不绑定特殊技术,每个服务都可以使用自己独立的技术栈,比如有些服务用java实现,另外的服务用python,服务之间不受影响,服务之间通过 Rest Full API 进行访问。
○ 每个服务运行在自己独立的进程中,服务与服务之间利用Rest API来进行沟通,把不同的服务有机的整合成一个统一的系统
       这一点和SOA是不同的,SOA要求技术架构是一样的
○ 每个服务都围绕着自己的业务来构建,并且可以独立的部署到类生产环境中。
       每个服务运行在自己独立的进程中,服务之间通过Rest API沟通,本质上就是 http 协议通过 Rest API 沟通,连接成整体,每个服务都围绕具体的业务构建,并且每个服务都能够独立部署到环境中。注意尽量避免统一的集中式的管理机制,对具体的业务应该选择合适的工具和技术。
2.为什么需要微服务
LAMP(Linux+Apache+MySQL+PHP)
MVC(Spring+MyBatis/Hibernate+Tomcat)
单体式架构(Monolithic Architecture)
       早些年,各大公司的项目主流技术,大概分为两派,一个是 LAMP Linux+阿帕奇+MySQL+PHP,另外一个主流技术是 MVC Hibernate 数据持久化。基本上就是这两大阵容,一个是 PHP 一个是 java,他们过去都是单一的应用架构设计。这种设计方式优点是学习成本低,开发速度块,测试部署运维都比较方便,有些项目甚至一个人就可以完成;比如 MVC 架构,通常是打一个包,丢到 Tomcat 中。早期项目规模不大时,利用这种单一的应用架构模式,团队的开发和运维成本基本是可控的。随着各个行业的业务拓展,服务越来越复杂,软件功能越来越多,这种方式就对企业的技术进行了限定,早期系统的对接和未来新系统和技术的变化,都产生了一定困难,项目的切换时间和成本都比较高,系统稳定性问题的解决时间也比较多。这种早期的传统的开发模式就是单体式架构,微服务就是用来解决这些不方便的,新技术雨后春笋般的飞快发展,要让企业和技术跟上时代进步,项目开发需要变的更加容易,更具扩展性;这些就是微服务诞生的基础。

二、微服务与传统开发方式的区别
■ 单体式架构
    ○ 优点
        ■ 团队组织结构简单,便于集中管理
        ■ 开发进度一致,统一管理,能够避免重复开发的问题。
        ■ 所有的功能都在本地,没有远程调用的开销和网络损耗
   ○ 缺点
       ■ 效率低
       ■ 维护困难
       ■ 不够灵活
       ■ 稳定性不好
       ■ 扩展性不够  
a1.png       所有功能打包在一起,项目没有对外的依赖,唯一的依赖大概就是数据库;业务逻辑,前端显示等等都是整合在一起的。这种架构的好处就是开发团队的组织架构简单,可以集中管理,开发流程也是统一的,同时也可以避免重复开发,所有功能都在一台运行机器上,访问都是本地操作,基本上没有网络延时,远程调用的损耗。但是,也有明显的缺点,现在软件应用越来越复杂,功能越来越多,对于项目的更新迭代速度越来越高,就像 Intel 总裁说的,如今市场不是大鱼吃小鱼,而是快鱼吃慢鱼,要求企业对产品和项目有快速更新迭代的能力,这样单体式架构就会力不从心,等待和修改冲突,对于开发来说是一个很高的成本,而且代码都在一个项目下,所以代码的内部耦合比较大,新接手项目的同事通常不知道bug位置在哪里,修复后,也需要对整个项目进行更新。单体式项目的稳定性也是比较差,整个项目在 tomcat 中,任何地方出现问题就会导致整个项目挂掉
■ 微服务架构
    ○ 优点
        ■ 解决上面单体式架构项目的所有缺点
        ■ 部署、回滚变得更加快捷
        ■ 每个服务都可以独立的扩容
        ■ 每个服务都可以采用适合自己业务需求的技术栈来实现
        ■ 可以运用插件的形式来更新系统,不必有一点扩充就要重新部署整个项目
        ■ 对于业务的数据可以采用数据接口的方式来方便未来业务发展后的数据管理与数据迁移
    ○ 缺点
        ■ 每个子系统都有独立的团队,这个会增加整个系统内部的通信需求,也会增加不同团队的交流成本
        ■ 对于这种分布式架构的系统进行测试时,复杂度大大提高了
        ■ 分布式系统的部署对于团队DevOps能力要求很高
        ■ 当系统的服务增加时,管理的复杂度也会呈指数级增加。
b1.png
       所以,微服务架构应运而生,解决单体式架构中的问题,核心理念是按业务功能,业务边界,把单体式项目拆分成一个个的子系统,每个子系统由单独的开发团队开发,他们之间保持合作,而不是整合的关系,只需要把子系统的边界,也就是接口定义好,这样每个团队就可以独立工作了,每个子系统的内部产生沟通成本,每个子系统是一个高内聚的系统,系统和系统之间的耦合关系就变弱了,仅仅只是一个请求,这样系统和系统之间的成本就变低了。图中,每个服务都变的简洁,服务和用户通过简单的 http 协议沟通和访问,微服务不仅能够解决单体式服务所面临的问题,微服务还有一些独特的优点,比如可以更快部署,每个子系统可以单独部署,独立运行,更新服务时,只需要更新子系统即可。
       每个服务自己可以独立扩容,服务本身在开发时,还可以在技术上有所改变,只要定义的接口不变,用什么技术实现是没有要求的,每个子系统可以使用适合自己业务逻辑的技术实现。整个项目的技术就不会被限制于某种特定的技术,比如 C 适合于快速,运算量大的计算,对于控制硬件比较优秀,java适合web的动态服务,Python脚本解释型语言比较快捷。微服务架构就是一个分布式系统,测试的复杂度大大提高,这是微服务的缺点,微服务的测试,除了考虑业务逻辑,还要考虑中间的通信成本,不同团队的沟通成本,都对测试提出了挑战,DevOps (开发运维)的要求,自动化部署的要求也相应提高,因为不止有一个包,每个项目都要有自己的环境。服务数量的增加会带来可怕的复杂度的增长,这就是微服务的缺点。

 
三、微服务架构对测试人员意味着什么
   1.每个服务承担一定的职责,服务尽可能地小,但是还需要达到一定的规模。对于项目做出向微服务转变的决策时,测试人员要勇于提出质疑,要不要做这样的转变。
   2.微服务之间通常通过REST API连接。
   3.每种服务不一定提供界面。对测试人员意味着不一定能够从UI对系统进行完整测试, 这就对API级别的集成化测试提出了要求。
   4.微服务通常还可以划分为更小的模块,在对微服务进行测试时,可以从不同的模块着手,进行相应的模块测试。
       第一个需要关注的是 微服务测试对于测试人员意味着什么。每一个服务都会承担一定的职责,都有自己的业务逻辑,如何把原来单体式架构的服务转变为 一个一个的小服务呢。服务划分的原则是规模要尽可能的小,但是又要达到一定的规模,每个服务至少能为其余的 2 个服务提供支持。如果划分的服务只能够给另外的一个服务提供支持,这个划分就太小了;这就是单体式架构向微服务架构转变时的功能切分原则。微服务的本质是解决系统里面的耦合,将耦合度变小,服务内部是高耦合的,服务和服务之间是低耦合的。开发团队在转向时,这个地方经常会出现问题,并没有达到真正的解耦作用,这就会造成产品维护和测试成本的增加。
       所以测试团队需要在会议中提出这样的问题,就是我们的项目有没有必要转变成微服务,需要提出这样的质疑,因为微服务随着服务的增加,管理成本一定会提升,而测试人员在企业里担当着产品质量把关人的角色。所以,提出这样问题的目标是让企业决策人员意识到这种转型的潜在成本,千万不能做无用功,这也算是测试团队的职责所在。
111.png

       图中,是一个典型制造型企业的运营系统,左边企业系统包含业务、财务、管理和设计等,最上层是界面,最下层是数据库,这些内部逻辑之间都存在关系。将这样的业务逻辑转变为微服务架构时,原来的黑线,被转变成为了 http 的 POST 或者 GET 请求,原来的每一个单独的业务逻辑被独立成一个单独的应用。每一个应用有自己的数据,同时应用和应用(也就是服务)之间是通过 http 请求发生联系,这样用户在使用时,未来业务有所改变时,可以独立维护服务。如果扩展一个设计,可以单独设计一个就好,而单体式项目,如果增加一个设计,必须将整个项目进行更新。并不是每个服务都要有界面的,对测试来说意味着,并不是每个服务都要做 ui 测试,这就对 api 级别的集成化测试提出要求。
1112.png上图是一个典型的微服务,分为很多的边界,里面可以有资源,业务逻辑,数据存储接口和外部通信接口,这意味着对微服务架构进行测试时,可以从不同的模块着手,进行相应的模块测试

四、微服务给测试带来的挑战
   ● 总体的测试策略
         ○ 从各个维度上,无一遗漏的对微服务进行全面的测试,既要确保我们对系统各个层面的覆盖度,又要确保我们的测试执行效率,从而保证CI/CD的顺利实施。
         ○ 测试策略的正确实施,工具和技术固然重要,但是我们需要注意更为重要的人的因素,测试人员要在团队中树立质量第一的测试文化。
         ○ 不能为了测试而测试,要以用户为核心,把有限的资源用在刀刃上,对于测试层次、流程以及用例的设计,要有的放矢。

软件测试的目的就是确保产品质量符合预期,衡量质量的指标有很多,最常见的就是测试覆盖率和测试成本,测试成本指测试时间和维护成本,衡量测试效果的手段就是用户实际使用中所暴露的问题的数量,针对微服务测试,就需要从各个维度,保证无一遗漏的对微服务进行全面的测试。特别是微服务的分布式系统架构,系统的所有层次都要覆盖,也需要测试执行的时间不可以过长,这样持续集成和持续交付的工作才能实现,同时也要确保测试策略的正确实施,工具和技术虽然重要,但是所有东西最后的落实还是人。所有测试人员有职责和义务在团队中树立质量第一的意识。一切从用户感受和需求出发,围绕用户的真实使用场景,考虑测试的流程和用意,不要把有限的资源浪费在没有实际意义的测试上。如果用户不这样用,也不必花太多时间,不要为了测试而测试,这是针对微服务测试的总体的测试策略,在微服务架构中,需要考虑的面和纬度更多,每一个服务都是独立的应用,服务和服务之间还有联系。
   ● 微服务对于传统测试方法带来的挑战
       采用微服务后,每个微服务有不同的客户要求,开发周期,开发进度,交付期限都有可能不同。但是又有整体的时间节点,传统的单体式架构,测试团队就会有一种疲于奔命的感觉,相较于过去的传统项目测试方法,微服务架构提出的挑战就比较严谨了。模块层次存在复杂的依赖性,在以往的测试中用集成测试的方式验证是否正常,但是在微服务中,如何保证依赖的正常呢?单独对某一服务测试时,会发现,这个服务如果正常的提供服务,可能要依赖其他的服务提供相应的数据和计算。这就意味着,测一个服务A,需要搭建依赖的服务B和C,我们没有办法方便的对一个服务测试。这种情况,通过模拟的方式,模拟依赖的服务B和C,去剥离对于其他环节的依赖。这样才可以对A服务进行相应的测试,不同的服务可能会在不同的环境/设置下运行,比如后端服务与前端服务,它们的运行环境可能截然不同,这时自动化集成程序就必须针对性的对环境进行配置。在微服务场景下,每个服务都需要搭建相应的运行环境,每个服务需要独立部署,而且交付周期也比较短,需要搭建的频率也会比较高,因为每个服务会独立更新,单体式架构部署一个环境已经足够头疼,微服务需要高频率的部署多个,这个用人工部署就可能没办法确保环境稳定正常运行,人工部署往往无法达到要求。
       这就意味着需要用自动化部署体系,保证配置的稳定性和可重复性,这对于微服务测试来说就是另一个挑战,可能需要和开发和运维共同配合解决这样的问题。这个在单体式测试中是不会面对的。在涉及多个服务的 UI 端到端测试非常容易出错,因为每种服务开发进度不同,而集成不同服务的端到端测试往往会因为其中某一个服务的小改变使端到端测试出错,端到端测试大部分是指 ui 测试,但不仅局限于 ui 测试,界面的自动化测试的稳定度是一个让人头疼的事情,现在面临多个服务,每个服务都可能发生变化,这样出错会更多。作为测试人员需要了解如何防止这种干扰,做端到端测试时需要有相应的策略避免干扰。测试结果可能取决于网络的稳定性,传统的单体式服务,运营,财务,管理等都是在同一系统下运行的,它们之间的调用就是函数和类之间的调用,从而实现相应的功能,微服务的调用往往不是本地环境,可能是一台主机对另一台主机的访问,这就带来了性能问题,因为跨进程,跨网络,就会对性能带来影响。其次是可靠度,网络间的调用可能会因为网络不好等原因而失败,而且随着服务的增加,潜在的故障点会越来越多,在整个服务的运行过程中,它们互相之间的访问高度依赖网络状态。那么如何提高系统可靠性,如何降低因为网络而引起的故障,这对整个系统的构建来说是很大的挑战。
       通信通过 http 访问,请求发出后,响应什么时候回来,不是我们能决定的,这就是异步通信的问题,为开发带来调试困难,为测试带来定位困难等问题。所以异步通信也是一大挑战,每个服务有自己的数据,所以需要在数据一致性,可用性,分区容错性三者之间做出权衡,特别是数据存储和外部通信的部分,如果测试过程中不摆脱这些因素的影响,问题可能就是随机性的,对于这种随机性问题,随机性的误报,这种干扰对于测试结果的影响是需要考虑的。
       故障分析的复杂度会随着服务的增加而提高。每个服务独立的运行,部署,配置,这些服务每个服务有自己的监控和日志信息,发现问题后,诊断分析时,随着服务的增加,搜集缺陷信息的成本就会指数级增长。所以,服务增加后,对测试分析定位问题就会变的异常困难。
       与交付周期不同的开发团队之间的交流成本,这个和技术本身无关,但是在实际工作中带来的困扰往往非常大。因为不同的开发团队有自己的进度和开发周期,测试人员每天需要花费大量时间了解团队的开发计划,进度和进展。在这种状态下,如果还依赖于手工测试来进行回归测试,那么有可能完成任务吗?所以,面对微服务自动化测试是测试团队被迫也是必须采用的手段和方向,如果在微服务时代还依赖于手工测试,那么将无法对产品进行充分测试,无法对产品进行完善测试,产品质量将无从谈起。微服务时代,自动化测试是被迫和必须采取的手段,这就是微服务给测试团队带来的挑战,在这些层面都有可能遇到问题,面对这些挑战,要采取什么样的方式进行测试?采取什么样的原则面对挑战?
   ● 面对上述挑战,测试团队需要采用什么样的测试原则呢?
         ○ 自动化
         ○ 层次化
         ○ 可视化

       自动化测试是被迫的也是必须要进行的,传统的手动测试面临那么多的团队和进展是不可能完成任务的。所以,第一个原则就是实现测试自动化,实现自动化测试要求必须是稳定的。
3.png       第二个原则就是层次化,采用分层的测试方法,测试力度由细到粗,范围由小到大。图中是测试金字塔,从下向上,测试力度由细变粗,测试速度由快到慢,测试金字塔可以得到两个重要的原则,用不同的力度测试应用程序
层次越高测试越长,最底层是单元测试,测试力度最细,速度最快,维护成本最低,ui 测试是最粗的,但是测试范围是最大的,测试用例的维护成本是最高的,稍微的细微变化就需要调整脚本,ui 的自动化测试稳定性最小,为了保证脚本稳定执行,需要人为设定等待时间,因为服务之间具有网络开销,所以测试速度最慢。因此设计 ui 自动化测试用例时,原则上往往会让用例少一些,测不到的地方则通过其他的测试进行保障,因为测试是分层级的
这就是层次越高,测试越少的含义,通过其他测试让所有的测试都测到,这就是层次化。
       为了降低测试团队的沟通交流成本,最好的方式就是让所有测试结果可视化,这就需要运用持续集成,比如 TeamCity Jenkens 等持续集成工具,通过这些持续集成工具可以让我们构建、测试、部署,可以让所有的团队成员随时监控项目进度,阻碍项目的瓶颈就更容易被发现,这就是可视化。有了应对挑战的原则,就需要知道主要的测试方法是什么。
   ● 针对微服务架构我们可以采用的主要测试方法
         ○ 单元测试(UnitTest)
         ○ 集成测试(Integration Test)
         ○ 组件测试(Component Test)
         ○ 契约测试(Contract Test)
         ○ 端对端测试(End to end Test)
         ○ 探索性测试(Exploratory Test)

       第一个就是单元测试,单元测试主要用于验证微服务内部的类方法或者函数的行为,会根据测试框架执行代码里的类方法或者函数,对每个方法或者函数提供不同的输入,验证每一个输入相应的输出。常用的就是 Mock,单元测试框架本身也带有 mock 模块,可以用mock来模拟函数或方法调用其他方法的结果。这样就可以对一个方法或者函数,进行测试。集成测试,主要用于验证微服务与外部模块的通信或者交互行为。
4.png这张图,上面是资源,下面是业务。然后是通信和数据访问。单元测试的对象是最小可测单元,验证它们是否按照期望进行表现。
5.png对具体的资源,服务层业务,以及通信,每一个地方进行测试,这是单元测试的范围。
6.png集成测试是指,对于外部通信的调用,内部向外部请求数据,请求数据后,外部将数据结果返回给内部,内部服务的执行逻辑是否正确。
7.png除了外部通信,还有数据,访问外部数据库,集成测试考虑访问数据后,拿到外部数据库数据后,内部的业务逻辑执行是否正确
8.png       组件测试主要验证微服务是否能够起到预期的作用,需要把微服务周边所有的依赖模拟化,模拟化后在从这个服务的外部进行考量,检查这个服务能否提供预期的输出,和集成测试的区别是,集成测试也是模拟外部服务,但那是站在被测服务的角度,考虑收到外部数据后,服务自身收到响应后,能否正确处理业务逻辑。而组件测试,依然是把外部服务模拟化,但考虑的是服务正常运行后,站在外部看,给了输入后,能否给出预期的输出,是站在外部看被测服务是否能够提供预期输出。
01.png       除了进行组件测试以外,还要进行 contract tests 契约测试。被测服务需要外部通信服务的数据才可以运行,内部服务是消耗数据的,是消费者,外部提供数据的服务是提供者,也就是生产者。被测服务是消费数据的,可以看做消费者。契约测试就是看生成者服务和消费者服务之间进行通信,在传递数据时的协作是否恰当,生成者提供的内容是否能够满足消费者(被测服务)的预期。比如在食堂买饭,点一份麻辣羊肉砂锅面,发出请求麻辣羊肉砂锅面。
2.jpgspacer.gif生产者做好麻辣羊肉砂锅面后提供给消费者我,如果给的不是麻辣羊肉砂锅面,,,那就不符合契约测试的要求,没有满足消费者的预期。对于契约测试就是看中间的协作机制是否恰当,协作机制其实就是请求、响应以及请求方式,这些就是契约测试需要关注的东西。
007.png       除了契约测试,还需要关注端到端测试,整个粉色圈就是端到端测试,验证的是整个系统的功能是否符合用户的预期,一般都是从 ui 层面进行测试,是确保用户体验是否能够达到用户要求的测试。除了端到端的测试,有时也需要探索测试,探索测试一般是测试团队中资深业务测试人员进行,通常是手动测试,这种测试的力度比端对端测试更大,测试范围是针对整个项目。


©著作权归作者所有:来自51CTO博客作者ATaburiss的原创作品,谢绝转载,否则将追究法律责任


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐