最近一家公司告诉我,他们管理着18个独立的开发和测试环境。如果不是我最近与另一个拥有29个环境的公司也交谈过,这将会使我更加惊讶。后者在开发/测试环境上的花费比生产环境的成本还多。这些数字可能看起来很惊人,但我已经见过并听说过许多类似的情况。
任何熟悉其工作原理的人都知道,在这么多环境中创建、更新、维护和管理数据是成本高昂且耗费人力的。每个环境每月都会给云账单增加数千美元的费用,同时维护这些环境正常运行可能需要一个专门的运维团队投入全职精力。
软件工程组织为何会出现这种情况?
根本原因: 过度依赖端到端测试
根本原因(或者至少是一个根本原因)是这些组织在QA过程中严重或完全依赖端到端测试。在端到端测试中,测试运行的环境通常是在一个生产环境缩小版副本的环境中进行的,其中每个服务或组件都是真实事物的副本。当我们依赖服务B和C的功能测试服务A时,它将调用这些服务的真实运行副本。反过来,这些可能又会调用服务D和E等等。这种“扇出”效应通常意味着每个服务都必须可用,以便进行全面测试。
当大型组织中有许多工作流同时进行时,这种情况下,在多个团队共享环境中进行端到端测试,如果超出一定的规模,就会变得难以维持,原因如下:
- 每个团队所需的版本组合不同。
- 部署不稳定的软件,破坏使用环境稳定性。
- 不同的团队有相互冲突的数据需求。
- 一个团队的状态改变会导致另一个团队的状态无效。
- 在进行负载或可靠性测试期间需要独占访问环境。
这些问题导致的一个后果是,许多团队(或者具有类似需求的分组)将要求为他们创建一个专用的环境,该环境由他们指定的特定软件版本、他们自己的测试数据和软件版本、他们自己的测试数据,并且没有来自其他团队的稳定性部署组成。
但是,尽管许多公司可以坦诚地讨论何时真正需要端到端测试以及所涉及权衡中的获益,但这也只是一个具有更深层次问题的表象——这个问题触及当今开发组织进行测试的核心方式。
根本原因 —— 对测试的理念
如果我们进一步深入挖掘,许多组织尽管知道端到端(e2e)测试方法成本高昂且难度大却仍然选择它的原因是,一种普遍存在的观念:“对于完整的真实系统之外的任何对象进行的测试都是不可信的”。
这种信念在世界上一些最成功的软件工程组织中被反复证明是错误的,但要说明为什么是这种情况以及替代方案可能是什么样的,则需要进行一些剖析。
在此语境下,测试本质上是从最终用户的角度对系统的所有功能进行操作并确认其正确执行的行为,虽然这在表面上看起来是合理的,但在实际操作中,这意味着我们将所有类型的质量风险管控都集中到了一个单一活动中。
如何避免测试环境无序扩张
当然,我写这篇文章是因为我相信有更好的方法。如果你不想在最后面对15个、20个或30个测试环境以及随之而来的所有的令人头疼的问题,下面是我的建议。简而言之,在很多情况下,你可以使用更有针对性的、更独立的测试来替代端到端测试。让我们来谈谈如何识别这些场景。在执行单个测试用例时,我们要检查:
- 每个协同服务是否对其他服务进行了正确的API调用。
- 每个服务的API是否接受了格式正确的请求并返回格式正确的响应。
- 几个单独的服务在功能上是否正确的。
- 基础设施和网络是否配置正确,以便服务能够相互通信。
在这些风险中,只有最后一项需要一个完全集成的环境才能发现。每一种类型的风险都可以通过有针对性的、独立的测试来应对——进行契约测试以确保客户端和服务器API的使用正确,针对mock对象对单个服务进行功能测试以确保正确的行为。
成熟、高性能的工程组织通常会在管道中针对每个代码或配置变更运行这些独立测试,只有在这些测试通过后才能部署到完全集成的环境中。在完全集成的环境中,只运行最小的端到端测试集,专门针对那些只有在整个系统中才能检测到的风险类型。通过这种方式,端到端环境的需求量会大大减少,因为大多数测试将在占用资源极少的环境(这些环境可能只在测试运行时存在)中进行。这将大幅度降低基础设施成本和运营工作量。
这种方法还有其他好处。过度依赖端到端测试的一个常见负面影响是,它往往会促使形成庞大、高风险、高工作量的版本发布 ——“我们已经一起测试了这些服务版本,所以我们现在必须一起发布它们”。独立的契约测试和针对模拟的功能测试可用于确保服务版本之间的向前和向后兼容性,这意味着单个服务可以非常有把握地进行发布。这将会带来更高的新功能产出量、更短的交付周期和更少的系统停机时间等好处。
采用更细致的测试方法的组织,在可能的情况下使用独立测试并将端到端测试用于特定风险,能够避免环境无序扩张带来的麻烦,并更高效地交付软件——同时还能将其环境数量控制在更易于管理的水平。