<audio id="audio" title="08 | 测试环境要多少？从现实需求说起" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/2b/f5/2baa4e34f51bd22150440461868cb7f5.mp3"></audio>

在整个持续交付生命周期中，测试环境的易用程度会直接影响软件的交付速度，但因为以下两点，它又是最被容易忽略的一环。

<li>
我们总是把环境理想化，忽略了其管理的难度；
</li>
<li>
我们也很少设立专职的环境管理员，导致环境长期处于混乱状态。
</li>

通常，我们在项目初期并不会关注测试环境的问题，然而在回顾时却发现在环境问题上浪费的时间非常惊人：硬件资源申请困难，测试环境配置繁琐，测试应用更新困难，基础设施稳定性差，服务调用异常，多项目并行造成互相干扰等等问题。

而不管你是开发人员还是测试人员，相信你都或多或少地碰到过这些问题。

在接下来的《环境管理》系列文章中，我会和你聊聊构建一整套好的测试环境的关键点以及具体实施方案。今天，我就先跟你说说和测试环境相关的两个问题：

<li>
测试环境的结构一般是怎样的？
</li>
<li>
什么才是好的测试环境？
</li>

## 互联网公司测试环境的结构

当公司规模较小时，测试环境的维护相对容易。开发和测试共用一套数据库缓存等基础设施，因为应用数量不多，开发环境可以是单机的，无论是手动或半自动化的更新测试环境的应用，花费的时间都还在可接受范围内。

这时，公司环境的结构很简单，分为开发环境，测试环境，生产环境即可。

但实际上，我看到的大多数公司的研发过程及配套环境并没有这么简单，一般都会存在5套以上的大环境以及更多的子环境，每个环境的机器数量可能有数十台甚至更多。

那么为什么会需要这么多套环境呢？我把主要原因概括为了以下两个方面。

<li>
纵向上看，人员的增多提高了项目的并行度，如果这时还使用一套环境的话，就会发生以下问题：
<ul>
1. 开发同学在debug一个困难问题时，发现下游的应用突然就不可用了；
<li>测试同学在跑了10多分钟测试脚本后，发现应用已经被开发更新掉了。<br />
这样的体验是让人崩溃的。</li>
</ul>
</li>
<li>
横向上看，公司的应用架构逐渐转为微服务化，完整的应用数量很容易就达到了几百甚至几千个的量级，建立一套独立而完整的环境变得越来越复杂，往往是研发团队想要构建一套新的环境却构建不出来。
</li>

所以，目前互联网公司常见的环境模型一般分为开发环境，功能测试环境，验收测试环境，预发布环境，生产环境这五个大套环境。

**第一，开发环境**

微服务架构下，单机已经无法完整地运行业务应用，这就需要开发环境内包含一套完整的业务应用依赖以及相关的基础设施，以保证业务开发同学能在本地完成开发测试。

**第二，功能测试环境**

在开发环境下，每个下游依赖应用都只有一个可用的stable版本。而在实际的开发过程中，由于项目的并行开发，往往会同时存在多个可依赖的版本。而每个项目组的同学在测试时，都希望测试过程中的关键依赖应用是可以被独占的，版本是固定的，不会被其他项目组干扰。

所以，一套独立的功能测试环境就很有必要了。通常，互联网企业会通过中间件的方式分割出一块隔离区域，在功能测试环境中创建多个子环境来解决这个问题。

**第三，验收测试环境**

验收测试环境和功能测试环境是完全隔离的。当功能测试通过后，你可以在验收测试环境进行最终的验收。

它除了可以用作测试之外，还可以用作产品展示。所以，除了测试和开发人员，产品经理也是验收测试环境的主要使用者。

**第四，预发布环境**

到了预发布阶段，应用已经进入了生产网络，和真实的生产应用共享同一套数据库等基础设施。预发布是正式发布前的最后一次测试，在这个环境中往往可以发现线下环境中发现不了的Bug。这个环境的运维标准等同于生产环境，一般不允许开发人员直接登录机器。

根据不同的业务需求和部署策略，不同公司对预发布环境的实现也有所不同：

- 一种比较常见的方式是，将金丝雀发布作为预发布，从接入真实流量的集群中挑选一台或一小组机器先进行版本更新，通过手工测试以及自动化测试和监控系统验证，降低新版本发布的风险。
- 另一种做法是，独立出一组始终不接入真实流量的机器，调用在预发布环境中形成闭环。

相对于第一种方式，第二种方式对生产环境的影响更小，但需要额外的资源和维护成本。

**第五，生产环境**

生产环境是用户真实使用的环境，对安全性和稳定性的要求最高。

## 什么是好的测试环境？

在和你分享什么是好的测试环境前，建议你先思考一下开发环境、功能测试环境、验收测试环境、预发布环境这四种测试环境形成的原因是什么，这样有利于你更好的理解好的测试环境的含义。

首先，搭建测试环境的目的是保证最终交付的软件质量，但每套测试环境的用户并不完全一样：

<li>
开发环境的用户是开发同学；
</li>
<li>
功能测试环境的主要用户是测试同学；
</li>
<li>
验收测试环境的用户是产品经理和测试同学；
</li>
<li>
预发布环境的使用者是测试同学，但收益者却是运维同学。
</li>

而每种角色对于产品研发流程中的需求也是不同的：

<li>
开发同学关注研发效率；
</li>
<li>
测试同学关注测试的可靠性；
</li>
<li>
产品经理更关注的是真实的用户体验和产品的完整性；
</li>
<li>
预发布环境的需求其实来自于运维同学，他们需要保证生产环境的稳定性，减少生产环境的变更，所以需要将预发布环境与线下环境完全隔离。
</li>

如果你是一位测试环境治理工程师，在规划测试环境以及开发和实施工具的时候，最关键的就是要考虑到不同环境的主要用户是谁，环境要做成什么样才能满足用户在研发流程中的需求。当用户不用发愁环境问题时，研发效率也就自然而然地上去了。

当然，不论一套环境用户是测试同学还是开发同学，以下几个需求都是必须被做到的。

<li>
可得性，即在开发一个新项目时，能快速获取构建一个环境需要的机器，基础设施。最好的情况是，能随时可得，随时归还。
</li>
<li>
快速部署，即在搭建新环境时，能以最快的速度构建出一整套完整的环境。测试环境的部署很频繁，在代码提交后，能在很短的时间内构建代码，在环境上更新，就能更早开始测试。
</li>
<li>
独立性，即一个环境在使用过程中，可以不受其他项目测试人员的干扰。
</li>
<li>
稳定性，即不会因为下游服务，基础设施的异常，造成测试中断、等待。
</li>
<li>
高仿真，主要分为两个方面：“测试数据真实”，即能在测试环境构建出真实的测试用例；“环境真实”，即基础服务的架构和行为与线上环境保持一致，避免因为环境不一致造成测试结果不一致。
</li>

但是，毕竟各个环境的用户和使用场景不同，它们的需求也是有差别的。 比如，相对于开发环境，验收测试环境对测试数据的仿真性要求会更高，而开发环境的灵活性，决定了不会过于严格的维护测试数据的真实性。

所以，如何评价一个好的测试环境，就是看它是否最终满足了核心使用者的需求。

## 总结

通常，互联网公司的环境会包括：开发环境、功能测试环境、验收测试环境、预发布环境和生产环境这5套。

测试环境的目的是要保证最终将交付的软件产品的质量，所以好用的测试环境，不能从规模、性能和作用的角度来评判，而应该是从它能否满足用户需求去保证软件质量的角度进行定义，于是得出：

> 
当一个环境可以满足其真正核心用户的需求时, 就是一个好用的测试环境。


除此之外，你还需要理解，环境是昂贵的，不仅涉及单一的机器资源成本，环境副本数的增加也意味着更难管理，更复杂的流程，所以仅仅考虑单套使用者的体验是不够的。

那么，在我的下一篇文章中，将会分享多环境带来的成本问题，以及如何在成本、效率、可管理之间权衡取舍。

## 思考题

<li>
请你思考一下测试环境中最让你痛苦的一点是什么？
</li>
<li>
如果让你来优化测试环境, 你会如何去改善这最让你痛苦的一点？
</li>

欢迎你给我留言。


