HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

提高软件质量:如何处理数据发现更多 Bug

作者:Elmar Jürgens

  • 2023-03-14
    北京
  • 本文字数:4561 字

    阅读完需:约 15 分钟

提高软件质量:如何处理数据发现更多Bug

历史累积的测试套件既测试得太多也测试得太少

 

软件系统的特性通常随着版本的发布不断增长,它们的测试套件也是如此。这会导致测试执行时间变得越来越长。对于手动测试来说,这意味着测试人员要付出更多的努力,从而直接导致更高的成本。对于自动化测试,这意味着开发人员在得到测试结果之前需要等待更长的时间。我们看到许多自动化测试套件的执行时间从几分钟到几小时增加到几天甚至几周,特别是当涉及到硬件时。这种缓慢的速度令人感到煎熬,会间接导致更高的成本,修复两周前出现的问题比修复一小时前出现的问题更难,因为在这期间发生了更多的变化。

 

具有讽刺意味的是,成本如此之高的测试套件通常在发现 Bug 方面表现不佳。一方面,被测试的软件经常会有些部分不会被测试到。另一方面,它们通常包含了大量的冗余,测试到的部分会被重复测试。这些部分的 Bug 会导致成百上千的测试失败。因此,这些测试套件既不有效(因为它们测试不到某些部分)也不高效(因为它们包含冗余测试)。

 

当然,这并不是一个新发现。大多数团队早就放弃了针对每一个变更执行整个测试套件,甚至也不针对每一个新发布版本执行整个测试套件。相反,他们要么每隔几周执行一次(这会延迟发现 Bug,导致修复它们的成本变得更高),要么只执行测试套件的子集(这会遗漏许多本可以被发现的 Bug)。

 

本文提供了更好的解决方案,使用来自被测系统和测试本身的数据来优化测试工作。团队可以在更短的时间内(通过减少执行不太可能检测到 Bug 的测试)发现更多的 Bug(确保测试了 Bug 密集区域)。

 

通过分析开发过程数据来优化测试

 

如果一个测试套件效率低下,那么其后果对开发和测试团队来说是显而易见的:测试工作量很大,但仍然会有很多 Bug 不会被发现,并进入生产环境。

 

然而,由于在大型组织中,没有人拥有完整的信息,对于如何解决这个问题(或者是谁的错),通常会有不同的——经常是冲突的——意见。基于部分信息提出的观点很难被证实或反驳,如果人们把注意力放在与他们的观点相一致的东西上,而不是大局,那么团队(或团队的团队)在很长一段时间内都不会有改进。

 

例如,有时候,经验丰富的测试人员会责怪开发人员在实现新特性时破坏了太多现有功能。作为回应,测试人员将更多的精力放在回归测试上。与此同时,开发人员指责测试人员测试新功能 Bug 的速度太慢。随着测试人员把更多的精力放在回归测试上,新特性中的 Bug 会在更晚的时候才有可能被发现。由于开发人员很晚才发现新特性中的 Bug,所以修复通常是在回归测试完成之后。如果这样的修复在不同的位置导致 Bug 出现,测试人员就没有机会通过回归测试捕获它们。

 

具有讽刺意味的是,这种局面为两个团队的观点提供了支撑,让两个团队更加认为他们的观点是正确的,但这也让问题变得更糟。

 

这些团队必须停止争论一般性的问题,比如原则上需要多少回归测试,他们要做的是看一下数据,看看现在一个特定的变更需要哪些测试。软件存储库,如版本控制系统、问题跟踪器或持续集成系统,包含了大量与软件相关的数据,这些数据可以帮助我们基于数据而不是意见对测试做出优化。

 

为此,我们基本上可以对在软件开发期间收集了大量数据的存储库进行分析,这样就可以得出一些与测试过程有关的问题的答案。

 


过去哪里出现的 Bug 最多?我们可以从中了解到什么?

 

版本历史记录和问题跟踪器包含了过去在哪里修复过 Bug 的信息。这些信息可以被提取出来,并用于计算不同组件的 Bug 密度。



 这显示了在一个系统中,一个组件的每行代码修复密度比系统平均修复密度高了一个数量级,如上面的蓝色矩形树图所示。每个矩形代表一个文件,其面积与文件的代码行数相对应。蓝色阴影越深,表示这个文件越是经常进行 Bug 修复。

 

在矩形树图的中心位置有一簇文件,蓝色比其他部分更深。

 

下面的矩形树图显示了自动化测试的覆盖范围。白色表示未覆盖,绿色表示测试覆盖的增加(绿色越深表示覆盖越多)。值得注意的是,中心的组件包含了大量的历史 Bug,但几乎没有被自动化测试覆盖。

 

经过与团队的讨论,发现了这个组件测试过程的一个系统性问题:开发人员已经为其他所有组件编写了单元测试,但缺少为这个组件编写单元测试的测试框架。开发人员已经提了一个改进测试框架的 Ticket。在实现所需的测试框架之前,他们系统性地跳过了为这个组件编写的单元测试。由于团队不知道这些 Bug 的影响,导致 Ticket 一直呆在 backlog 没有被解决。

 

在上述的分析揭示了 Bug 的影响之后,Ticket 很快就得到了解决,并编写了缺失的单元测试。在此之后,这个组件中的新 Bug 数量不再高于其他组件。

 

未测试的变更(测试间隙)在哪里

 

测试间隙(Gap)是指未被测试到的新代码或修改过的代码的区域。团队通常会特别仔细地尝试测试新代码和修改过的代码,因为从直觉(和经验研究)上看,它们比没有被修改的代码区域包含更多的 Bug。

 

测试间隙分析通过结合两个数据源来揭示测试间隙:版本控制系统和代码覆盖信息。

 

首先,我们从版本控制系统中计算两个软件版本(例如上一个版本和要发布的下一个版本)之间的所有变更,因为根据我们的直觉(和经验研究)认为这些区域是最容易出错的。



 这个矩形树图描绘的是一个包含大约 150 万行代码的业务信息系统。30 名开发人员花了 6 个月的时间来准备下一个版本。每个白色矩形表示一个组件,每个黑色矩形表示一个代码函数。组件和函数的面积与代码行数相对应。灰色矩形中的代码自上次发布以来没有发生变化。红色矩形是新代码,橙色矩形是修改过的代码。树图显示了哪些区域变化相对较小(例如左半部分),哪些区域变化很大(例如右侧的组件)。

 

其次,我们收集了所有测试覆盖率数据。收集过程是完全自动化的,不管是对于自动测试还是手动测试来说。更具体地说,我们使用代码覆盖概要来捕获发生的所有测试活动的测试覆盖信息。不同的编程语言甚至是不同的编译器可能需要不同的分析器,但它们通常适用于所有较为流行的编程语言。



 这个树图显示了上述系统的测试覆盖率。它结合了自动化测试(在本例中是单元测试和集成测试)和手动测试(5 名测试人员花了一个月执行手动系统级回归测试)的覆盖范围。灰色矩形表示测试期间未被执行的函数,绿色矩形表示已被执行的函数。

 

最后,我们将这些信息结合起来,找到那些没有被测试到的变更,从而找出所谓的测试间隙。

 


 在这个树图中,我们并不关心没有发生变更的代码。因此,它们使用灰色表示(与测试期间是否被执行无关)。新代码和修改过的代码用不同的颜色表示:如果是在测试期间执行的,则用绿色表示。如果不是,则新代码用红色表示,修改的代码用橙色表示。

 

在这个例子中(在计划发布日期的前一天),我们看到几个组件(包含数万行代码)在测试期间根本没有被执行。

 

团队可以基于测试间隙分析慎重决定是否要将这些测试间隙(即未测试的新代码或修改过的代码)交付到生产环境中。在某些情况下,这不是问题(例如,如果未测试的功能还没有被使用),但通常情况下最好要对关键功能进行额外的测试。

 

在上面的例子中,团队决定不发布,因为未被测试的功能非常重要。发布被推迟了三周,大多数测试间隙被数以千计额外的(手动和自动)测试用例覆盖到了,他们因此可以捕捉(并修复)关键的 Bug。

 

现在哪些测试最有价值

 

如果我们对代码变更和测试覆盖率进行持续的分析,就可以自动计算出自上次测试套件执行以来哪些代码发生了变更。我们可以明确地选择那些执行了这些代码区域的测试用例。相比重新运行所有测试,运行这些受影响的测试用例能够更快地发现新 Bug(因为不涉及变更的测试无法发现由这些变更引入的新 Bug)。

 

这种测试影响分析加速了开发人员的反馈。根据我们的经验,我们发现我们可以在 1%的时间(运行整个测试套件所花费的时间)内发现 80%的 Bug(运行整个测试套件所能发现的 Bug),或者在 2%的时间内发现 90%的 Bug(关于变更驱动测试的更多细节可以参看这里)。

 


一般来说,哪些测试最有价值

 

一些测试本身就需要消耗昂贵的资源。例如,我们的一些客户在昂贵的硬件上执行测试套件。每个测试运行包括数万个单独的测试,需要数周的时间来执行,并集成来自不同团队的组件。而这些测试又很重要,因为没有这些测试软件就不能发布。

 

对于这种大型、昂贵的测试套件来说,一个真正的问题是“海量 Bug”:一个位于中心位置的 Bug 会导致数百甚至数千个测试用例失败。如果被测试的系统版本包含大量 Bug,那么整个测试就会被破坏,因为在数以千计失败的测试中很难再进一步找到其他 Bug。因此,测试团队在开始执行大型、昂贵的测试套件之前,需要确保所测试的系统不包含质量缺陷。

 

为了防止出现海量 Bug 现象,团队使用了验收测试套件(也叫作冒烟测试套件),在执行大型、昂贵的测试之前必须先通过验收测试套件。验收测试套件将执行所有测试中的一小部分,这些测试极有可能会发现会导致众多测试失败的 Bug。

 

我们可以根据特定的代码覆盖率信息从现有的测试集中选择一个最佳的验收测试套件(在最短的时间内覆盖最多的代码)。我们发现所谓的“贪婪”优化算法比较有效:它们从一个空集开始,逐步添加每秒覆盖最多代码行的测试。然后,它们继续添加那些覆盖了还没有被之前的测试覆盖到的代码行的用例。重复这个选择过程,直到验收测试套件的时间预算用完为止。在我们的研究中,我们发现我们用这种方法选择的验收测试套件可以在 6%的时间内(执行整个测试套件所需的时间)找到 80%的 Bug(整个测试套件可以检测到的 Bug)。



 我们在一个项目中将这种选择验收测试套件的方法与测试专家手动选择的验收测试套件进行了比较。对于前两年的历史测试执行数据,优化选择的验收测试套件发现的 Bug 比专家手动选择的套件多两倍。

 

这种方法不如测试影响分析(只需要 1%的时间就能找到 80%的 Bug),但是当可用的信息较少时(我们不需要知道自最后一次执行测试以来的所有代码变更),可以使用这种方法。

 

如何在项目中开始使用测试智能分析

 

测试智能分析可以为各种问题提供基于数据驱动的答案。因此,你很有可能会尝试使用它们,看看它们能揭示出有关系统的哪些信息。

 

如果从正在被测试的系统的特定问题开始会更加有效,变更管理会因此更有可能取得成功,因为说服同事和经理解决问题比尝试新工具来得更容易。

 

根据我们的经验,在使用测试智能分析之前,可以先考虑以下这些问题:

 

  1. 是否有太多的 Bug 从测试环境进入到生产环境?通常,造成 Bug 的根本原因就是测试间隙(即尚未被测试的新代码或修改过的代码区域)。测试间隙分析有助于在发布之前发现并解决它们。

  2. 整个测试套件的执行时间是否太长?测试影响分析可以识别出 1%发现 80%新 Bug 的测试用例,这大大缩短了反馈周期。

 

一旦采用了测试智能分析,就可以很容易地用它们来回答其他问题。因此,团队很少只使用一种分析手段。但要解决实质性的问题,总是要卖出第一步。

 

作者简介


Elmar Jürgens 写了一篇关于静态分析的博士论文,现在仍然活跃在软件质量分析领域。2009 年,他联合创立了 CQSE GmbH,帮助开发团队更有效地使用分析工具。Jürgens 经常在研究会议(如 ICSE、ICPC)和行业活动(如 GTD、OOP、JAX)上发言。Jürgens 在 2015 年被评为 ACM 德国分会的 Junior Fellow。

查看英文原文:

https://www.infoq.com/articles/process-data-find-more-bugs/

相关阅读:

软件开发,如何同时保证效率和质量?

软件质量因素的定义

软件质量问题造成损失高达 2.4 万亿美元!

软件测试 | 质量控制

2023-03-14 14:536491

评论

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

【伙伴故事】一盏智能灯,点亮家庭和工业照明的新未来

华为云开发者联盟

物联网 华为云 AIOT PLC 智能照明

快过年了,用五种不同的JS特效带你看烟花

海拥(haiyong.site)

大前端 js 28天写作 前端特效 1月月更

“云联邦”构建连云成片、无缝混合的一朵云

华为云开发者联盟

混合云 多云 华为云Stack 云联邦 联邦认证

知识中台,驱动产业智能化升级

百度大脑

人工智能

全面容器化之后,来电科技如何实现微服务治理?

阿里巴巴云原生

阿里云 微服务 云原生 实践

MASA Framework - EventBus设计

MASA技术团队

C# .net 微软 框架 Framework

做网络安全竟然不了解ATT&CK?这篇文章的介绍详细到令人尖叫

博文视点Broadview

4种Spring Boot 实现通用 Auth 认证方式

华为云开发者联盟

拦截器 spring-boot Auth 传统AOP 参数解析器

零数科技入选毕马威中国“2021领先金融科技50企业”

科技热闻

Hoo虎符研究院 | 币圈后浪——Osmosis一种高级AMM协议

区块链前沿News

Hoo 虎符交易所 虎符研究院

🍃【Spring专题】「技术原理」为大家介绍一下Spring中的Ant路径匹配工具组件AntPathMatcher

洛神灬殇

spring 1月月更 SpringFramework AntPathMatcher

中小型企业过等保困难有哪些?如何解决?

行云管家

网络安全 企业 过等保

喜讯!Apache APISIX Committer 张晋涛当选「中国开源先锋 33 人」

API7.ai 技术团队

云原生 微服务网关 APISIX 网关

微帧ROI视频智能编码:基于人眼感兴趣区域,实现极致观感体验

微帧Visionular

视频编码

构建面向异构算力的边缘计算云平台

火山引擎边缘云

gpu 云原生 边缘计算 算力

详解数据湖:概念、特征与架构

五分钟学大数据

数据湖 1月月更

零数科技入选毕马威中国“2021领先金融科技50企业”

科技热闻

【等保小知识】等级保护工作是指等保测评吗?意思一样吗?

行云管家

网络安全 等保 等保测评

开源操作系统年度技术会议演讲PPT下载来啦!

鉴释

开源 操作系统

移动数字化平台如何让企业生态协同更高效?

WorkPlus

武汉智慧城市建设新名片 一城一云打造数字经济新引擎

InfoQ_967a83c6d0d7

产业协同,助力数转 | 鲸鲮正式加入中国电信5G产业创新联盟

鲸鲮JingOS

Linux 5G 操作系统 信创 电信

MobTech观察 | CSDN:企业数字化转型如何提升段位?杨冠军畅谈企业数字化前世今生

MobTech袤博科技

数据分析 数字化转型 数据治理 企业 数据可视化

共建龙蜥社区,支撑商业建设

OpenAnolis小助手

Linux 开源 开发者

面试官: Flink双流JOIN了解吗? 简单说说其实现原理

华为云开发者联盟

sql flink join 双流join 数据库SQL

利用 Amazon Batch 来为容器化负载调用海量云端算力

亚马逊云科技 (Amazon Web Services)

计算

大数据开发之Hadoop高频面试题

@零度

大数据 hadoop

4种高速安全混合云解决方案,助力您的云迁移之旅!

亚马逊云科技 (Amazon Web Services)

计算

通过 Amazon CloudWatch 配合 Amazon ElastiCache for Redis 遵循监控最佳实践

亚马逊云科技 (Amazon Web Services)

计算

关于减碳你是否有很多问号?施家碳中和咨询服务来了!

ToB行业头条

Go Error 嵌套到底是怎么实现的?

AlwaysBeta

Go 源码 源码阅读 Go 语言 源码学习

提高软件质量:如何处理数据发现更多Bug_架构_InfoQ精选文章