在微服务生命周期过程中,测试是一个非常非常关键的阶段。测试是验证微服务功能、性能、部署、协同等能力是否能满足需求的一项工作,是发现存在的错误和潜在的错误及不足的前瞻性举措。软件测试是一门十分庞大繁杂的学科,要做好测试并不容易,因此我们希望在微服务测试过程中尽可能做到自动化,尽可能实现标准化流程和操作,尽可能的使用工具完成相应的测试工作,减少人的因素影响。这也是敏捷自动化测试需要面对的问题。
微服务测试是保证微服务质量的必要步骤,是实现微服务生产就绪的前提。微服务相对轻量,适合部署于轻量的容器平台,而微服务的生命周期过程又是DevOps微服务开发和基于容器平台部署、测试、管理、运营微服务的过程。这其中包含测试过程,也就让我们考虑基于容器平台采用DevOps流程和工具完成微服务的测试。
我们期望微服务开发阶段完成单元测试后交付的微服务镜像进入测试环境镜像仓库,自动完成镜像扫描,扫描通过的镜像可部署于测试环境,根据规则构建相应的微服务测试域,自动生成测试用例,完成功能、性能、集成等测试,生成测试报告。测试过程中遇到的缺陷,在关联Jira中创建缺陷跟踪记录,并从Jira发送邮件提醒给相关开发人员。开发人员修复缺陷提交代码自动编译、完成单元测试、打包到镜像仓库,然后可部署于测试环境,启动新的测试流程,这样就形成了一个测试的小闭环。
测试并不简单,可以从测试理论指导、测试流程定义、微服务测试过程到微服务生产部署,有众多的工作需要做,目的是为了微服务生产就绪。
一、 测试方法论
我们之所以提测试方法论,是希望从一个相对高的角度来认识测试,更好的指导测试工作。不是谁都可以拿鼠标点点就是测试了,测试人员需要有相应的测试理论指导,需要熟练使用相应的测试工具,根据需求和设计构建测试用例,完成各项测试并输出测试报告。
各大公司基本上都有一套自己的测试方法论。比如微软的两类测试方法、IBM的RUP测试方法、Parasoft提倡的AEP自动错误预防测试方法等。至于什么方式适合自己,可能不同的行业不同的场景会不一样。一方水土一方人,最重要的是要找到适合自己业务、自身技术水平的测试方法。
很多方法是长时间的测试过程中实践经验的总结,或者说最佳实践,但别人的最佳实践不见得适合自己,别人的鞋不一定是自己穿的号码,再说即便同样的号码,肥了瘦了软了硬了深了浅了也不一定就适合。所以一方面要求对测试理论方法要有认知,另一方面也要对自己的技术实力、业务场景等深刻理解,选择合适的方法,也许需要经过裁剪、经过磨合,才能逐步打造适合自己的一套测试理论指导方法。
二、 微服务测试阶段
测试是DevOps的一部分,DevOps强调开发运维一体化,但是否完全让开发人员自己测试自己写的程序代码?我们觉得这种方式并不可取。在没有第三方测试验证的情况下,首先人的思维是有误区的,有缺陷的,开发人员也是一样,自己写的程序在测试的时候也会有思维惯性,一些存在的或潜在的错误可能根本想不到,也就测不出来;其次人往往都是严于律人宽以待己,特别在时间紧急的情况下,更难以保证微服务的测试质量;因此我们觉得微服务的测试可能需要根据微服务生命周期过程分为几个阶段分别进行测试和验证,需要不同的角色人员参与到微服务的测试之中去,并能及时自动反馈测试结果。
(一) 持续集成阶段
持续集成阶段大部分时间花在编码上,包括业务逻辑代码和单元测试代码。代码提交通常会触发自动构建流程,完成代码检查、代码编译、单元测试、打包、构建镜像、上传镜像到镜像仓库等步骤。在这个阶段代码检查和单元测试是保证微服务代码质量的。
1. 单元测试
单元测试重质不重量,但通常有量才能保证质。所以测试用例的设计就显得很重要。测试用例包括验证正确的用例和验证异常的用例,异常的用例可能有多个,从不同侧面、不同层面验证功能的容错性。所以其实验证错误的用例设计更为重要。
(二) 测试环境测试
基于DevOps,测试人员只负责提供测试环境、测试用例、测试工具、测试方案、测试计划、测试文档等。而测试所需基础设施资源则由云计算基础设施平台提供。比如测试需要10个节点,每个节点2个CPU,8G内存,50G NAS存储。则测试人员直接从云计算平台申请划分资源,构建相应微服务的测试域,微服务可能需要其他微服务协同支持,或使用测试挡板程序模拟协同微服务。这样就可以迅速构建测试环境,完成测试。
1. 构建测试域
在跟不同厂商交流中,有人提到搭建基线测试环境,这让我们对不同服务不同版本之间的协同问题进行了认真的考虑,我们觉得第一步使用标准API隔离底层服务版本逻辑的变化,只要接口不变或兼容,就认为是同一个API,不兼容的变更就认为是一个新的接口。第二步根据开发进度,部署开发好的API或者暂时使用API挡板模拟程序,保证测试过程的平滑推进。第三步对公共的组件部分使用基线版本,构建最小测试域,快速完成功能测试和接口测试,或者单一功能的性能测试。
2. 部署及功能测试
功能测试重点检查实现的微服务是否满足功能性要求。单元测试已经做了初步验证,这里根据微服务需求和设计等规则生成的测试用例,验证输入和输出是否符合预期结果。同时检验微服务部署、配置、安全等能力。对于异常结果则记录缺陷,生成测试报告,发送相应职责的人员来检查确认。
这个过程是DevOps自动化流程中的一部分,具体的工具选择和流程定义可能不同公司不同场景会不一样。我们觉得适合自己就好。
3. API接口测试
我们使用API网关来帮助完成部分服务治理工作,因此微服务会在API网关上映射API接口。一个微服务可能会映射为多个API,或者多个微服务映射为一个API(可能涉及网关层的服务编排,通常不建议这么做),同时会定义API接口的访问控制策略、流量控制策略、安全策略、路由策略等。API接口配置难以实现自动化,需要接口管理人员来完成相应的工作。然后根据相应的策略规则生成测试用例完成接口测试工作。
测试是一项需要合作进行的工作,而且会涉及到众多不同的组件,因此我们觉得在考虑DevOps的时候需要考虑不同角色的职责和如何更好的协调不同角色的工作,很难让一个人做所有的事情。测试人员的素质往往直接决定了软件产品的质量,所以我们也提议过:让专业的人用专业的工具做专业的事!角色分工可能还是需要的。
4. 应用(集成)测试
微服务架构下集成测试可以看做是应用测试。应用由微服务编排而成,根据业务需求编排部署为不同的业务应用。比如客户中心应用、产品中心应用、服务中心应用等。应用测试通常会包含界面测试、业务流程测试、部署扩展测试等。
5. 性能及其他非功能性测试
微服务性能、可用性、容错性、弹性以及灾备能力等可能都需要考虑。利用容器平台的话可以借助于容器的弹性伸缩、资源调度、高可用部署等特性,实现微服务的高可用、弹性、容错和灾备能力等。
微服务性能测试可能需要考虑基准测试、负载测试、压力测试、容量测试等,以获取微服务在不同条件下的性能指标。
(三) 生产环境验证
微服务达到生产就绪,部署于生产环境之后,还要做最后的生产环境验证。通常可以采用验收测试或者灰度发布的机制,使用历史数据或模拟数据,或引少部分流量以验证微服务实现的业务逻辑是否正确。
1. 验收测试
微服务在生产环境验证没有问题就可以确定合格而验收了。验收通常需要明确验收条件,包括功能性和非功能性验收条件。比如性能要求、平均延迟时间、单实例负载支持及资源需求等。验收测试通常需要需求部门参与,确定验收条件,在测试验证满足条件后签字验收。
2. 灰度验证
在多版本情况下,特别类似于App服务,经常变更,可能需要在生产环境中导部分流量做实际的生产验证,这样影响不会很大。引流的方式也很多种,可以根据需要导入不同的请求进行验证。这也是我们在API层实现负载均衡和API治理的原因之一。
三、 测试工具集成
DevOps过程很重要的是实现工具链的集成,测试工具、测试流程、缺陷管理、文档管理、缺陷自动记录,报告自动生成,包括区分租户和打通权限管理。我们觉得DevOps重要的是协调好微服务生命周期过程中各参与相关方的职责并能够激励相关方的主动性,做到测试流程的阶段自动化。
四、 自动生成测试报告
测试最终是需要一个测试报告作为参考的,也是后期基准测试的参考。测试数据可以考虑自动存储起来,在测试完成后自动输出测试报告,当然这需要DevOps平台的支撑。
五、 微服务生产就绪
微服务达不到生产就绪条件,我们宁愿它不上线,第一印象往往很重要,如果留下了很差的第一印象,后续再想改观就不是那么容易了。但要达到生产就绪,这些测试步骤可能必不可少,而且需要认真详细的进行验证。
除了功能性验证,微服务部署及非功能性验证也很重要,比如不同的部署方式可能运营策略会有不同,容器化部署其弹性可以借助于容器平台,非容器化部署其弹性就比较难实现。例如我们ESB服务虽然也能实现实例的扩展,但往往需要借助于人或者复杂的监控自动化工具协同。
微服务生产就绪可能需要考虑以下这些方面:功能性、可用性、伸缩性、高性能、容错能力、灾备能力、日志监控告警能力以及文档可用性等。实现业务逻辑功能是必须的,所以功能测试主要验证微服务的功能实现。可用性和容错能力会涉及部署方式,通常可以考虑负载均衡及容错机制,实现分布式多实例部署(也会涉及请求次序处理问题和数据存储问题等场景,不同场景部署和现实方式可能不同);灾备通常需要基于平台支持,部署于不同的数据中心用于特殊情况下的备份支撑;伸缩性可以利用容器的弹性伸缩能力;性能则和微服务实现及软硬件环境有关了,这个在不同的环境下差别还是有点大,不过至少可以从微服务的实现上确保微服务性能;日志监控和告警是基本的能力,可以规划平台级的统一的日志中心、监控告警中心;文档是认识业务微服务和理解业务微服务重要的助手,所以微服务整个生命周期都需要有相应的文档支持。