转载

我们使用了不同的技术栈,但是都实现了微服务测试

我们使用了不同的技术栈,但是都实现了微服务测试

作者 | Wojciech Bulaty、Liam Williams

译者 | 王强

编辑 | 田晓旭

当我们使用了微服务架构和基于容器的基础设施之后,那么我们就不得不重新制定一个测试策略,因为微服务架构对在线(远程)依赖项的依赖较多,而对进程内组件的依赖较少,所以测试策略和测试环境都需要随之做出改变。

在线通信越多,测试微服务之间的连接和契约所需的精力就越多,所以在处理微服务的组件依赖方面,我们可以尝试新的测试技术,同时可以从上市时间、成本和风险的角度选择测试技术。

当使用服务虚拟化等技术测试单体应用时,不必同时测试所有内容,可以分而治之,测试单个模块或者是一组关系密切的组件。在测试单体应用时,使用 服务虚拟化 可以将测试环境与相关组件解耦,并减少以下问题的影响:

  • 难以准备或配置相关组件

  • 测试数据准备成本高,耗时多

  • 团队因为其他团队没有及时交付 API 而受阻

  • 测试环境时间调度

而在微服务架构中,我们可以使用更广泛的测试技术。微服务更多的是通过网络进行通信,所以需要彻底地测试网络连接的影响。

为了帮助大家彻底了解如何做微服务测试,我们研究了以下 6 家企业的实践过程,其中有 3 家企业是组合了测试技术,并把其作为整体解决方案,而另外三家企业是通过单一技术来解决特定问题。

美国保险业初创公司

架构:

Greenfield 微服务取代了最近构建的单体架构。

技术栈:

Go、Python、NodeJS、gRPC、Protocol Buffers、Docker 和 Kubernetes。

任务优先级:

快速交付;将在首次生产发布后重构发布流程。

使用的测试技术:

  • 使用另一个微服务的测试实例测试你的微服务(端到端测试)

  • Mocks(进程内)

  • 服务虚拟化(通过本地 / 远程)

  • 测试容器

契约管理:

  • 团队使用 API mocks 在彼此之间传达契约的语法和语义。

  • API mocks 定义了自动测试的契约快照,以确保它们与最新的协议规范保持同步。

要点:

  • 使用了 gRPC 协议 API mocks 来允许团队并行工作。

  • 使用自动化测试来确保 API mocks 不会过时。

这家初创公司有两个团队,当时他们在开发一组共三个新的微服务,必须在两个月内交付。这些微服务正在替换已弃用的一个单体架构的一部分内容。团队决定使用单元测试来测试 Go 微服务的内部组件,这些单元测试使用了进程内 mocks,基于 GoMock 框架实现。他们使用组件级集成测试来测试与数据库的交互,该测试使用测试容器数据库来避免依赖数据库的共享实例。

为了管理团队之间的契约并允许团队并行工作,他们决定使用 API生产者创建并与 API 消费者共享的 API mocks。他们使用 API mocking 工具建了 gRPC API 服务 mocks。

他们还在预生产环境中使用了一些手动端到端测试,以确保在没有足够的自动化测试的情况下,微服务也能协同工作。他们将在第一个期限之后填补自动化测试中的空白。

由于这是一个必须按时投入生产的绿地项目(新开发的项目),因此公司决定不对微服务 API 进行版本控制。相反,每次发布时他们将所有内容一起发布到生产环境(通常称为快照版本)。他们考虑到了服务的停机时间,以及与之关联的,面向客户的组件出现的小幅度功能退化,这些问题已事先通知客户。在发布第一个产品之后,他们开始对 API 进行语义版本化。这使他们能够更好地管理 API 更改,以实现向后兼容性并为客户提升正常运行时间。

他们在早期就遇到了另一个有趣的问题,那就是 API mocks 每天都会过时,因为 API 确实每天都在变化。这些更改通常不会向后兼容,因为开发人员正在重构协议文件以反映正在快速进化的领域模型,当时他们尚未明确定义这一模型。这种状况是绿地项目普遍所有的特征,其中项目团队使用迭代方法为客户交付价值。为了按时完成任务,公司决定同时向 mock 和真实的微服务发出请求来测试 API mocks。他们将两者的响应与该公司专属的自定义格式所定义的"预期请求 / 响应对"的契约定义进行了比较。这样,与契约文件中定义的预期行为的最新定义比较后,API mocks 和真实服务就可以被证明是最新状态了。

西班牙电子商务公司

架构:

从拥有十年历史的单体式服务器转向微服务。

技术栈:

Java、HTTP REST、gRPC、protocols、JMS、IBM MQ、Docker 和 OpenShift。

任务优先级:

采用 API 优先方法,以允许并行工作和解耦团队。在公司的 3,000 名开发人员中大规模采用微服务。

使用的测试技术:

  • 使用另一个微服务的测试实例测试你的微服务(端到端测试)

  • Mocks(进程内)

  • 服务虚拟化(通过本地 / 远程)

  • 测试容器

契约管理:

  • 团队使用 API mocks 在彼此之间传达契约的语法和语义。

  • 为驱动开发(BDD)API 测试,还可以验证 API mock 交互。

  • 这些 API 设计为始终向后兼容。

要点:

  • 允许团队使用 API mocks 实现的 API 优先方法来并行工作。

  • 开发人员根据 OpenAPI 和协议规范创建了 mocks。

这家公司决定从单体架构迁移到更自治的团队组合和微服务上。在转型过程中,他们决定采用推荐的良好实践,而不是将特定的技术和解决方案强加给团队。

团队架构师负责收集开发人员要使用的技术、指南和工具。他们还负责创建一种架构,通过复用成熟的技术、工具和组件来最大程度地减少浪费。

开发人员编写了 JUnit 和 TestNG 集成测试,并使用 API mocking 工具 mock 了从属组件。他们还编写了 Cucumber/Gherkin、BDD 和 API 验收测试来捕获业务需求(他们称其为“契约测试”),使用了微服务的 Docker 映像和称为 Traffic Parrot 的 API mocking 工具的 Docker 映像。BDD 测试通过验证 API mocks 上的交互来验证微服务 API 和其与从属组件的交互。这样,BDD 测试通过断言和验证来验证微服务 API 请求和响应,以及它与从属组件的所有通信。

该公司使用 JMeter 来创建性能测试。JMeter 测试可以测试单个微服务,并使用真实依赖项(例如微服务和旧的单体组件)的 API mocks 替换从属组件。他们使用的一种技术是在 API mocks 上配置响应时间,并观察增加的延迟对所调用服务的影响。

所有的单元、验收和性能测试都在 Bamboo 持续交付管道中进行。

这家公司创建 API mocks 的方式很有趣。他们使用了两种方式。

如果开发人员想要消费的 API 已经存在,他们会记录请求和响应从而创建 API mocks。开发人员首先在他们的计算机上创建一个新测试。然后,他们运行测试并记录测试内容从而创建 API mocks。他们将测试和 mocks 提交给 Git 中的微服务项目。在 QA 管道(在每次提交时启动以检查产品质量的管道)中,他们启动了一个 Docker 容器,该容器运行 API mocking 工具并从微服务项目中加载 mock 定义。

如果微服务要消费的 API 尚不存在,则开发人员将根据 HTTP REST API 的 OpenAPI 规范创建 API mocks,或根据 gRPC API 的协议文件创建 API mocks。

每当开发人员在测试套件中需要 Cassandra 数据库时,他们就会运行 Cassandra 数据库测试容器。这样做的好处是不必依赖数据库的中心化副本。他们使用自定义的 Cassandra 配置构建了自己的 Docker 映像。

他们还开发并运行自动化的端到端烟雾测试。这是测试微服务之间契约的技术之一,它能确保微服务组可以很好地协同工作。端到端测试套件的存在是有道理的,因为它不仅测试了在 BDD 测试中测试的契约生产者方,而且还测试了消费者方,因此提供了更多的可信度。架构师会监视端到端测试的数量。他们将端到端测试套件的复杂性保持在不会拖累发布流程或日常开发活动的水平。

英国媒体公司

架构:

在生产环境中已经有超过 100 种微服务,这些微服务运行在具备手动配置硬件的环境中。

技术栈:

Java、HTTP REST、Docker 和 Kubernetes。

任务优先级:

迁移至云(内部 Kubernetes 集群)。从运营团队管理的硬件迁移到 Kubernetes 集群上,后者由自治功能团队管理,从而降低基础架构成本并缩短面市时间。通过引入零宕机时间版本,将正常运行时间从 99.5%提高到 99.95%。

使用的测试技术:

  • 使用另一个微服务的测试实例测试你的微服务(在早期使用其他微服务进行手动探索性测试)

  • 测试具有第三方依赖项的微服务(第三方的英国媒体基础设施测试 API)

  • 测试具有非软件(硬件)依赖项(网络硬件)的微服务

  • Mocks(进程内)

  • 服务虚拟化(通过第三方服务和其他微服务的本地 / 远程 API mocks)

  • 测试容器(Oracle 数据库测试容器、API mocks 测试容器和从属微服务测试容器)

契约管理:

  • 消费者驱动的契约以及集群中其他微服务的契约测试。

  • 第三方 API 契约的窄集成测试。

  • 无回归端到端测试。

  • BDD API 测试还可以验证 API mocks 交互。

  • 这些 API 向后和向前兼容(版本兼容性 n±1)。

要点:

使用了消费者驱动的契约和消费者驱动的契约测试、BDD API 测试以及 API 版本管理取代端到端测试。

这家公司现有一个包含 100 多个微服务的技术栈,主要使用自动化 BDD 端到端测试,但是它们的维护成本很高,因为开发人员需要花费大量时间来编写和调试测试套件。由于被测系统的复杂性导致测试不够稳定,所以开发人员经常会感到沮丧,从而导致许多不确定的故障点。这些测试还使他们无法做到按需发布新功能,因为这些测试需要花费几个小时才能运行完毕。他们意识到,这套复杂的测试套件花费的时间太久了,并且放弃它的成本也太高了。

吸取了这些教训后,该公司决定不在其正在研究的新产品上实施端到端测试。这一产品将在新的内部 Kubernetes 集群上运行,并尽量减少端到端测试的使用,而应用新的契约管理技术。

为了针对新的微服务之间的契约以及整个产品行为来提升信心,他们使用的主要方法是以消费者驱动的方式设计契约。公司选择使用 Pact-JVM 来测试消费者驱动的契约。公司中的大多数团队是首次接触消费者驱动的契约,但他们很快就掌握了这种方法。

他们用来改善微服务的另一项技术是在每个功能团队中配备一名人工测试员。这名测试员将针对每个新用户故事进行手动探索性测试。测试时,这名测试员将在自己的计算机上使用 Docker 测试容器运行微服务,有时还会与其他微服务一起运行。

开发人员决定基于清洁架构的理念来实现某些微服务,这需要使用进程内 mocking,这个案例中他们使用的是 Mockito。

作为 Docker 测试容器运行的 API mocks 被广泛用于 mocking 第三方的网络硬件和栈中的其他微服务。

当在 TeamCity 构建内部运行时,BDD 验收测试使用 WireMock 进行 API mocking。手动测试人员使用具有 Web 用户界面的 API mocking 工具进行探索性测试。这种方法简化了设置测试场景和测试微服务的工作。

美国铁路公司

问题:

迁移到为自治团队提供的新 CI/CD 管道基础架构,需要一种服务虚拟化工具,该工具可以在管道内部运行,而不必使用共享环境。

解决问题的技术:

测试容器(将 API mocks 作为 Docker 测试容器运行)

要点:

使用按需 API-mock Docker 测试容器来避免依赖共享的服务虚拟化基础架构。

这家公司决定从单体架构过渡到微服务架构上。在转型过程中,他们推动的一项主要变革是新的 CI /CD 管道基础设施。

负责设计管道架构的架构师希望使用在共享环境中部署的服务虚拟化。这样做的原因是这家公司已经有了适当的解决方案。虚拟服务已在团队之间共享,并且 CI/CD 会构建在现有的单体架构中。

经过仔细考虑,架构师意识到在新的微服务世界中,使用由众多管道、开发人员和测试人员共享的服务虚拟化环境效果会适得其反。公司转向微服务的原因之一就是让功能团队彼此独立地工作。依靠由中心化的团队管理的共享服务虚拟化环境并不会帮助他们实现这一目标。此外,任何共享环境都是一个单故障点,他们希望避免这种情况。

架构师决定,他们将使用 API mocks 而不是共享的服务虚拟化环境,这些 mocks 将作为构建作业的一部分来部署。他设计了一种完全分布式的部署方法,其中 API mocks 会按需部署。一个 Jenkins 构建将在测试套件之前启动 API-mock Docker 测试容器并在 OpenShift 中运行。构建完成后,这些 Docker 容器将被拆除。

以色列电子商务创业公司

问题:

将自动化 API 和第三方集成测试引入之前没有开发人员接触过它们的环境。

解决该问题的技术:

服务虚拟化(使用第三方 API 虚拟服务的在线 / 远程服务,前者由使用现成服务虚拟化工具创建的数据库支持)

要点:

使用第三方 API 服务虚拟化工具创建由数据库支持的虚拟服务,以加快刚开始接触自动集成测试的开发人员的上手速度。

这家初创公司正在向市场推出新产品。开发人员正在添加新功能,但没做过自动 API 或第三方集成测试。他们必须快速发布新功能,因此没有多大空间来更改现有的开发流程。

QA 自动化负责人在 Jest 中开发了 API 和集成测试框架。他使用了以前在许多项目中使用过的现成的商业服务虚拟化工具,从而创建了替代第三方 API 的虚拟服务。

该工具部署在了共享环境中,因为他相信这能让他对新测试方法的应用拥有更多控制权。每个单独的虚拟服务都由一个包含 HTTP 请求 - 响应映射数据的数据库表支持。他决定允许通过数据库设置虚拟服务,因为开发人员已经习惯在数据库中设置测试数据。他选择了开发人员比较熟悉的数据库 MongoDB。

这是向这家创业公司的开发人员介绍各种类型的自动化 API 和集成测试的第一步。这位负责人认为,开发人员可以轻松掌握数据库驱动的虚拟服务。每人几个小时的入门时间就足以让开发人员开始编写他们的第一个自动集成测试。

美国商品经销商

问题:

将亚马逊简单队列服务(Simple Queue Service,SQS)队列引入技术栈时,必须验证是否已将正确的消息发送到正确的队列,从而导致了手动测试问题。它还影响了自动化测试工作的成果。

解决问题的技术:

服务虚拟化(通过亚马逊 SQS 模拟器本地 / 远程进行)

要点:

使用亚马逊 SQS 模拟器可以在测试时无需访问实际的 SQS 实例。

公司将亚马逊 AWS 组件引入他们的架构。不幸的是,组织中的开发和测试团队没有协作机制,因此测试团队要手动工作,而来自开发团队的帮助却很少。这意味着测试团队无法使用可帮助他们测试产品的工具。他们总是落后于开发团队,赶不上进度,还要在周末加班。最重要的是,他们被要求引入自动化测试,以逐渐开始摆脱手动回归测试。

其中一项技术挑战是使用亚马逊 SQS 队列手动并自动进行集成测试。为此,他们使用了带有用户界面的亚马逊 SQS 模拟器,这使他们可以模拟有状态的 SQS 队列,从而继续进行手动测试。他们使用模拟器的用户界面来检查队列中的消息,以手动验证请求消息。在它的帮助下,他们还开始使用 SQS 模拟器的 API 引入与 SQS 集成的自动化测试。

小结   

以上案例中的企业使用了截然不同的实现方法,这意味着企业、团队在实践微服务测试时,可以根据环境、任务相关的熟练程度来选择不同的技术。如果你也有相关的故事和我们分享,欢迎在下方留言。

作者介绍

Wojciech Bulaty ,敏捷软件开发和测试架构专家。他将自己十余年的一线编程和领导经验用在了敏捷、自动化、XP、TDD、BDD、结对编程和简洁编码领域的文章写作中。他最近的成果是 Traffic Parrot,其中他通过提供 API mocking 和服务虚拟化工具来帮助使用微服务的团队加速交付、提高质量并缩短产品面市时间。

Liam Williams

,自动化专家,致力于通过高质量的软件解决方案来改进容易出错的手动流程。他是开源贡献者,并且是许多小型库的作者。最近他加入了 Traffic Parrot 的团队,进而将注意力转向了在转型现代微服务架构时改善测试体验的问题。

原文链接:

https://www.infoq.com/articles/testing-techniques-microservices-use-cases/

我们使用了不同的技术栈,但是都实现了微服务测试

原文  http://mp.weixin.qq.com/s?__biz=MzIzNjUxMzk2NQ==&mid=2247492270&idx=1&sn=04960c51e930d7c44353a92a3c3b8ba3
正文到此结束
Loading...