原文作者:Mike Wacker
原文地址:http://googletesting.blogspot.com/2015/04/just-say-no-to-more-end-to-end-tests.html
译者:chenhengjie123

在你生命中的某些时刻,你想起一部电影,你和你朋友都想看,但你和你的朋友都后悔看了这部电影。或者你还记得当你的团队以为他们发现了他们产品的下一个 “杀手级功能”,但上线后却是功能炸弹。

好的想法通常会在实践中失败,而在测试领域,一个听起来相当不错但实践中经常失败的概念是建立围绕端到端测试的测试策略。

测试人员可以投入他们的时间来编写任何类型的自动化测试,包括单元测试、集成测试以及端到端测试。但这个策略把大部分时间投入到端到端测试中以整体验证产品或服务。通常情况下,这些测试会模拟真实用户使用场景。

端到端测试理论

当你觉得依赖端到端测试是一个坏主意时,肯定会有人通过这个主意在理论上的合理性和存在意义来说服你。(译者注:原文是 While relying primarily on end-to-end tests is a bad idea, one could certainly convince a reasonable person that the idea makes sense in theory. 实在不知道怎么翻比较合适,麻烦大伙给下意见,我后面更正)

在开始之前,我们先来看一下 Google 的 ten things we know to be true(十件我们知道正确的事)中的第一条:“关注用户,剩下的一切都随之而来(Focus on the user and all else will follow)”。根据这条准则,关注真实用户场景的端到端测试听起来是一个很好的主意。另外,这种策略在许多地方都呈现出:

实践中的端到端测试

既然这个测试策略在理论上听起来这么赞,那么它在实践中哪里出问题了?作为示范,我基于自己收集到的我和其他测试人员的共同经历来讲述下面这个故事。在故事中,一个团队正在建立一个在线文档编辑服务(比如: Google Docs)

我们假设这个团队已经有比较不错的测试基础设施。在每个晚上:

  1. 最新版本的服务会被构建

  2. 这个版本会被部署在团队的测试环境

  3. 所有端到端测试都会在这个测试环境中进行

  4. 一个包含了测试结果的测试报告会通过电子邮件形式发给整个团队

最后期限在我们团队不断为下一个版本编写新功能的过程中很快来到。为了保证产品处于高质量水准,他们要求在功能被认定为完成前,端到端测试用例通过率至少达到 90% 。现在,离最后期限只有一天了:

剩下的天数 通过率 备注
1 5% 所有东西都有问题!登录到服务的功能有问题。几乎所有测试都需要用户登录,所以几乎所有用例都失败了
0 4% 一个和我们服务有依赖关系的搭档团队昨天在它们的测试环境上部署了一个无法运行的版本
-1 54% 一个开发在昨天(也许是再前一天)搞坏了保存功能。几乎一半的用例在需要保存文档。开发花了差不多一天的时间来确定这到底是一个前端的 bug 还是后端的 bug 。
-2 54% 确定了昨天那个保存问题是前端的 bug ,开发花了半天时间来查找具体哪里出问题。
-3 54% 一个很烂的 fix 在昨天被提交了。这个错误仍然被触发到,然后一个正确的 fix 终于在今天提交了。
-4 1% 我们测试环境使用的实验室出现了硬件故障
-5 84% 很多大 bug(如无法登录,无法保存)背后的小 bug 被发现了。团队还在修复小 bug 中。
-6 87% 我们应该能达到 90% 以上,但由于某些原因,还没达到
-7 89.54% (达到 90% 左右了,已经可以接受了)昨天没有任何 fix 被提交,所以昨天的测试达不到 90% 肯定是由于碎片造成的。

分析

抛开各种问题,这个测试最终还是找到了真正的 bug 。

好的地方

不好的地方

那么我们现在知道了端到端测试策略在实践中做得不好的地方了,我们需要改变我们的测试来避免这些问题。那么应该怎么做?

测试真正的价值

通常情况下,一个测试人员在找到一个失败的用例时,他的工作已经完成了。登记完 bug 后,接下来的修复工作就交给开发了。然而,为了确定端到端测试策略行不通的原因,我们需要跳出这个场景,并结合前面提到的第一条准则来思考。如果我们 “关注用户(剩下的一切都随之而来)”,我们必须自问一下:一个测试用例的失败到底能为用户带来多大的利益。下面是答案:

一个失败的用例并不能直接给用户带来利益

虽然这个结论看起来会让人很惊讶,但这是事实。如果一个产品能用,那么无论测试结果说明说它能否能用,它都是能用的。如果一个产品用不了,那么无论测试结果说明说它用不用得了,它都用不了。所以,一个失败的测试用例并不能直接给用户带来利益。那么什么能给用户带来利益呢?

一个 bug fix 直接给用户带来利益

用户只会对不正确的行为 —— bug —— 消失时感到高兴。显然,为了修复一个 bug ,你必须知道它的存在。为了知道 bug 的存在,理想地你会有执行内部测试来发现 bug(因为如果测试没找到 bug ,那么用户就会找到)。但在整个过程中,从一个失败的测试里面找 bug 来修复,它的价值只会在最后一步体现出来。

阶段 测试用例失败 开 bug 修复 bug
是否产生价值 No No Yes

因此,在评估一个测试策略的价值时,你不能只看它如何找到 bug ,你还需要评估它怎么让开发去 fix(甚至避免产生)这些 bug 。

建立良好的反馈闭环

测试需要建立起一个反馈闭环,通知开发人员这个产品是否能用。理想的反馈闭环有下面这些特征:

从小处着手

那么我们可以造出这个理想的反馈闭环吗?可以的,但要从小处着手。

单元测试

单元测试只取产品中的一小部分并在隔离环境下对它进行测试。它们更合适用于建立这个理想的反馈闭环:

编写有效的单元测试需要依赖管理、moking、以及隔离测试领域的技术。我不会在这里详细讲述这些技术,但作为一个引子,一个通用的适用于新的 Google 员工(或者非 Google 员工)的例子是 Google 如何构建测试一个秒表程序。

单元测试 vs. 端到端测试

使用端到端测试,你需要等待:首先构建整个产品,然后把它部署到环境中,最后才是执行测试。当测试执行时,不稳定的测试将由于碎片存在而一直存在。而且即使这次测试找到了一个 bug ,这个产生 bug 的代码也有可能存在于产品的任何一个地方。

虽然端到端在模拟真实用户场景这方面做得更好,这个优势很快就会被端到端反馈闭环的劣势盖掉:

单元测试 端到端测试
高速度
高可靠性
故障隔离
模拟真实用户场景

集成测试

单元测试有一个主要劣势:即使这些单元在隔离状态下运行的很好,你不知道他们集合到一起后是否也能运行地很好。但即使这样,你也不需要端到端测试。为了确认他们集合后的运行情况,你可以使用集成测试。一个集成测试需要数个的单元 —— 大部分情况下是 2 个 —— 然后在整体上测试他们的行为,验证他们是否能连贯地工作。

如果两个单元没有被正确地集成起来,为啥你要在抛弃够编写更小、更专注的集成测试而去编写端到端测试来查找 bug ?当你需要从更大范围进行测试时,你只需要把范围扩大一点点来验证各个单元集成后能正常工作。

测试金字塔

即使有了单元测试和集成测试,你还需要有少量的端到端测试来整体验证这个系统。为了找到这三种测试类型的平衡,最直观的方式就是测试金字塔。这里是一个精简的、来自 2014 Google Test Automation Conference测试金字塔

大量的测试都是在金字塔底部的单元测试。越往上看,你的测试范围将越来越大,但同时测试的数量(金字塔的宽度)越来越少。

作为一个开拓者(译者注:原文是 good first guess ,没找到很好的翻译,就用开拓者来代替吧), Google 建议采用 70/20/10 的划分方式:70% 单元测试,20% 集成测试,10% 端到端测试。实际比例会根据各个团队的情况有所不同,但总体上,它应该保持这个金字塔的形状。尝试避免以下的反模式:

就像真实世界中金字塔是最为稳定的结构,测试金字塔也应该是最稳定的测试策略。


↙↙↙阅读原文可查看相关链接,并与作者交流