随着互联网的不断发展,越来越多的企业对软件测试的重视程度也在不断的提高,而今天我们就一起来了解一下,微服务架构技术对软件测试都有哪些影响。
总体的测试策略
软件测试的目的是确保软件产品的质量符合预期。衡量测试质量的指标有很多,常见的是测试覆盖率和测试成本(包括测试所用时间、测试维护成本),而衡量测试效果的主要手段则是终产品在实际使用中暴露出来的问题数量(BugNumber)。
具体到采用微服务架构的产品而言,MartinFowler在关于软件测试的论述中提出了其目的:
开发团队采用的任何测试策略,都应当力求为服务内部每个模块的完整性,以及每个模块之间、各个服务之间的交互,提供全面的测试覆盖率,同时还要保持测试的轻便快捷。
因此,我们需要采取下面几点测试策略:
我们一方面要保证从各个维度上,无一遗漏地对微服务进行全面的测试,特别是对于分布式的系统,系统的所有层次都必须被覆盖到;另一方面又要确保测试执行的快捷,这样才能保证持续集成/持续交付(CI/CD)的实现。
要确保测试策略的正确实施,工具和技术固然重要,然而,先需要测试人员在团队中树立起提倡质量一的“测试文化”:
无法通过测试的代码不应该被合并到代码仓库里;
无法通过测试的代码不应该被发布出去。
不能为了测试而测试,测试的真正目的是为了交付高质量的软件给用户,而不是把资源浪费在没有实际意义的测试用例上。所有的测试层次、流程和用例,都应该有的放矢。
传统测试方法面临的挑战
以一个常见的开发团队为例,在采用了微服务架构之后,很可能同时会开发多个模块(即微服务),每个微服务有不同的客户要求、开发周期、开发进度和交付期限,但是整个团队又必须保证能够在固定的时间节点(譬如每月一次、每两周一次,甚至每天一次或者多次),持续地、稳定地为用户提供可以部署、使用的产品。这意味着,过去那种先等产品经理、业务部门提供需求,开发人员再进行开发,后交给测试人员执行集成测试、端到端测试的方法,已经无法提供足够的测试粒度和足够快的响应速度。
归结起来,与基于单体式架构的传统测试方法相比,微服务架构对测试提出了以下挑战:
服务/模块/层次(layer)之间存在复杂的依赖性。
在单体式架构中,通常使用集成测试来验证依赖是否正常。而在微服务架构中,服务数量往往很多,每个服务都是独立的业务单元,服务之间主要通过接口进行交互,如何保证这些依赖的正常,是测试人员面临的主要挑战。这意味着,如果想单独测试某一个服务,或者服务中的某个模块,就必须剥离它们对于其他环节的依赖关系。这需要通过Mock、Stub等方法来实现。
不同的服务可能会在不同的环境/设置下运行。
特别是一些后端服务,与前端服务的运行环境可能截然不同。这时在考虑对每种服务设立自动化管线时,就必须有针对性的设置相应的环境配置。而且,在微服务架构中,每个服务都独立部署,交付周期短且频率高,人工部署已经无法适应业务的快速变化。因此如何有效地构建自动化部署体系,保证配置的稳定性、可重复性,是微服务测试面临的另一个挑战,必须与DevOps人员一同解决。
涉及多个服务的UI端到端测试(End-to-End测试,简称E2E测试)非常容易出错。
因为每种服务的开发进度不同,集成不同服务的端到端测试往往会因为某一个服务的微小改动而出错。这种出错是测试人员希望避免的干扰信息。这意味着,对端到端测试的设计,必须采取一定的防干扰、防误报策略。
测试结果可能取决于网络的稳定性。
微服务架构是基于分布式的系统,而构建分布式系统必然会带来额外的开销。
性能:分布式系统是跨进程、跨网络的调用,受网络延迟和带宽的影响。
可靠性:由于高度依赖于网络状况,任何一次的远程调用都有可能失败,随着服务的增多还会出现更多的潜在故障点。因此,如何提高系统的可靠性、降低因网络引起的故障率,是系统构建的一大挑战。
异步:异步通信大大增加了功能实现的复杂度,并且伴随着定位难、调试难等问题。
数据一致性:要保证分布式系统的数据强一致性,成本是非常高的,需要在C(一致性)A(可用性)P(分区容错性)三者之间做出权衡。
特别是涉及到数据存储和外部通信的部分,如果在测试中不摆脱这些因素的影响,就可能会得到一些随机性的误报,干扰测试结果。
故障分析的复杂度会随着服务的增加而提高。
微服务架构中,因为每个服务都需要独立地配置、部署、监控和收集日志,因此在发现问题之后,进行诊断分析时,搜集缺陷信息的成本呈指数级增长。
与交付周期不同的开发团队之间的交流成本。
这一点虽然跟技术无关,但是实际上会对测试人员的工作造成很大的困扰。因为开发模式分解为负责不同服务的多个小组,测试人员往往每天要花费大量的时间,了解不同团队的开发进度。如果还需要手动进行回归测试(RegressionTest),终将会不堪重负。所以自动化测试是必须采取的手段和方向。