测试
00 测试概述
软件测试的目的是,保证程序员编写的程序达到他的预期结果,保证发布的产品是产品经理(产品设计人员)的真实意愿表现。这些都需要软件测试来监督实现,避免将有缺陷的软件发布到生产环境。
软件测试种类有很多,粗略的划分为:单元测试、集成测试、端到端测试。从其他的角度来说,又有回归测试、自动化测试、性能测试等。当我们项目进行服务化改造之后,尤其是进行了微服务设计之后,测试的工作就更加困难了。很多项目都是以独立服务的形式发布的,这些服务的发布怎么能保证是进行了充分测试了的?测试的入口应该是哪里?是直接进行集成测试,还是做端到端的用户体验测试,好像都不太合适。按照分层测试的思想,于是就有服务测试的话题。服务的测试理论和其他的测试应该是大体类似的,其中比较特殊的是,如何提供方便快捷的服务测试入口。
01 微服务测试
目前常见的微服务设计都是会采用一些分布式服务框架,这些框架从通信协议上分有两种:
公共标准的HTTP协议的;
基于私有的RPC调用协议。
第一种http协议的微服务接口,比如使用spring boot开发的服务,这样的服务的测试工具应该有很多,postman是一个常用的工具。如果想为测试人员做点事情的话,可以根据服务注册中心做个所有服务的列表。
第二种以私有协议暴露的服务的测试是非常麻烦的,也是本文主要讨论的解决办法。最初我们为了打通服务接口和测试人员之间的屏障,为了能让测试人员方便地测试到RPC协议的服务接口,我们为每个服务接口写了一个客户端,将其转换为http协议暴露,这是一种解决办法。但是,这样无形中增加了很多开发人员的工作量,而且测试服务的质量还依赖于客户端编写的质量,明显的是费力不讨好工作。
作为程序员,懒惰是其本性,于是就想办法改变这种微服务测试苦难的现状。怎么能构建一个项目,它能提供所有服务的客户端,新开发一个服务只需要做极少的工作就能生成一个服务的测试客户端,快速的将接口提交测试?这是我们下面讨论的问题(开始造轮子)。
02 基于RPC协议的微服务测试的设计思路
微服务设计的项目一般都是基于分布式服务的注册和发现机制的,所有的服务都是在一个注册中心集中存储的。而且一般的分布式服务框架都支持丰富的服务调用方式,有基于Spring xml配置的、Spring 注解、和API等调用方法,为我们编写公共的服务测试工具提供了便利的条件。
我们设计的服务测试工具在整个分布式服务架构中所扮演的角色就是如下图所示,是所有的服务提供者的公共客户端。
服务测试工具的角色
根据上述服务测试工具的定位,我们开始设计该测试工具,主要的宗旨是:
简化测试人员工作。
简化服务开发人员工作。
保证测试质量。
下面描述一下我们的微服务测试工具的设计思路,主要分为如下几步:
服务测试工具的处理流程
第一步是从服务注册中心获取到所有的服务接口,并将这些接口可视化地展示给测试人员,测试人员可以选择需要测试的服务接口。
服务列表
第二步就是将服务的每个接口以一种易读易用的方式暴露给测试人员,目前能想到的就是将接口的请求参数转化为xml或者json的形式展示给测试人员,方便他们填写测试用例。我们采用的是xml格式,示例如下:
<?xml version="1.0" encoding="UTF-8"?><java.util.List> <com.unicom.front.model.MucfcBussOrderRequest> <systemCode>0</systemCode> <flowNo>0</flowNo> <charSet>0</charSet> <requestTime>0</requestTime> <signType>0</signType> <signMsg>0</signMsg> <operatorName>0</operatorName> <operatorId>0</operatorId> <orderId>0</orderId> <woAccountId>0</woAccountId> <serialNumber>0</serialNumber> <certType>0</certType> <certCode>0</certCode> <expandAttribute> <entry> <java.lang.Object>0</java.lang.Object> <java.lang.Object>0</java.lang.Object> </entry> <entry> <java.lang.Object>0</java.lang.Object> <java.lang.Object>0</java.lang.Object> </entry> </expandAttribute> </com.unicom.front.model.MucfcBussOrderRequest></java.util.List>
第三步,将测试人员提交的服务测试请求中的参数转换为xml报文参数转换为请求对象,以便使用统一的API接口,调用到后端服务。
第四步,发起服务调用,这一步一般使用API的方式来调用服务,这是因为我们做的工具是统一的服务调用入口,能够根据请求参数动态地调用不同的服务。
第五步,将服务的响应参数再次转换为xml或者json展示给测试人员查看,这时候可以顺便返回一些调用耗时等附加数据,帮助测试人员判断服务的效率等情况。
请求和响应示例
03 微服务测试拓展功能
遵循着我们设计这个服务测试系统的宗旨,尽可能的简化一切服务测试过程。其中还有一些服务测试基础功能之外的拓展功能:
有规律(规则)请求参数的自动化生成,例如请求流水号、请求时间、手机号、身份证号等,减少测试人员的填写参数时间。
后台保存服务测试的请求参数和响应参数,方便回归测试。
实现了回归测试,在服务代码有变动之后,可根据保存的请求参数进行回归测试,并且可以和之前的响应参数进行对比,以便验证是否影响到当前测试服务接口。
服务的并发测试,在提交测试请求的时候可以指定每个服务测试请求的测试次数,这时后台会模拟多线程调用服务,可实现对服务接口的并发测试。
多个测试环境自由切换,通过选择不同环境的注册中心,来实现其他环境的测试,如集成、系统等环境。
服务测试出现异常的时候,将异常堆栈信息直接展示在测试人员面前,方便他排查问题。
实现定时回归测试,有时候我们的测试环境也需要保持一定的稳定性,因为经常会有别的系统发起联调测试。定时回归测试,既能及时发现后端系统对我们服务的影响,又能保证我们服务的持续稳定地对外提供服务。
开发公共的mock测试服务(未实现),有些时间避免后端未开发完成的服务耽误我们服务的测试,有时候也需要mock掉后端服务,这看起来更像是单元测试,但是实际的开发测试环境是复杂的,这种情况也是时常发生的。但是每个服务都要单独开发的话,又有些麻烦,于是就想设计一个万能的mock服务。
04 结束语
上面的介绍的微服务测试工具和其中一些思想,都是我厂几个同事一起讨论实践过程,在此分享出来希望能对各位有帮助,最好能减少我们这类程序员们的一些疑惑。
作为一个开发人员说起测试显得有些不够专业,如果有哪些地方描述的不合适的,请各位测试专业大神指点,欢迎拍砖。
作者:rabbitGYK
链接:https://www.jianshu.com/p/70b5387cbef7