译者注:这是国外一篇介绍如何测试云原生应用的文章,云原生应用通常是基于微服务架构风格的分布式应用程序,传统的测试方法和技术已不能满足产品交付的质量要求,只有结合现代测试技术,既加强研发阶段的测试,又引入产品发布后的线上测试,才能有效应对云原生应用在功能、性能、安全、可靠性方面的挑战。这些新的技术包括契约测试,灰度发布,混沌工程,在线监控和日志分析等。

一、应用程序的“云原生化”

越来越多的公司正将本地部署的应用迁移(或计划迁移)到云上,它们的目标是设计、架构并构建的应用程序可以很容易地扩展并部署到云上,并且可以充分利用云平台(如AWS、Azure,或GCP)提供的计算模式。

“云原生化”和开发云原生应用指的是设计、架构并构建的分布式软件应用能够完全利用云服务商提供的PaaS(Platform-as-a-Service,平台即服务)和IaaS(Infrastructure-as-a-Server,基础设施即服务)的服务模式。这些应用通常是作为一组微服务(基于微服务架构风格)构建的。

这些松耦合的微服务运行在一个由公有云、私有云和混合云提供的动态环境中的容器化和动态编排平台上(基于Kubernets、Docker等技术)。促使企业进行应用的“云原生化”尽管有不同方面的原因,但其中包括一些最重要的驱动因素,如:缩短重要的软件应用的宕机时间、增加应用的弹性能力、根据业务需要动态扩容或缩容,提高应用开发速度、快速响应用户需求、更专注于创新从而增加更多的业务价值。

二、云原生应用的测试方法

测试总是帮助我们更深入地挖掘问题,并向用户交付高质量的产品。软件测试在帮助我们收集产品的状态、可维护性、性能、健壮性和可靠性等大量有用信息方面发挥了重要作用。通过对这些信息进行分析,企业的决策者们可以更有信心地进行产品发布的决策。

相比其它软件应用(例如单体架构的应用)的传统测试方法,云原生应用的测试要更复杂。这是因为云原生应用是动态、分布式构建的一组微服务(每个微服务可以独立发布),发布速度更快(通常采用CI/CD和DevOps实践),而且存在难以预测和跟踪的故障模式。

这就要求我们适应这些变化,重新审视传统的测试技术,并采用新的、现代的测试方法来预见、检测、响应、调试、分析和报告问题。

这些测试技术将在许多方面帮助我们找到并揭示大量信息,这将有助于提高云原生应用的整体质量。对于这类应用,软件测试已成为软件开发生命周期的所有阶段中不可分割的一部分,并且促使业务分析人员、开发人员、测试人员、架构师和软件设计人员等进行更多沟通和交流:提出疑问,共享信息,讨论并评估问题和风险。现在就让我们一起看看针对云原生应用的有效的测试技术。

1)单元测试,集成测试,端到端的测试

通过在微服务架构的云原生应用中测试单个服务组件中的最小可测试单元,可以在开发早期阶段发现许多缺陷。快速、可靠、自动化的单元测试不仅能确定服务组件的独立单元/模块是否能正常工作,也将有助于开发人员观察单元/模块状态的变化,检查对象之间的交互,以及对象之间的依赖,对于组件的状态获得快速反馈,或者由于代码变更导致了回归缺陷等。这些测试让软件代码更具有可测试性并有利于代码的重构。

软件应用的服务组件在集成之后,由持续集成服务器触发的集成测试将有助于测试各个服务组件之间或服务组件与外部服务、系统、数据存储之间的通信路径和交互。尽管测试所有的集成点是困难的,但团队必须采用基于风险的测试方法,根据制定的目标、范围和优先级执行测试。

对于云原生应用来说,执行端到端测试是比较困难的,因为这涉及到微服务架构中每个独立开发的部分,测试进度会比较缓慢,而且有时候会非常不稳定,不得不考虑到服务组件之间的异步调用和环境因素的影响。这都造成端到端的测试在测试准备、运行和维护方面的成本较高。尽管如此,研发团队仍然需要运行其中的一些端到端的测试,尽管不那么频繁,但需要覆盖重要的业务路径,并验证完整的应用是否满足业务需求。

2)契约测试

既然会涉及单个独立的微服务,研发团队也需要对微服务执行契约测试。微服务体系架构由“生产者”服务组件和“消费者”服务组件组成。当消费者组件试图与生产者组件结合并使用它的输出时,一个“服务契约”(由预期的输入和输出组成)就在它们之间形成。

由这些契约测试组成的自动化测试套件可以集成到流水线中,运行这些测试来验证生产者和消费者组件中的任何更改是否符合二者之间的服务契约。开发和运行契约测试是测试云原生应用的一项重要内容。

3)非功能测试

对于云原生应用来说,功能测试非常重要,可以验证产品是否满足业务需求。但是,当产品发布到生产环境中,功能测试能够提供产品将以预期的方式响应的信心吗?当突然出现服务器崩溃、服务组件宕机或某些依赖服务不可用时,服务是否能够安全降级?产品上线后是否足够安全?该产品能否应付突发的大量用户请求?

非功能测试对于云原生应用非常重要。对于上述问题,任何缺陷或者偏离预期行为的情况都要求我们以最少的工作量和步骤尽快发现、分析并修复问题,以避免这些问题再次发生。

为了确保这些问题发生的机率或影响很小,我们需要借助有用的工具(许多工具是云提供商自己提供的)测试产品的性能(如延迟、负载平衡的影响、缓存、产品性能中的风险因素、基于性能指标来对比和提供反馈结果的基准测试等)、可用性、负载(例如在接近真实负载条件下对产品吞吐量的影响)和安全性(静态和动态),并预先处理任何潜在的风险。

4)混沌工程和失效模式测试

说到质量工程,我们大多数人都知道像“FMEA”(失效模式和影响分析)技术,它可以帮助我们识别产品中的潜在失效模式及其原因和后果。对于单体应用,大多数潜在的故障模式是已知的,可以识别的,因此可以在代码结构中处理。即使不处理,当缺陷发生时也能够快速修复。

但是对于微服务来说,产品在生产环境中失败的方式是难以计数、不可预测的,因为涉及到大量的复杂性。在这些情况下,“混沌工程”会很有帮助。它是一种识别在生产环境中产品失效的方法,以建立对系统应对意外或未知操作能力的信心。

“混沌工程”和FMEA一起,通过注入可控的故障,帮助我们获得一个可靠性和弹性能力更高的产品,让我们能够检测和分析这些故障,从而预知产品在哪些方面会出故障。这将帮助我们调整现有的流程,以防止故障级联的后果,并提前计划如何缩短MTTR(Mean Time to Recovery/Restore,故障平均恢复时间)。

5)可观察性、在线监控和日志分析

作为软件工程师,对云原生应用我们既要在上线前进行测试也要在上线后进行测试。如果操作得当,线上测试可以为我们提供许多有价值的信息,为计划下一个版本的弹性、可伸缩性和灵活性提供重要反馈信息。但必须记住,线上测试的设置和执行很复杂,在执行这些测试时必须非常小心,并充分考虑到,如果线上测试没有正确和安全的执行,对业务和用户带来什么样的影响。

“可观察性”是帮助我们更好地理解产品中软件行为的方法之一,是指通过观察产品的输出来了解产品内部状态的方法。我们可以使用一些监控技术和工具收集、存储、维护和查询应用的状态、行为,以及服务之间交互相关的信息。这些日志和指标可以被进一步分析来获取有价值的发现,或者快速评估和分析缺陷。一些云服务提供商会提供开箱即用的功能和工具帮助我们实现监控、信息收集和分析。

三、结论

我们必须明白,无论计划和执行多少功能测试和非功能测试,无论我们如何努力提高这些云原生应用的质量,最终用户仍然会面临问题。我们的目标是减少意外事件的风险,快速分析和修复故障,从既往事件中学习并将这些知识用于下一个版本。

在生产环境中发现缺陷的成本是非常高的,我们应该在软件的开发生命周期中尽早发现缺陷。在生产环境中,我们可以利用金丝雀部署(把所有功能推送给部分用户),暗启动(把新功能/主要功能推送给部分用户),智能功能切换/标志/位/翻转器(允许特定功能的应用被激活或停用)等技术在生产环境中逐渐暴露缺陷。

但我们也必须记住,由于各种限制因素,包括预算、团队承接能力、时间表、上市时间、大量互相依赖/独立的服务、环境的可用性等,通过已知的测试策略做详尽的测试是不可能的。因此,团队需要采取基于风险的测试方法,也必须意识到和缺陷有关的各种类型的成本,比如检测成本,分析调试成本,机会成本,修复成本,验证成本和维护成本。

考虑到所有本文中讨论的因素,可以肯定的是,尽管测试云原生应用是困难和具有挑战性的,但我们可以让新的测试方结合自身的专业知识、不同的测试技术和策略,向用户交付高质量的产品。

来源:软件质量报道

作者:Sumon Dey

4月每周四晚8点,【冬哥有话说】DevOps之庖丁解牛,拆解DevOps的工具及具体实战。公众号留言“解牛”可获取地址

  • 0401《数据库持续交付流水线分享与演示(Azure DevOps+Flyway)》
  • 0408《持续交付中的版本管理与基于Azure DevOps扩展框架的插件开发》
  • 时间待定,本周四晚暂停一期《微服务,多团队协作中的API测试怎么做 - Pact契约测试》**
  • 0422《BoatHouse端到端流水线展示》

用户bPcN1SC
149 声望55 粉丝