持续集成之“测试三角形与分段构建策略原则”

发表于:2014-05-07来源:博客园作者:乔梁点击数: 标签:
在《戏说Checkin Dance》一文中,咱们说到:Joe的团队实施了带有令牌的持续集成提交流程纪律。由于每个人都做本地构建进行验证后再提交,所以持续集成平台上的构建结果比较稳定,每天持续集成服务器上的构建最多只有一两次失败(常见的原因是忘记提交某个文件而导致失败,和因本地环境配置与平台环境配置不一致而导致失败),但一般都能在30分钟内修复。随着项目的进 行,新功能不断地增加,自动化测试用例也越积越多。由于不做任何修改,本地

  在《戏说Checkin Dance》一文中,咱们说到:Joe的团队实施了带有令牌的持续集成提交流程纪律。由于每个人都做本地构建进行验证后再提交,所以持续集成平台上的构建结果比较稳定,每天持续集成服务器上的构建最多只有一两次失败(常见的原因是忘记提交某个文件而导致失败,和因本地环境配置与平台环境配置不一致而导致失败),但一般都能在30分钟内修复。随着项目的进 行,新功能不断地增加,自动化测试用例也越积越多。由于不做任何修改,本地构建脚本就会运行所有自动化测试用例,所以本地构建的运行时间也越来越长。团队里有人开始抱怨,“每次提交代码前,运行本地构建都超过15分钟,这样太浪费时间。我们可否把那些不太重要的测试拿出去,不再运行了?”

  一、自动化测试黄金三角形

  作为团队的技术负责人,Joe把大家叫到一起,就这个问题进行了专门的讨论。

  “我们不能放弃运行这些测试。”Alice说道,“在我前一个项目中,我们就是这么做的,结果,这些花精力写的测试都作废了。”

  “那是为什么呢?”?Bob问道。

  Alice回答道:“因为并不经常运行这些测试,随着功能的修改,有些测试的逻辑就不再是正确的了。而当再次运行发现这类问题时,通常的结果就是把这个测试删掉,因为修复这个测试的工作量太大了。”

  “那持续运行所有测试的话,等待的时间太长了,也是一种浪费呀。”Bob说道。

  此时,作为团队技术负责人的Joe说话了。“让我们先分析一下,到底有哪些什么原因让我们的测试在这么短的时间里就变成需要这么长时间了呢?”

  “功能增加的多了,测试自然就多了呗。”

  “功能增加了,自动化测试数据的准备工作也多了,需要的时间当然就长了。”

  “现在我们的测试中有很多地方需要测试在原地等待结果返回,所以等待时间也挺长的。”

  “大家还有没有其它原因?”Joe追问道。

  大家沉默了一会儿,Bob说道:“好象主要就这些原因吧”。

  “那好吧。功能多而导致测试多这是好事儿,说明我们大家都非常重视我们的自动化测试。对于‘测试准备时间变长’这个问题可以理解,因为我们的产品越来越复杂了。对于‘结果返回的等待问题‘嘛,需要具体问题,具体分析。前几天,我看到一个‘测试黄金三角形’,讲的就是自动化测试中各类测试的应具有的比例关系,对我很有启发。我在白板上画一下吧。”于是,Joe走到白板前,将这个测试黄金三角形画了下来,如图1所示。

  然后,Joe将这个图形解释了一下。原来,这个三角形讲的就是单元测试、集成测试和验收测试的关系。首先,左边向上的箭头表示,越高层次的测试维护成本越高,运行时间越长。因此,对于单个测试来说,单元测试运行最快,维护最容易,而集成测试次之,验收测试则最高。每类测试的面积代表着该测试的数量。现在,业界有很多种工具支持单元测试,因此它的编写及维护成本相对其它两种测试来说较低,应使用单元测试对代码做尽可能多的测试覆盖。一般来说,单元测试覆盖率达到70~80%是比较理想的状态。

  接着,Joe问了大家一个问题:“我们产品中的这些自动化测试属于哪一类测试?”

  Alice说道:“那要看你怎么定义单元测试中的这个单元。”

  “根据WikiPedia上的定义,一个单元是指应用程序中最小可测试的部分。既然我们使用面向对象的开发语言C++,那么单元测试的粒度应该是类中的一个方法吧。而且,通常来说,如果一个测试包括以下任何一个情形,它就不是一个单元测试:(1) 需要连接数据库;(2) 需要网络通信;(3) 需要与文件系统打交道;(4) 不能和其它单元测试同时运行;(5) 需要对环境进行一些配置(如编辑配置文件)才能运行它。”Joe回答道。

  “要是这么说的话,我们的测试中,一部分是模块集成测试,一部分是验收测试,只有一小部分算是单元测试。我们的测试集合正好是一个倒三角。”Bob边说,边在白板上画了出来,如图2所示。

  “既然高层次上的测试(集成测试和验收测试)维护量比较大,今后我们应该加入更多的低层次测试(单元测试),对于关键功能进行集成测试和验收测试。如果对于测试用例具有等价性的话,我们应该用低层次测试来实现。这样我们就会达到自动化测试的黄金三角状态啦。”Joe边说边在白板上笔划着,如图3 所示。

  “我同意你说法,但是仍旧没有解决我们目前遇到的问题。如何解决我们现在本地构建时间太长的问题呢?”Alice有点儿不耐烦地问道。

  二、分阶段构建?

  “这还不容易,Martin Folwer(敏捷宣言的创造者之一)已经给出了一个解决方案,那就是两阶段构建(Secondary Build)。也就是说,我们可以把那些运行比较慢,时间比较长且基本上不会失败的自动化测试用例挑选出来,组成一个新的测试集,在第二阶段运行,可以叫做‘二级构建阶段’。剩余的测试集仍旧放在第一个阶段运行,我们可以把第一个阶段叫做‘提交构建阶段’。”Joe回答道。

  “那什么时间运行这两个阶段的构建呢?”Bob问道。

  “提交阶段构建当然就是在我们每个人提交之后就运行啦。而且在我们提交之前,作为本地验证集合,在我们开发环境上也要运行同样的提交构建。一般来说,本地构建和提交构建最好都在五分钟内完成,最长也不要超过十分钟,否则开发人员就不愿意花时间做频繁地代码提交啦。另外,一旦提交阶段构建成功以后,就马上自动触发第二阶段构建。而我们开发人员在持续集成服务器上的提交阶段构建成功以后,就可以继续进行其它的工作啦。”Joe说道,“我们原来的六步提交图就变成这个样子了。”说着,Joe拿起白板笔就画了出来,如图4所示。

原文转自:http://kb.cnblogs.com/page/91338/