硬核干货——《中小企业 AI 实战指南》免费下载! 了解详情
写点什么

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

  • 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:325662
用户头像

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

关注

评论

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

速剖架构(一)-- 流量的自然走向

Dinfan

架构设计

RocketMQ 监控告警:生产环境如何快速通过监控预警发现堆积、收发失败等问题?

阿里巴巴云原生

阿里云 RocketMQ 云原生

算力新话题,畅聊算力之新民生

鲸品堂

算力网络 企业号 2 月 PK 榜

Sugar BI 增强分析能力全场景解析

XxinQi

数据分析 可视化 BI 商务智能 预测模型

化繁为简|中信建投基于StarRocks构建统一查询服务平台

StarRocks

数据库 大数据 开源

新书上市 | 以过去预测未来,有趣的时间序列

图灵社区

机器学习 统计学 时间序列 时间序列预测

上海前端培训学习的就业前景

小谷哥

单体应用、SOA、微服务,优劣势都有哪些?

FinFish

微服务 微服务架构 前端开发 移动开发 小程序化

前端报表如何实现无预览打印解决方案或静默打印

葡萄城技术团队

新书上市 | 以过去预测未来,有趣的时间序列

图灵教育

机器学习 统计学 时间序列 时间序列预测

真正的低代码平台

陈飞

PaaS SaaS 低代码平台

启科量子解决方案实践:使用QuTrunk+AWS Deep Learning AMI(TensorFlow2)构建量子神经网络

启科量子开发者官方号

人工智能 量子计算

设计模式-工厂方法模式和抽象工厂模式

C++后台开发

数据结构 设计模式 后端开发 Linux服务器开发 C++开发

关于Zebec生态的改进提案,以及即将上线的 Nautilus 链

BlockChain先知

基于流量双发平台的高效回归方案

网易云信

反垃圾 业务集群

Go1.20新版本正式发布,新特性值得一看

王中阳Go

Go golang 高效工作 学习方法

《流浪地球2》“数字生命”最后一秒拯救人类,现实中AI也正在“长出”灵魂

硬科技星球

BIGO 如何做到夜间同时运行 2.4K 个工作流实例?

白鲸开源

spark 工作流调度 Apache DolphinScheduler 离线计算

谷歌用Bard打响了Chat GPT的第一枪,百度版Chat GPT 何时出炉?

GPU算力

在这些工厂、农田、服务区,看到智能中国的草蛇灰线

脑极体

人工智能 华为 许昌

干货分享 | 3个Zbrush实用减面工具分享

3DCAT实时渲染

3D渲染 3D模型

Apache RocketMQ 入选 SegmentFault 年度中国技术品牌影响力企业榜单!

阿里巴巴云原生

阿里云 Apache RocketMQ

可路由计算引擎实现前置数据库

石臻臻的杂货铺

数据库

Top 5 OSSInsight 年度最佳 MLOps 开源工具

Jina AI

深度学习 开源框架 Jina MLOps OSSInsight.io

UE干货| UE虚幻引擎调试神器—控件反射器

3DCAT实时渲染

游戏开发 虚幻引擎 ue 游戏开发引擎

浅谈 2022 前端工作流中全流程多层次的四款测试工具

Liam

前端 测试 前端开发 测试工具 测试开发

点对点传输现状,镭速高速点对点传输解决方案

镭速

架构实战营 10 期 - 作业 6

炮仗

程序员必备的数据库知识 2:Join 算法

NineData

数据库 程序员 join SQL sever NineData

CNStack 2.0:云原生的技术中台

阿里巴巴云原生

阿里云 云原生 技术中台

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