集成测试类型概述,重点关注为开发人员提供快速反馈的合并前测试。
译自 The Struggle To Test Microservices Before Merging,作者 Nočnica Mellifera。
对微服务进行良好测试 始终是一项挑战。当谈到测试时,测试阶段的模糊定义会立即出现。涉及所有服务的测试是集成测试吗?还是端到端测试?满足 API 规范的测试是契约测试吗?还是单元测试?具体来说,集成测试的概念可以涵盖许多方面:
但与其纠结于测试的是什么,不如问一个更好的问题:“集成测试的目的是什么?”如果集成测试的目的是查看我们更新的服务如何与我们堆栈的其余部分交互,那么我们希望在将代码与生产或预生产环境合并之前运行此测试。
适当的集成测试可以帮助尽早发现问题,从而减少缺陷进入生产环境的可能性。但是,集成测试的方法 可能会有所不同,每种方法都有其自身的优缺点。
让我们看一下集成测试的类型,重点关注提供快速反馈给开发人员的合并前测试,并探讨如何在开发人员工作站和拉取请求 (PR) 期间使用共享环境有效地运行这些测试。
我在科技行业的第一份工作是为在线课堂工具提供支持。在与工程团队的交谈中,我询问了测试覆盖率。团队告诉我,他们有自动测试来模拟虚拟课堂的正常更新操作。“你的测试用例中有多少学生?”我问道。“哦,很多,大约 50 个。我们想确保它可以处理大型课堂。”然后我解释说,我在现实世界中见过的最大的虚拟课堂大约有 2000 名学生,我们的整个用户体验在这些规模下真的崩溃了。这说明了,无论设计得多么仔细,完全人为的测试场景都可能无法模拟现实世界的情况。
使用模拟进行集成测试不需要完整的环境设置或启动许多依赖项。启动时间接近零,并且可以在笔记本电脑上运行测试堆栈,这意味着非常快速的反馈。
开发人员可以创建非常定制的测试设置,播种特定数据并运行精确测试。这里的主要好处是能够模拟特定交互,而无需完整的环境。
但是,维护模拟可能很费力。测试可能侧重于可能不反映现实世界条件的合成场景,这使得难以实现全面覆盖。模拟特别适用于验证紧密耦合组件(例如微服务 和数据库)之间的交互,但它们可能不适合所有类型的集成测试。
总的来说,模拟支持的测试很难建立“覆盖率”:我们可以确信我们已经涵盖了之前在两个组件中看到的案例,但不能确定我们涵盖了所有现实世界场景。
对集成测试执行契约测试具有一定的价值。当服务通过 HTTP 交互并具有 RESTful 关系时,发送预测的请求或响应可以帮助确保服务在更新后仍然可以相互通信。但是,编写大量请求可能非常耗时,而且我们仍然会进入模拟多个请求处理步骤的空间,这会导致更新通过所有测试但无法在生产环境中运行的风险。
端到端测试是真正考验实力的地方,当我们发送实际命中所有依赖项和服务的请求以形成正确响应时,我们会获得最可靠的测试。在使用真实微服务依赖项的 API 或前端级别进行集成测试 提供了巨大的价值。这些测试评估真实的行为和交互,提供对系统功能的现实视图。通常,此类测试在合并后在暂存或预生产环境中运行,通常称为端到端 (E2E) 测试。这种方法确保了全面的覆盖率和高精度,但由于仅在分支合并后才运行测试,因此开发循环变得更长,开发人员需要等待数小时或数天才能获得测试反馈。
更糟糕的是,在微服务环境中,大多数重大故障很可能在集成测试阶段被发现。我们不能让开发人员等待数天才能获得测试反馈,因为这些测试很可能失败。
我们真正想要的是一个现实的环境,任何开发人员都可以使用,即使是在处理 PR 的早期阶段。在合并之前实现 API 和前端级别测试的好处将节省编写和维护模拟的精力,同时测试真实的系统行为。这可以通过在共享基线环境中使用金丝雀式测试来实现,类似于金丝雀发布,但是在生产前环境中。为了澄清这个概念:我们希望尝试在共享的预发布环境中运行新版本的代码,在这个环境中,实验性代码不会破坏所有其他开发团队的预发布环境,就像金丝雀部署可以发布、在生产中出现故障,但不会让所有人的服务都宕机一样。
请求路由可以用于在具有所有依赖项的真实共享环境中对 PR 运行 API 和 E2E 测试,提供早期和准确的反馈。Lyft 等公司有效地利用了这种方法来简化他们的测试流程。
实现请求路由解决方案,让“测试”版本的服务与集群交互,同时又不破坏或修改其他开发人员的流程,对于您的测试流程来说非常有效,但它并非没有技术上的提升,这就是 Signadot 的用武之地。
Signadot 是一款工具,可以让任何规模的团队在共享的预发布集群中实现高质量的合并前测试。Signadot 使团队能够共享和维护单个环境,同时在选定的服务上运行测试。
Signadot 沙箱让用户可以尝试修改后的服务 C 版本。
通过使集成测试能够在合并之前运行,它显著减少了测试所需的时间和精力。这种方法消除了复制环境的需要,从而节省了大量成本。有关更多详细信息,请访问 Signadot。