多年来,微服务一直是行业趋势,但组织却未能从该方法中获益,并因发布失败而苦苦挣扎。这些失败通常归结为测试服务之间的接口以获得预期的质量、安全性和性能的困难。
最终,未能以足够稳健的方式测试这些 API。一线希望是遗留 SOA 测试和微服务测试之间的测试概念和解决方案是相同的。如果您可以解决 API 测试问题,您就可以改进您的微服务版本。
Parasoft 产品免费试用
微服务带来新挑战
如今,数百甚至数千个微服务组合在一起定义现代架构已是司空见惯。
高度分布式的企业系统具有庞大而复杂的部署,而这种部署的复杂性通常被视为不实施微服务的原因。事实上,您正在分解的整体架构中的复杂性只是分解为更复杂的部署环境。
令外行人失望的是,复杂性并没有真正消失,而是演变成一种新的复杂性。
虽然微服务有望提高并行开发效率,但它们也带来了一系列新的挑战。这里有些例子。
- 在 API 层需要测试更多的交互,而之前 API 测试仅限于测试外部公开的端点。
- 并行开发障碍限制了打破整体结构带来的上市时间优势。对其他服务的依赖和复杂的部署环境降低了现实中的并行性。
- 对单体应用中成功的传统测试方法(例如端到端 UI 测试)的影响现在必须转移到 API 层。
- 由于分布式数据和计算,潜在的故障点更多,这使得故障排除和根本原因分析变得困难和复杂。
微服务测试的 3 个关键步骤
微服务测试的三个关键步骤是什么?简单描述一下,这些步骤是:
- 记录
- 监视器
- 控制
记录、监视和控制将帮助您实施测试方法,有效地发现要创建的测试,同时在需要隔离下游 API 时帮助您自动化组件测试。
实现这一点的支持技术是服务虚拟化。服务虚拟化通过一个基本功能将所有这 3 个概念变为现实:消息代理。
通过在部署环境中使用消息代理,您可以监控和记录 API 之间的消息流,并控制消息发送的目的地。
消息代理如何工作?
它旨在侦听给定端点或队列,然后将其接收到的消息转发到目标端点或队列。基本上,它是 API 的中间人。您主动选择在集成系统之间注入一个。一旦就位,您就可以开始利用它了。
API 和微服务测试
无论您的环境是高度分布式、部分分布式还是大部分单一,测试 API并克服它们所带来的挑战都没有太大不同。存在的集成数量越多,一些挑战就越严峻,但基本方法是相同的。
当将API 或微服务视为黑匣子时,我们可以将其分解为服务的客户端和服务的依赖项。将 API 作为黑盒进行测试意味着您的测试工具充当服务的客户端,其工作是验证它收到正确的响应。依赖项是您的服务需要集成才能正常运行的内容。客户端和依赖项之间都需要进行优化。
在探索这些优化之前,让我们从设计阶段开始,即规划微服务以及测试策略应开始的阶段。
微服务生命周期
设计阶段:定义清晰度要求
一个广为接受的 API 开发最佳实践是在设计阶段实现服务定义。对于RESTful服务,通常使用OpenAPI规范。
您的客户使用这些服务定义来了解您的服务支持哪些资源和操作以及您的服务期望如何接收和发送数据。REST 服务的服务定义中将包含描述消息体结构的 JSON 模式,以便客户端应用程序知道如何使用您的 API。
但服务定义不仅对于帮助其他团队了解您的 API 工作原理很重要,而且还对您的测试策略产生积极影响。
您可以将服务定义视为合同。这是开始构建 API 治理策略的基础。就像任何软件测试一样,API 测试中最大的挑战之一是应对变化。
随着敏捷实践的流行,变化从未如此迅速。当您试图与许多正在构建 API 的团队争论,然后期望所有这些 API 能够以某种方式彼此良好地合作时,执行这些合同是解决混乱问题的第一步。
验证和执行合同
如何执行合同?
作为任何自动回归套件的一部分,您应该检查您的团队编写的服务定义是否存在任何错误。Swagger 和 OpenAPI 有自己的模式,定义了必须如何编写服务定义。您可以使用它们在 API 开发生命周期的早期自动执行这些检查。
然后,除了验证合同本身之外,您还想检查您的服务返回的响应是否也符合合同。您的 API 测试框架应该内置支持,以捕获 API 返回偏离其服务定义架构的响应的实例。
这样想吧。汽车由数千个单独的零件组成,所有零件都需要完美配合。
如果负责动力装置的团队提供的发动机偏离了设计规范,那么当您尝试连接其他团队制造的变速箱时,您可能会遇到大问题,因为他们正在参考发动机的设计来了解螺栓需要对齐的地方。
这就是您在这里检查的内容。良好的 API 治理可以帮助您避免这些类型的集成问题。根据这些契约进行设计并遵守这些契约应该是 API 测试实践的首要关注点之一。
服务定义合同还可以帮助您的测试过程更能适应变化。针对 API 中的更改重构测试用例所需的时间可能会对测试产生巨大影响,从而导致测试被推到冲刺之外。
这既是质量风险,也是安全风险。这也意味着需要额外的测试时间。使用 API 测试框架时,它需要帮助团队在 API 设计更改时批量重构现有测试用例,以便他们能够跟上敏捷和冲刺测试的快节奏。服务合同和正确的工具可以减轻这一切的痛苦。
实施阶段:应用最佳实践
微服务开发并不意味着可以免费跳过单元测试。代码就是代码,单元测试是基本的质量实践。它可以帮助团队快速、尽早地发现回归问题,并以开发人员易于修复的方式进行修复——无论是哪种软件。
丑陋的事实是,不存在或反应性单元测试实践的软件团队往往会得到质量较差的结果。单元测试的开销被认为太多,因此许多经理和领导者没有优先考虑它。
这是不幸的,因为工具市场已经成熟,开发人员的生活变得更加轻松和高效,而单元测试以及成本和质量之间的权衡比以前少得多。单元测试构成了可靠测试实践的基础,不应被忽视。
此外,开发人员的软件质量实践已经成熟,具有 API 开发的专用编码标准。2019年,国际非营利组织OWASP发布了OWASP Top 10 API安全标准。
像这样的编码标准可以帮助微服务团队避免常见的安全性和可靠性反模式,这些反模式可能会给他们的项目带来业务风险。尝试在没有工具的情况下采用编码标准几乎是不可能的。
幸运的是,现代静态分析工具,也称为静态应用程序安全测试 (SAST) 工具,与行业标准保持同步,并将支持该标准。开发人员可以在编写代码时扫描代码,并将其作为持续集成过程的一部分,以确保不会遗漏任何内容。
组件测试阶段:使用 API 依赖代理
组件测试意味着单独测试您的微服务。实现真正的隔离面临一些挑战,例如了解如何处理微服务的依赖项。此外,作为微服务开发人员,最难预测的事情之一就是准确理解其他系统将如何使用您的 API。
API 的客户端应用程序可能会发现从未考虑过的微服务的创造性用途。这既是商业上的祝福,也是工程上的诅咒,这也正是为什么花费精力来理解 API 用例如此重要的原因。
设计阶段的 API 治理是重要的第一步,但即使有明确定义的契约和对微服务响应的自动模式验证,您也永远无法完全预测端到端产品的需求将如何发展发展,以及这将如何影响您领域内的微服务。
记录、监视和控制将帮助您实施测试方法,有效地发现需要哪些测试,同时在需要隔离下游 API 时帮助您自动化组件测试。实现这一点的支持技术是服务虚拟化。
服务虚拟化通过一个基本功能将所有这三个概念变为现实:消息代理。使用消息代理可以监控和记录 API 之间的消息流,并控制消息发送的目的地。
精心策划与精心设计的服务
编排和编排(或反应式)服务是描述同步或异步消息传递模式的奇特术语。
如果您的服务使用消息代理与 AMQP、Kafka 或 JMS 等协议进行通信,那么您正在测试精心设计的或反应式服务。
如果您正在测试 REST 或 GraphQL 接口,那么这是一个精心策划的或同步的服务。
就本文而言,您所面对的协议和消息交换模式并不重要。但是,如果您的 API 测试框架不支持您的组织选择采用的协议,您可能会发现将这些原则应用于异步消息传递会更加困难。
捕获客户端使用场景
微服务团队很难预测其他团队将如何使用他们的 API。我们知道端到端、完全集成的测试既昂贵又缓慢。使用服务虚拟化工具中的消息代理功能,您可以记录来自上游客户端应用程序的流量,以便您可以捕获真实的使用场景,从而显着提高您对 CI/CD 管道中应运行哪些测试的了解,而无需这些客户端应用程序始终存在以触发该流量。
换句话说,记录使您能够重播这些集成场景以进行自动回归测试,这比要求客户运行测试(间接测试您的 API)更简单、更容易管理。这就是为什么将服务虚拟化与 API 测试相结合的工具如此受欢迎。它们可以轻松记录此 API 流量,然后将其用于您控制下的 API 场景测试。
使依赖关系易于管理
测试您的服务很快就会变得困难,因为它依赖于测试环境中的其他 API,这会带来可用性、实际测试数据和容量方面的问题。
这可能会将测试工作推到冲刺之外,并使团队难以及早发现集成问题以便有时间处理这些问题。这是服务虚拟化的传统用例,该技术允许模拟或模拟下游 API 的响应(这样做时,创建服务的虚拟版本)提供隔离,以便您可以更早、更轻松地全面测试您的 API您的 CI/CD 管道。
当消息代理部署在环境中时,团队可以记录 API 流量,然后构建忠实、真实地响应微服务的虚拟服务(包括有状态事务,其中模拟依赖项必须正确处理 PUT、POST 和 DELETE 操作),而无需真实的操作可用的依赖项。
有状态服务虚拟化是创建涵盖所有测试用例的最真实虚拟服务的重要功能。
集成测试阶段:控制测试环境
现在让我们将测试范围进一步缩小到集成测试。在此阶段,有时称为系统集成测试或 SIT 阶段,测试环境是类似生产的环境,可确保不遗漏任何缺陷。
您应该期望消息代理能够控制您是否想要与依赖项建立隔离的连接或现实世界的连接。控制的另一个方面是确保消息代理可以通过 API 轻松管理。CI/CD 流程高度成熟的组织正在自动化部署和销毁工作流程,其中消息代理的编程控制是必须满足的要求。
当您处于集成测试阶段时,您可以从消息代理公开的可见性(或可观察性)中提取哪些优化?
这就是监控功能对于支持自动化测试的服务虚拟化解决方案至关重要的地方。来自消息代理的监控将暴露这些复杂工作流程的内部工作原理,以便您可以实施更好的测试,告诉您问题出在哪里,而不仅仅是问题存在。
例如,考虑一个订单处理系统,它需要检查多个下游服务(例如库存、计费和运输系统)来履行订单。对于给定的测试输入,您可以针对某些幕后行为进行断言,以帮助开发人员查明测试失败的原因。当您的团队花费更少的时间来找出问题发生的原因时,他们就有更多的时间来实际解决问题。
测试微服务的五个技巧
这里有五个技巧可以帮助您制定微服务测试策略。请记住,这些只是建议。与所有类型的测试计划一样,您需要考虑您的设置的具体情况。
- 将每项服务视为一个软件模块。像对任何新代码一样对服务执行单元测试。在微服务架构中,每个服务都被视为一个黑匣子。因此,对每个进行类似的测试。
- 确定架构中的基本链接并测试它们。例如,如果登录服务、显示用户详细信息的前端和详细信息数据库之间存在牢固的链接,请测试这些链接。
- 不要只测试快乐路径场景。微服务可能会失败,模拟失败场景以在系统中建立弹性非常重要。
- 尽力跨阶段进行测试。经验证明,使用多种测试实践组合的测试人员,从开发开始,逐步扩大测试范围,不仅增加了错误暴露的机会,而且效率很高。在复杂的虚拟环境中尤其如此,其中各种库之间存在微小差异,并且尽管存在可视化层,底层硬件架构仍可能产生不可预见的、不期望的结果。
- 对新代码使用“金丝雀测试”并对真实用户进行测试。确保所有代码都经过充分检测。并且还使用您的平台提供商提供的所有监控。这满足了“左移”测试和“右移”测试,因为您也在“野外”进行测试。
揭秘微服务
微服务将继续存在。不幸的是,组织未能获得该方法的好处。归根结底是测试分布式系统之间的接口(即 API)以获得预期的质量、安全性和性能的难度。
我们需要一种微服务测试方法,能够发现、创建和自动化组件测试。支持技术是消息代理和服务虚拟化,它们与功能丰富的 API 测试框架紧密集成。
消息代理可以记录 API 流量、进行监控以发现场景和用例,以及进行控制以管理和自动化 API 测试套件。与服务虚拟化相结合,自动化微服务测试成为可实现的现实。