# 测试金字塔和持续自动化测试
敏捷和DevOps开发模式下，产品要具备随时可发布的能力，本文介绍如何应用测试金字塔和CI/CD持续自动化测试实现高效的测试反馈，保障随时发布产品的质量。
#### 测试金字塔
自动化测试金字塔最早是由Mike Cohn在2009年的著作《Succeeding with Agile: Software Development using Scrum 》（《Scrum敏捷软件开发》）中提出。最早提出来的时候是一个三层的金字塔，从上到下分别是UI界面/Service服务/Unit单元测试，随着敏捷测试的不断推进，测试金字塔出现一些变种。实际使用中不用太拘泥于每层的名字，在服务化软件架构中Service层也可以理解为API测试。
这种下宽上窄的三角形结构，代表在各层自动化的建议投入分配比例，越接近底层的单元测试建议的投入最多，接口测试居中，界面层建议的投入最少。
Martin Fowler关于测试金字塔有这样一段评论："GUI测试用例还很脆弱，如对系统的一些修正可能导致很多用例的失败，这时候你需要重新录制。你可以放弃录制的方法来解决这个问题，通过写GUI测试代码，但是这样效率非常低。就算你已经很精通了GUI测试代码的编写，端到端的GUI测试用例也很容易出现不可预期结果的问题，因此，基于GUI的自动化测试是脆弱、耗时（包括用例维护和执行）的。所以测试金字塔要表达的是：底层应当有更多的单元测试和接口测试和逻辑测试，GUI测试用例能覆盖到主业务流程即可。"
**测试金字塔中每层中涉及的测试技术均有自己的优势和局限性，由于上层GUI测试的脆弱（不稳定性）、耗时（执行效率）问题，以及问题表现位置（UI）和问题根因位置（代码）距离太远的问题，测试金字塔由关注测试数量转向关注测试质量，推荐增加底层的测试投入。**
- 层次越靠上，运行效率越低，延缓持续集成的构建-反馈循环。
- 层次越靠上，开发复杂度越高，如果团队能力受限，交付进度受影响。
- 端到端测试更容易遇到测试结果的不确定性。
- 层次越靠下，单元隔离性越强，定位分析问题越容易。
原则上单元测试需要开发人员承担，很多团队中开发人手不足，优先保障功能的实现，在单元测试的投入不够，并且很多开发人员的单元测试经验不足，导致很多团队中不做单元测试或者被动执行流于形式，有人提出了金字塔结构的反模式：**蛋筒冰激凌模式** 和**纸杯蛋糕模式**。
蛋筒冰激凌模式由Alister Scott在2012年提出，金字塔中界面测试和单元测试的比例倒置形成倒金字塔，界面测试之上有大量的手工测试。反模式不是建议模式，但却是实际团队中大量存在的。团队初期没有自动化测试，完全依赖手工测试，然后从功能测试自动化入手，产生了一些界面自动化测试用例。这种由外向内进行自动化测试的建设方式，导致了这样的反模式。这样的模式在测试效率、测试用例可维护性角度讲，均存在一些问题，但又往往是很多团队自发进行测试自动化能力建设过程中的必经路径，问题积累到一定阶段需要逐步向测试金字塔方向演进。
#### 持续自动化测试
持续自动化测试是在持续集成和持续部署过程中运行自动化测试，快速反馈失败，最早源自开发人员在开发环境中通过单元测试获取快速反馈的思想。持续自动化测试是随着CI/CD（持续集成和持续部署）发展而逐步成熟的。现实需要开发人员能够越来越快的发布产品变更，修复在线问题。如果仍然依赖原来的手工测试或者开发和测试完全分离的方式，难以保障在很短的时间窗口中完成测试质量保障活动，因此需要在CI/CD过程中嵌入自动化测试"持续"保障交付物的质量。
持续测试意味着测试活动纳入到持续集成、持续反馈、持续改进循环中，持续不断的测试，贯穿了整个软件交付周期。持续测试提倡尽早测试、频繁测试和自动化测试。
"持续"体现在贯穿了敏捷、DevOps流程中交付物由小粒度逐步演变为软件成品的全过程，从代码白盒测试，到组件模块测试、接口测试、E2E（端到端）功能测试，甚至交付之后进行生产环境的在线测试。每个阶段正好映射了测试金字塔由下向上的各层，越下层的测试在越早的阶段执行，越上层的测试在越后的阶段执行。这类似于汽车制造流水线的各个环节，每个环节的组装结束后都会进行必要的检查通过才进入到下一个环节，在软件DevOps开发过程中Pipeline流水线承载了这样的组装、检查测试过程。
- 测试左移、测试右移 二者强调在持续测试过程中测试活动越过了传统测试的时间、角色、部门限制，将测试活动发展为连贯的持续性的质量保障活动。
  测试左移强调测试活动尽早开展，测试人员更早地参与到软件项目前期的各项活动中，在功能开发之前定义好相关的测试用例，提前发现质量问题，开发人员参与到测试。
  测试右移强调在生产环境中测试监控，并且实时获取用户反馈，持续改进产品的用户体验满意度，提高产品质量。
  
  
- 测试自动化 持续测试要实现快速流动和快速反馈，需要使用自动化的手段来提高效率，于是自动化单元测试、接口测试、E2E测试就应用嵌入到了DevOps流水线中。自动化测试提高了测试反馈效率，也降低了人为因素导致的错误。测试自动化不仅仅要完成测试用例脚本执行的自动化，还要实现其它所有可以减少人力投入的活动，例如自动化环境创建，自动化部署，自动化监控，自动化数据分析等。
  
  
 
