为什么演练测试不适用于微服务测试

2024-08-20 14:02:48 浏览数 (3)

解决演练环境问题的斗争一直是开发团队面临的持续挑战,安全共享可以解决这个问题。

译自 Why Staging Doesn't Scale for Microservice Testing,作者 Arjun Iyer。

想象一下:你是一家中等规模工程团队的开发人员。你刚刚完成了一个很棒的新功能的编码。你很兴奋地将其部署到演练环境进行测试。但是等等...这是什么?演练环境又坏了。

听起来熟悉吗?如果你沮丧地点头,你并不孤单。与演练环境的永恒斗争,是软件开发史上的一个古老故事。

演练环境的高风险

在我们深入探讨细节之前,让我们先解决一个关键问题:为什么你应该关心演练环境?答案很简单:它们是你代码和生产环境之间的最后一道防线。在当今的微服务架构和持续交付的世界中,稳定演练环境的重要性不可言喻。

请考虑以下情况:根据2021 年 DevOps 状态报告,高绩效 IT 组织部署代码的频率是低绩效组织的 973 倍。这意味着每天都有大量的代码变更进入演练环境。如果这些环境不稳定或不可靠,就像在流沙上建造房屋一样——灾难不可避免。

演练环境故障的影响是深远的:

  • 发布延迟: 当演练环境不稳定时,你精心制定的发布计划就会泡汤。突然之间,你承诺下周发布的功能看起来更像是下个月了。
  • 开发人员生产力: 没有什么比等待演练环境可用或稳定更能扼杀生产力的了。这就像当你已经迟到了一个重要会议时,却困在了交通堵塞中。
  • 质量保证噩梦: 如果演练环境不可靠,你怎么能相信你的测试是有效的?这就像在有人不断更改文字的情况下,试图校对一本书。
  • 生产风险增加: 当演练环境无法捕获错误时,这些错误就会进入生产环境。我们都知道,在生产环境中修复错误就像给正在参加马拉松比赛的病人做手术一样。

演练环境的“两难境地”

现在,让我们来解决问题的核心。为什么演练环境难以保持稳定?我们正在处理一个经典的“两难境地”:

  • 开发人员需要一个稳定的演练环境来测试他们的代码变更。
  • 将代码变更部署到测试环境的行为可能会使环境对其他人来说变得不稳定。

欢迎来到演练环境的世界!

当前的解决方案(或者应该说是创可贴?)

多年来,工程团队想出了各种解决此问题的变通方法。让我们看看其中一些“解决方案”及其优缺点。

1. Slack 锁定

一些团队使用 Slack 来“锁定”演练环境进行测试。过程如下:

开发人员 A:“锁定演练环境一个小时。不要碰!” 开发人员 B:“但我需要测试我的关键错误修复!” 开发人员 A:“太可惜了,我比你先到!”

虽然这可能适用于一个由三个开发人员和一只宠物仓鼠组成的团队,但它无法扩展到更大的团队。这就像在一个整个办公大楼只有一个浴室的情况下——混乱是不可避免的。

2. 功能标志泛滥

其他团队转向功能标志,认为他们找到了演练环境管理的圣杯。其理念是在演练环境中禁用新代码,直到它准备好进行测试。

但问题是:你最终仍然需要启用该标志,猜猜怎么了?你又回到了起点,为一个稳定的环境而战,以测试你现已启用的功能。

3. 环境激增

一些组织决定创建多个“较低”环境。理论上,开发人员可以在这些环境中进行初始测试,然后再移至“正式”演练环境。听起来不错,对吧?

错了。这种方法就像用修建更多高速公路来解决交通拥堵一样。当然,它可能在最初有所帮助,但很快,你就会在更大范围内处理相同的问题。

这种方法的缺点是显而易见的。较低环境通常缺乏与第三方服务的完全集成,而是依赖于无法真正代表生产行为的模拟。跨多个环境协调更新会变成一个后勤噩梦,引入不一致和错误。资源消耗很大,包括基础设施成本和持续维护。

也许最阴险的是,这些较低环境可能会造成一种虚假的安全感。它们可能无法揭示在完整演练环境或生产环境中会出现的错误,从而导致后续出现令人不快的意外。随着你的微服务架构的增长,维护这些多个环境的复杂性也会随之增加。

讽刺的是,在试图解决演练环境问题时,我们却创造了一系列新的问题。这就像典型的治标不治本。我们需要的不是更多环境,而是更智能地利用现有环境。

4. 模拟的疯狂

另一种解决演练环境问题的方法是在代码合并之前使用模拟进行集成测试。这种方法有其优点,但也存在重大挑战。

从积极方面来看,模拟可以提供一种快速轻便的方式来模拟依赖关系,使开发人员能够独立测试他们的代码。这可以加快开发过程,并及早发现基本的集成问题。对于简单的系统或定义明确的接口,模拟可以成为测试库中的有效工具。

然而,随着系统复杂性的增加,模拟的局限性变得更加明显。维护服务依赖关系的准确模拟需要付出巨大的努力,尤其是在快速发展的微服务环境中。随着服务的改变,模拟也需要相应地更新,这可能成为一项耗时的任务。

此外,虽然模拟可以发现某些类型的问题,但它们可能会错过仅在真实集成环境中才会发生的细微交互。这会导致一种错误的安全感,即代码通过所有基于模拟的测试,但在实际集成场景中失败。

维护全面且最新的模拟所需的努力通常会随着系统复杂性的增加而呈指数级增长。在某个时刻,在创建和更新模拟上投入的时间可能会超过它们带来的益处,尤其是在与在更现实的环境中进行测试相比时。

隧道尽头的光明

那么,我们注定要生活在一个演练环境永远无法修复的世界吗?正如我们所见,传统的演练环境方法充满了挑战。为了克服这些挑战,我们需要换个思路。

这让我们想到了一个很有前景的新方法:在共享环境中进行金丝雀式测试。这种方法允许开发人员在共享的演练环境中独立测试他们的更改。它的工作原理是创建受开发人员更改影响的服务的“影子”部署,同时保持环境的其余部分不变。这种方法类似于生产环境中的金丝雀部署,但应用于演练环境。

主要优势在于开发人员可以共享环境而不会影响彼此的工作。当开发人员想要测试更改时,系统会创建一个通过环境的唯一路径,其中包含他们修改的服务,同时使用所有其他服务的现有版本。

此外,这种方法能够以每次代码更改或拉取请求的粒度进行测试。这意味着开发人员可以在开发过程的早期阶段发现问题,通常是在代码合并到主分支之前。通过在这个阶段识别问题,团队可以显著降低将错误引入共享代码库的可能性。

这种方法提供了彻底测试所需的隔离,而无需管理多个完整环境的开销。它允许团队在类似生产的环境中进行彻底的测试,及早发现问题,并同时维护一个稳定的共享环境。

正如著名的软件工程师和教育家Kent C. Dodds所写:

你的测试越接近你的软件的使用方式,它们就能给你带来越多的信心。 — Kent C. Dodds

1 人点赞