如何减轻软件开发的回测压力?Facebook 已经用上了机器学习

如何减轻软件开发的回测压力,从而提高工程师的生产效率?MATEUSZ MACHALICA、ALEX SAMYLKIN 等人组成的 Facebook 研究团队提出使用一个利用机器学习的新系统来创建一个为特定代码更改选择回归测试的概率模型,从而更好地执行这种回归测试。

为了高效地开发新产品特征和更新,Facebook 研究团队使用基于主干的开发模型来管理对代码库的改动。一旦一位工程师的代码更改被接入主分支(主干),他们试图让它对从事该产品或服务的其他工程师快速可见。这种基于主干的开发模型比使用特征分支和特征融合更加有效,因为它使得每个人都能够在代码库的最新版本上工作。

但是,在被接受到主干之前,对每项提出的更改进行彻底的回归测试很重要(注:回归测试是指修改了旧代码后, 重新进行测试以确认修改没有引入新的错误或导致其他代码产生错误的一种测试方法)。在从主干被部署到生产之前,每项代码更改都需要经过彻底的回归测试,进入主干异常代码会使得评估新提出的代码更改变得更困难得多,并且还会影响工程师的生产效率。

对此,该研究团队开发了一种更好的方法来执行这项回归测试:使用一个利用机器学习的新系统来创建一个为特定代码更改选择回归测试的概率模型。这种方法需要仅仅运行一个小的测试集,以确保检测到错误的更改。与典型的回归测试选择(RTS)工具不同,该系统通过从历史代码更改和测试结果的大型数据集中学习,来自动开发测试选择策略。

这个预测性测试选择系统已在 Facebook 上部署了一年多,在一段新的代码加入到主干、被其它工程师看到之前,这个系统就可以捕捉超过 99.9% 的回归异常,而且它运行的基于修改的代码的测试数量也只需要以往的三分之一那么多。这也让 Facebook 的基础测试设施的效率得到翻倍的提升。

随着代码库的不断发展,该系统也几乎不要求手动调试。而且经证明,它还能够捕捉产生不一致和不确定性结果的片状测试。

为什么使用创建依赖项是低效的

回归测试的一种常用方法,就是使用从构建元数据中提取的信息来确定在特定代码更改上运行哪些测试。通过分析代码单元间的创建依赖项,可以确定传递依赖于在代码更改中被修正的源的所有测试。例如,在下图中,圆圈表示测试;正方形表示代码的中间单元,如库;菱形表示存储库中的单个源文件。箭头连接起实体 A →B,当且仅当 B 直接依赖于 A 时,他们将其解释为 A 影响 B。蓝色的菱形表示在示例代码更改中被修正的两个文件,所有传递依赖于它们的实体也用蓝色表示。在这个场景中,基于创建依赖项的测试选择策略将执行测试 1,2,3 和 4,但不执行测试 5 和 6,因为后两项测试不依赖于修正的文件。

这种方法有一个明显的缺点:它以说「是的,本测试受到影响」告终的次数比实际所需要的要多。平均而言,对于移动代码库的每项更改,该方法都会导致执行多达四分之一的可用测试。如果传递依赖于修正文件的所有测试都真正受到影响,他们将别无选择,而只能将每项测试都执行一遍。然而,在他们的单片代码库中,终端产品依赖于许多可重复使用的组件,这些组件使用一小组低级库。在实践中,许多传递性依赖实际上与回归测试无关。例如,当某个低级库发生更改时,在使用该库的每个项目上重新运行所有测试将是低效的。

软件开发研究领域也开发了其他的回归测试选择方法,例如基于静态更改-影响分析的方法。然而,由于他们代码库的大小和使用的不同编程语言的数量,这些技术在他们的使用案例中是不现实的。

一种新方法:预测性测试选择

基于创建依赖项的选择测试涉及到判断哪些测试可能受到更改的影响的问题。为了开发更好的方法,Facebook 的研究团队考虑了一个不一样的问题:指定的一项测试发现某个代码修改中的回归问题的可能性有多大?如果他们能估计到这个可能性,就可以做出明智的决定,来排除那些极不可能发现回归的测试。这是对传统测试选择的重大背离,并且开辟了一种新的、更有效的选择测试方法。

作为第一步,该研究团队创建了一个预测模型,该模型针对新提出的代码更改估计每项测试失败的概率。他们通过使用包括历史代码更改上的测试结果在内的大型数据集,然后采用标准的机器学习技术来创建模型,而非手动定义模型。

每个新的代码更改总会与之前的情况略有不同,因此模型不能简单地将新的更改与历史更改进行比较,来确定哪些测试值得运行。然而,新更改的抽象可以类似于前一个或多个代码更改的对应的抽象。

在训练期间,研究团队的系统学习基于源自先前代码更改和测试的特征的模型。然后,当该系统正在分析新的代码更改时,他们将学习到的模型应用于基于特征的代码更改的抽象。对于任何特定的测试,该模型接着能够预测检测到回归的可能性。

为此,该系统使用了标准机器学习算法的变体——梯度提升决策树模型。研究团队虽然可以使用其他机器学习算法,但其之所以选择这种方法,有几个原因:决策树是可解释的、易于训练的,并且已经是 Facebook 机器学习算法基础结构的一部分。

他们可以使用这个模型分析特定的代码更改,来找到所有传递依赖于修改文件的可能受影响的测试,然后估计测试检测到由更改引入的回归的概率。基于这些估计,系统选择对于特定更改最有可能失败的测试。下图显示了将选择哪些测试(用蓝色表示),来更改影响前一示例中的两个文件,而在前一示例中,用 0 到 1 之间的数字来表示每个被考虑在内的测试的概率。

评估和校准模型

对于每项代码更改,系统选择的测试数量影响它在检测回归时的可靠性。使用最近代码更改的选择作为验证集,研究团队可以评估其在新更改上的准确性。下面的图表显示了每次更改所选择的最大测试数量与这一选择的准确性之间的关系。在生产中,他们要求其模型能够正确预测超过 95% 的测试结果,并且能为超过 99.9% 的有问题的更改捕获至少一个失败的测试。他们发现,这种准确度的高标准所带来的测试信号的损失可以忽略不计,并且消除了大量不必要的测试执行。

由于代码库结构的不断演变,测试选择策略必须适应继续满足这些严格的正确性要求。然而,他们的系统让其变得简单,因为他们可以使用最近提交的代码更改的测试结果来定期地重新训练模型。

处理测试片状

为了确保他们的测试选择很好地适用于现实世界的测试,系统需要处理测试片状问题:当被测试的代码没有真正被更改时,测试结果从通过变为失败。正如他们在论文中所做的更详细的解释,如果他们训练一个模型而不去识别片状测试失败,该模型可能无法学习去一致地预测测试结果。在下面的示例中,两个测试选择策略捕获所有失败的测试执行的共同部分。如果系统不能区分哪些测试失败是片状的以及哪些不是,那么它将无法知道哪个策略是最好的。策略 A 具有明显更好的准确性,因为它捕获了所有无法发现实际回归的测试。然而,策略 B 选择了大量由于片状性而非代码的实际问题而失败的测试。

为了减轻片状性对所学到的测试选择模型的影响,研究团队在收集训练数据时积极地重新尝试失败的测试。这种方法让他们将连续失败的测试(指示真实回归)与那些呈现片状、非重现性失败的测试区分开来。

检测和固定回归:30000 英尺的视角

这个系统是研究团队创建智能工具以使代码开发过程更加可靠和高效的更广泛努力的一部分。他们的基于搜索的自动化软件测试系统 Sapienz 和自动化缺陷修复工具 Getafix,也可以帮助他们自动检测和修复回归——也就是说,这些工作仅要求工程师们投入很少的注意力甚至不投入注意力。

预测性测试选择(这篇博客文章中描述的系统)通过选择由工程师定义的正确的测试集,来高效地检测回归。Sapienz 生成新的测试序列,来发掘让移动应用程序崩溃的条件,Getafix 则为他们使用测试和验证工具所发现的问题推荐补丁,然后由编写更改的工程师检验并选择接受或拒绝这些补丁。总而言之,这些系统让工程师能够为使用 Facebook 产品的数十亿人,更快、更有效地创建和部署新特征。

未来规划

预测性测试选择是 Facebook 的数个项目中的一个,它旨在应用统计学方法和机器学习来提高回归测试的有效性。随着研究团队进一步提高系统的效率和准确性,他们也将应用相关的方法来识别测试范围中的潜在差距。

机器学习正在变革生活的方方面面。他们相信软件工程在这方面也一样。

原文地址:https://www.cnblogs.com/chuangye95/p/10200637.html

时间: 2024-10-27 19:16:54

如何减轻软件开发的回测压力?Facebook 已经用上了机器学习的相关文章

敏捷软件开发(Agile Software Development)的上位史

敏捷软件开发(Agile Software Development)的上位史 所谓敏捷,最常见的用法,便是用来形容动作的迅速与思维的活跃了,但若是给"软件开发"这个计算机行业的术语强行戴上一个"敏捷"的帽子,读者见了十有八九会一脸懵逼:厉害了我的哥,软件开发怎么还能"敏捷"了? 从上面的漫画可以看出,"敏捷软件开发"并不是要求开发人员练出像猴一样的敏捷身手(当然如果读者真的是一位身手敏捷的程序"猿",那就更

对软件开发的理解

软件开发是根据用户要求开发出软件系统或者系统中软件部分的过程. 本书讲的模型有以下几种. 一.瀑布模型 二.快速原型模型 1. 思想的产生 2. 原理 3. 类型 4. 运用方式 5. 开发步骤 6. 与瀑布模型的对比. 7. 缺点 8. 优点 三.增量模型 1.缺点 2.优点 四.螺旋模型 五.喷泉模型 六.敏捷模型 七.智能模型 八.混合模型 开发方法有以下几种 一.结构化方法 二.面向数据结构的软件开发方法 三.面向对象的软件开发方法 四.可视化开发方法 五.软件重用和组件连接 白话MSF

程序与软件、编程与软件开发的区别

今天突然想到两个有意思的问题:程序与软件有区别吗? 编程与软件开发有何区别? 这两个问题也是我在大学时期一直思考的两个问题.作者在学校期间阅读了许多的专业书籍,比如<Java语言程序设计>.<C语言程序设计>.<软件工程>.<设计模式:可复用面向对象软件的基础 >以及许多<21天精通XXX程序设计>系列书籍,也写了许多的小程序,但有一些问题作者始终没有完全弄清楚.比如: 1.真的可以在21天之内精通某一门程序设计语言吗? 2.什么是面向对象? 3

软件开发平台的演变

从编程之初,便免不了和方法,类,接口之类的东西打交道.久而久之,自然会对此进行总结,由此而产生了开发平台.而今中国的程序员之中,有很大一部分都是编一些企业MIS.政府MIS之类的程序.其主要工作就是对数据进行一下增删改查的操作,对MIS系统做一些基础的管理而已.软件开发平台有两种平台模式:一种是传统的C/S架构模式,一种是现在流行的B/S架构模式.B/S架构模式是随着互联网的流行,自然又要求以互联网为基础,把这些都网络化,以实现网络资源共享,而不是传统的单机模式.这便激发了软件开发者的创造力,形

直播软件开发中连麦功能解析

在视频直播过程中,用户看到的主播直播画面其实是单向直播,视频直播软件开发的服务器接收到主播传输上的画面后,分发到各请求端,属于单向内容输出.当出现用户请求与主播连麦时,性质就发生改变,信息流传输由单向传输变为双向传输,如果有用户正在观看直播,那他接受到的信息流包括主播和连麦用户两股信息流. 为保证观看用户能及时接收到语音信息,直播平台都会使用CDN分发直播内容.也就是说用户接收的信息流线路不一定是它在请求获取信息时的那条线路,而是由CDN节点根据服务器的负载情况,重新选择最优线路进行分发.对于互

软件开发中的自测及C代码示例

在软件开发中,程序自测是一个永远都绕不开的话题.很多开发人员以写出有难度的代码为荣,但却不重视对自己编写的代码进行测试,这导致了最终到达客户手中的产品质量不高,bug频发,损害了公司的形象.对于一个开发人员来说,我们应该将开发和自测置于同等重要的地位,我们花在自测上的时间要不比开发少.能否对自己编写的代码进行充分的自测也是检验一个开发人员水平高低的标准之一. 自测方法 根据所编写的程序的特点,自测方法大致有如下几种: 第一种,利用模拟工具进行自测.这种方法适用于需要其他模块(尚不具备)发过来的消

二码公益软件开发app分析

二码公益软件开发app分析 王泽:151.1222.4001(微信同步)二码公益系统软件开发,二码公益app模式开发,二码公益平台开发,二码公益全返模式,二码公益商家让利平台,二码公益消费返利平台.非平台客服,玩家勿扰!!!灵猴欢腾辞旧去,金鸡报春迎新来.1月11日下午,二码公益山东商家联谊会暨年货大集,在青岛海鲜巨无霸怡情楼隆重举行.作为二码公益联盟商家的首批商户,里白黑蒜参与了活动并给予了赞助.本次年货大集是二码公益举办的第一次,现场气氛火爆,里白黑蒜更是得到广大消费者的喜爱. 你问我为什么

软件开发生命周期中测试的使用情况

软件开发的生命周期主要包括以下的阶段: 1.问题定义. 2.可行性研究. 3.需求分析. 4.概要设计. 5.详细设计. 6.编码和单元测试. 7.综合测试. 8.软件维护 以上就是一个软件开发的完整生命周期,能比较明显的看出,到详细设计为止,之前的阶段很少涉及到测试的环节,从编码实现开始,测试就开始贯穿之后的阶段,编码实现中,用的最多的就是单元测试,编码人员或测试人员主要通过一些测试用例来检测编写的代码块是否实现了所需要的功能,但是单元测试中又分为黑盒测试和白盒测试,黑盒测试是不知道内部的详细

软件开发到底是怎么一回事呢?

人生得一良友不易,友人是做数据库DBA(运维方向)出生,对软件开发算是没有什么经验,但是最近手头却有点儿事让它对软件这件事开始有了兴趣.于是就问我这个问题.我呢,水平很差,这么大的标题丢过来,怎么回答呢?好在友人给明确了方向: 代码管理,版本控制,补丁管理,架构设计,模块划分,接口设计,报错编码制定,日志设计,测试方法,安全管控,性能规划 然后我就根据这些,作答如下,既然写了这么多,就拿出来和大家分享. 1.代码管理,版本控制,补丁管理对于单一产品的公司,其实问题就是各种迭代和这些迭代的管理.首