写点什么

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

  • 2011-02-17
  • 本文字数:3396 字

    阅读完需:约 11 分钟

随着软件产品新特性的不断增加,软件自动化测试用例的数量也会成倍增长。对于一些历史“悠久”的遗留系统来说,甚至会积累数以万计的自动化测试用例。如果对这样的系统进行持续集成,还要求每个开发人员都要进行本地验证的话,困难的确不小。让我们还是看看 Joe 的团队是如何解决类似问题的吧。

在《戏说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 所示。

“不对,这里有问题!持续集成强调尽早反馈。如果把测试分成两个阶段了,那反馈周期不是加长了 吗?”Bob 反驳道。

Joe 点点头,说道:“你说的没有错。但是,根据我们现有的软硬件资源条件,我们目前还无法通过增加资源的方式来缩短所有测试运行的时间。所以我们必须在质量与速度之前做出平衡。这也是我为什么要把那些不易出错的自动化测试集合放在第二阶段构建的原因,这样可以降低但不能完全解除第二阶段构建失败的风险。所以, 这也要求我们大家当第二阶段构建失败时,也要找人尽快把它解决,并且把相关的测试再次放回提交测试阶段中运行,或者在提交测试阶段加入新的测试来补充。” ?

Alice 此时插话,问道:“既然第二阶段构建不常失败,为什么我们不定时运行它,比如每天晚上运行一次呢?这样不是更节省资源吗?另外,如果第二阶段构建运行得慢,那它不是一直都落后吗?”

“因为每次提交阶段构建成功以后就触发第二阶段构建,这样无论如何都比每天晚上运行一次的更多的反馈。因为每天晚上运行一次的话,如果出了问题,我们只能在第二天早上才能发现。对于你的第二个问题,我画一张图来解释。”Joe 找了一张大白纸,在上面开始画了起来。

一会儿功夫,几个示意图就画好了。看到这几个示意图以后,大家恍然大悟。如图 5 所示。从图中我们可以看到:

  1. 当版本 123 的第二阶段构建被触发并正在运行,Alice 又提交了一次,触发了版本 124 的提交构建;
  2. 当版本 124 的提交构建完成之后,由于版本 123 的第二阶段构建仍在运行,所以不再触发第二阶段构建;
  3. 当版本 125 的提交构建完成时,版本 123 的第二阶段构建仍旧在运行,所以也不触发第二阶段构建;
  4. 当版本 126 提交构建正在运行时,版本 123 的第二阶段构建刚完成,此时由于版本 125 的提交阶段构建是一个最近 成功完成的提交构建,所以持续集成服务器就会启动该版本的第二阶段构建,而忽略版本 124 的提交构建。

“那根据我们持续集成纪律,谁的提交让构建失败,就由谁来修复。如果版本 125 的第二阶段构建失败了,就包括版本 124 和 125 两次提交的变更,由谁来修复呢??”Bob 接着问道。

“这个好办,由这两个提交人一起负责修复。如果想确切找到谁的提交有问题,还可以手动触发版本 124 的第二次构建。假如构建成功,说明版本 125 有问题,假如构建失败,说明问题在版本 124 就引入了。”Alice 抢着说道。

讨论到这里,团队成员都达成了共识,(1) 开始加强单元测试的力度;(2) 在反馈速度和反馈质量之间做出折衷,使用二级构建构建的方式。

整个产品的开发非常顺利,马上就要进行版本发布了。团队还会遇到什么问题呢?他们是如何解决的呢?请听下回分解。?

2011-02-17 02:325220
用户头像

发布了 100 篇内容, 共 21.7 次阅读, 收获喜欢 5 次。

关注

评论

发布
暂无评论
发现更多内容

移动应用平台有哪些优势?能为企业带来什么好处?

WorkPlus

Java开发学习----SpringBoot三种配置文件解析

钟奕礼

编程 Spring Boot java;

安全、可靠、稳定的企业IM,WorkPlus是政企工作的首选

WorkPlus

每日算法刷题Day2-向上取整、三角形条件、字符串拼接匹配、三数排序思路

timerring

算法 刷题 9月月更

每日算法刷题Day7-比较字符串大小,去掉多余的空格,单词替换

timerring

算法 刷题 9月月更

从 0 到 1 上手阿里云服务器 ECS(三)

六月的雨在InfoQ

MySQL RDS ECS 云数据库RDS for MySQL 9月月更

技术分享| anyRTC服务4.3升级

anyRTC开发者

音视频 sdk 视频通话 实时消息 快对讲

MASA Stack 第五期社区例会

MASA技术团队

MASA Framewrok MASA MASA Blazor

每日算法刷题Day4-完全数、分情况输出、平方矩阵、斐波那契数列匹配输出

timerring

刷题 算法题 9月月更

每日算法刷题Day5-平方矩阵II和III、蛇形矩阵图解

timerring

刷题 算法题 9月月更

java技术线下面授培训学习好还是自学好

小谷哥

Java进阶(三十六)深入理解Java的接口和抽象类

No Silver Bullet

Java 接口 抽象类 9月月更

再添重磅理事成员!麒麟软件、浪潮信息、中科曙光、新华三加入龙蜥

OpenAnolis小助手

龙蜥社区 新华三 中科曙光 麒麟软件 浪潮信息

参加java培训学习难不难?

小谷哥

Redis进阶知识点(可学习,可复习,可面试)

钟奕礼

编程 redis 底层原理

极狐GitLab 15.4 | 四大专享更新、更能打的CI/CD,近 50 项更新全面来袭!

极狐GitLab

DevOps 运维 Harbor CI/CD 极狐GitLab

意外!花20天刷完Alibaba JVM笔记去面阿里,却意外拿到京东Offer?

Geek_0c76c3

Java 数据库 开源 程序员 面试

web前端开发技术培训需要学习多久

小谷哥

面试中经常问到的几个问题,快来看看能答对几道吧(Java)

钟奕礼

编程 java;

参加前端培训哪种方式比较靠谱

小谷哥

爱番番企业查询结果优化实践

百度Geek说

大数据 搜索引擎 elasticsearch

Github星标百万!终于有人将Spring技术精髓收录成册

Geek_0c76c3

Java 数据库 开源 程序员 开发

每日算法刷题Day3-起始时间转换、二次方根、while连续输入、斐波那契思路

timerring

刷题 算法题 9月月更

每日算法刷题Day6-循环相克令,字符串插入,单次字符出现

timerring

算法 刷题 9月月更

阿里P9师傅亲传98K+星的MySQL性能优化金字塔法则手册助我升职P7

Geek_0c76c3

Java 数据库 开源 程序员 架构

orbeon form 的架构简介 - 如何访问用户通过 form 存储的数据

汪子熙

SAP Hybris commerce form 9月月更

文科生大数据培训需要注意的问题

小谷哥

回归理性,直面低代码

华为云开发者联盟

云计算 后端 软件开发 低代码 企业号九月金秋榜

每日算法刷题Day1-隐式转换与精度丢失

timerring

算法 刷题笔记 9月月更

膜拜大佬!分享一份京东T9大牛私藏文档:从NIO一直学到Netty

Geek_0c76c3

Java 数据库 开源 程序员 开发

Optional源码解析与实践

京东科技开发者

Java Optional 抛出异常 NullPointerException 映射函数

持续集成之“测试三角形与分段构建策略原则”_Java_乔梁_InfoQ精选文章