当前位置: 首页 > 科技观察

【NCTS峰会回顾】饿了么邱华峰:人工智能在Bug定位中的应用_0

时间:2023-03-19 02:06:50 科技观察

2019年10月26日,由Testin主办的第二届NCTS中国云测试行业峰会在京召开。以“未来”为主题,汇聚国内外测试领域知名专家学者、领先企业决策者、高层技术管理者、媒体从业者等,共同探讨高端云测试技术帮助测试从业者了解最前沿的行业动态和最新的行业实践。会上,饿了么测试开发专家邱华峰做了主题演讲《人工智能在Bug定位中的应用》。邱华峰指出,“企业要想获得人工智能带来的便利,首先要制定相应的标准,没有这个标准,按照固定的算法就很难实现。”以下为邱华峰演讲实录:今天我讲的是人工智能。智能在错误应用程序中的定位。在讲这个话题之前,我想做一些统计。有多少人用java来管理bug?修复bug后,在代码中,要关联bug的请举手。人工智能定位首先需要一个数据基础。这个数据的来源是什么?测试通过java提交bug。我们有BUG的描述,BUG的相关信息,以及BUG的重现步骤,直接给开发提。开发会按照这些步骤执行,看能否重现bug。如果可重现,开发将需要关联相关问题。关联后,将作为bug分析的前提。不需要手动标注什么样的样本,因为把bug描述的相关信息放好后,我们就可以通过自然语言或者人工处理提取出bug相关的字段,比如什么是exception,什么是error,问题是什么。有了这个基础,一些样本就可以在不需要人工标记的情况下获得。学术界还有一件事要做。首先,有些人维护所有关于java的错误。当修复这些bug时,会产生一些数据,告诉你哪个方法在哪一层,哪个方法哪一行出现了什么错误。要想使用人工智能带来的便利,首先要制定一些相应的标准。没有这个标准,很难按照固定的算法得到你想要的。说完这些前提,我主要讲三个部分。第一个是工具的介绍,第二个是bug定位的原理和方法,第三个是使用这些工具后应用的具体方面。有八种工具。这个PPT是以前做过的。上个月,一个新的bug定位技术问世了,就是基于行为的bug定位技术。以上八种定位技术都是根据相关样本的可用性进行相应的处理,通过提取测试用例来编译和测试这些东西。这个大部分是基于单元测试来做的,但是基于行为的已经突破了,在单元测试层面获取bug样本,根据链接来分析什么样的情况。第一个是程序谱,就是我运行了多少测试用例,成功的测试用例覆盖了哪些行,失败的测试用例覆盖了哪些行。我们计算失败的测试用例占用的行数,我们做一个排序,得到这行代码出现BUG的概率。然后在变体的基础上,在程序谱的基础上进行了改进。该变体当前已应用。最实用的是衡量测试用例有效性的一个非常重要的手段。我写了那么多测试用例。这些测试用例真的有效吗?我可以去变体测量它。基于变体,生成两个变体,并有一个变体分数。分数越高,表示本单元测试用例的质量越高。程序切片是一种通过程序切片或场景生成程序用例的方式。程序切片也可以用于错误定位,然后堆栈跟踪。APP端用于监控,类似于连接到监控系统的学生举手。Android系统下的大部分应用只在Android上发布。有多少学生不在iOS上分发?他们中的大多数都是Android和iOS。基于stacktrace,有很多stack的话题可以聊,比如logs,logs,还有怎么把这些东西放到网上。Stacktrace不仅仅适用于server端的bug定位,也可以适用于C端的bug定位。比如界面突然崩溃,或者突然死机,我拿到相应的栈信息,我也可以直接去bug。定位和预测错误。第五个是上下文切换,这个就不说了。第六是信息检索。通过一些词出现的频率,或者说出现的概率比较高,知道热点覆盖概念的请举手,可以告诉我吗?Audience:有个热力图可以看用户哪边点击多,哪边点击少。邱华峰:我们采用变向的热点覆盖方式,映射到修改的方式最多。最后是机器学习。如果我们要知道如何定位bug,通过人工智能,首先要定义各种指标,而这些指标决定了定位bug的准确性。基于java,这里列出了7个。首先看一下有效代码行数,圈复杂度,包括是否符合javadoc规范。为什么要把这个作为参考指标?阿里巴巴推出Java编写规范,并不是说它是凭空产生的,而是基于对阿里巴巴所有代码仓库的扫描,包括历史记录,比如空格应该有多少行是空的。我们有人工智能定位工具,通过统计bug的种类来统计。产生bug最常见的原因是随机命名的变量名,这是定位bug最重要的参考指标。大部分的bug都是人类在一定范围内的理解或认知产生的,导致对某个变量名的错误使用,包括函数。代码编写标准,一代是函数式的,二代是面向对象的,面向对象不是万能的,我们写面向对象的时候,是不是容易维护,容易理解?最重要的是扇入和#128085;扇出。我在做bug定位的时候,如果多次引用这个方法,出现bug的概率也会增加。然后是包装的设计质量。以前是单体应用,现在讲微服务,现在讲平台。这些相当于在包的基础上做了一些改动。之前我们是一个单体应用,我们拆分成微服务之后应该做什么?当把微服务抽出来做一个中台的时候,主要的变化就是Jar包的结构,这些东西也在不断变化。第四,用于分析Jar包的升级质量,变量个数和参数个数,这也是影响bug定位的主要指标。如您所见,您可以知道在测试过程中发现了最多的变量。同学们,你说的是用了多少个参数,或者说一个函数可以支持多少个函数?有人知道吗?参数的数量在语言中或多或少有所不同。我在函数中传递参数时,函数的参数名和变量最多只允许有256个,如果超过256个,程序就跑不起来了。变量和参数的个数也作为bug定位的指标。看最后一个,运营商的数量。我们都知道,功能测试和中间件测试是有本质区别的。区别在哪里?基于业务的可能是业务场景、逻辑,或者业务场景比较固定,逻辑上的简化比较好,但是作为一个中间件,会考虑很多不确定的因素。当我们考虑这些不确定因素的时候,其实是增加了操作者的操作。第二部分,原理与方法。刚才我们也给大家普及了基础的东西。这部分训练集来自实践中编写的代码或样本。它是用于错误预防的第一代原型。比较简单,只用了A圈复杂度,知道圈复杂度的同学举手,为什么可以作为预测bug发生概率的重要指标呢?也就是圈复杂度会根据你写的代码,里面有多少个分支,走了多少个流程,和圈复杂度比较。在一个函数中,如果圈复杂度是工业级的,比如军用软件,一般检测到不超过7,或者更严格一点,代码复杂度不能超过5。当圈复杂度较高时,证明那就是写函数体越来越长,但是如果在5、7以内,大概是40行,如果超过7,到了20,代码行数可能就变成几千行了。一个几千行的函数,不管是让原来的开发,还是接手做这个的新开发,都变得难以维护。既然可以知道圈复杂度有这样的作用,那么我们就可以利用圈复杂度来预测和测试代码,然后扫描圈复杂度看是否在合理的范围内。如果不在合理范围内,可能会有一定概率的bug。这张图介绍了在学术界的应用,解决了添加代码中的bug,并做了一个sample,修复bug之前代码是怎么写的,修复bug之后代码是怎么写的。这是第二个基于错误定位的原型,用于预测错误缺陷。从第一个原型到第二个原型,中间经历了很多步骤。首先,需要一个数据集。二是上面提到的学术界获取数据集的方法。三是用人工自然语言来处理,不需要java管理,或者和javaBug无关,但是直接写的开发者很多,不管是英文还是中文注释,都会讲到某些问题。共同发展就行了。三是获取样本的方法。以后可能导致bug的因素有哪些?这就是对这些因素的整理和处理。在做bug定位或者预测的时候,首先要知道哪个指标应该占什么比例。用刚才的方法不断调整各种指标的比例,然后根据这些比例的比例,判断实际Bug和最终现实的匹配程度。人工智能有一个专业术语叫召回率。看最后的结果,这属于二代的原型机。在这个原型中,有一个测试样本,其中大部分是使用变异测试来完成的。这是基于java,参考各种因素和指标,可以展示一些示例结果。每种定位技术得到的定位结果也有很多差异。如果想看具体的实现,这个下面有个链接可以生成各种技术的统计结果,包括方法、源码、结果。大家可以进去看看具体实现是怎么样的。这是栈,当前栈抛出。一般来说,无论是前端还是后端,都需要进行封装。异常,堆栈有多个方法。异常会提示属于哪种异常。它基于系统层面,由中间件定义,由用户行为定义。这个时候不能简单的说是作为缺陷来使用。预防先用三层,不可直接简单使用。根据堆栈来预测这种情况,会比较准确。这个会告诉你某个类,某个方法,哪条线到哪条线下面,我们在基于热点覆盖的时候经常会提出一个概念,得到修改后的线,通过修改后的线进行匹配。代码会清楚地告诉你,我在这一行把它扔掉了。开发解决问题的时候,经历过开发,会做一件事。我会一直看0或者1,不要看后面,以后扔掉。出来的东西和现在的完全不一样。既然可以通过这个进行开发,那么我们就可以把它变成一种缺陷预防或者一种技术判断手段。这时候我们就可以针对这些抛出的Exception,做一个排名。我们需要收集所有的在线日志,不管所有日志中是这种类型还是这种方法,只要在里面出现过一次,我就给排名加“1”,我会先看是哪种类型或者方法worldworld,即使行数不同,我想统计一下这个方法下服务器的排名。我刚才说的是如何建立我的缺陷预防指标的参考。你可以看到这些指标,比如有多少链接被调用,有多少函数在栈中被抛出。异常相关信息,十位前的ST为基础数据。我们发现用基础数据来预测BugStackTrace出现的概率并不是很准确。Bug出现的概率是多少?,或者在统计学上应该叫均值,参数应该是综合的。举个简单的例子,如果这个项目只有两个文件,如果抛出堆栈异常,这两个类有多少个,而我有10个文件,但是每个类的代码行数对应到不同数量的行。要想全面了解bug发生的概率,不能简单的拿其中一个指标作为参考。做了组合之后,相当于对bug出现的概率和情况做了更详细的指标定义。有了这个指标的定义,就更容易预测bug出现的概率。这是堆栈信息人工智能预测的模型。它将StackTrace与错误代码相关联,进行提取和构建模型,并自动对其进行标记。第二阶段,我这个线上已经有很多异常了,我们有一个新的,能不能直接定位到某类某行的方法。你为什么要这样做?现在测试要么向左移动,要么向右移动。对于我们来说,在配合开发的时候,他觉得最理想的测试就是说没有那么多的步骤和方法。你能写一个单元测试并直接告诉我们吗?我的问题在哪里。有很多方法希望测试能做到这一点。不是说测试不能做,测试也可以做,只是需要很多工具,包括历史数据的积累。而且很多时候,测试更了解场景,包括业务,这里只写了一小部分模块。如果把测试反馈给开发,这个是可以做到的。这是第三代技术,将静态分析和动态分析融为一体,把代码覆盖率、方法覆盖率、分支覆盖率做成一个矩阵。对应这个矩阵,可以认为原来的第一代是一维的,只有一个东西可以帮助我们做判断。这是一个二维的。在第三代,其实是多了维度,但是这个维度把static和dynamic也都放进去了,同时把覆盖的行也放到了统一的PageRankMatrix里面,看看能不能把多角度预测这个bug出现的概率。最后我们会得到一个RankList,统一做各种排序,然后看预测bug出现的概率,会比之前更准确。还有一种最近刚出现的基于行为的定位bug,这里就不描述了。那我们就来说说如何应用吧。程序谱是定位bug的有效方法。卡住了,首先不能简单的用指标来衡量。需要作为一个综合指标来看整体的测试质量。你会发现它们之间是正相关的,或者说是线性数据的指标。代码写得越差,出现bug的概率就越高。这是毋庸置疑的。其次,StackTrace对于定位Crash非常有效。现在手机经常运行不动,或者反应比较慢。我们会得到栈的错误异常并上报。这个时候,定位这些异常就很重要了。这是非常有效的。用它来提高Android终端的响应,包括发生什么样的错误,是一个非常有效的手段。三是错误样本集还不够大。刚才说的三种方法,还是遗漏了很多遵循规范和固定操作系统的失败。许多发展并没有遵循这一点。一种叫做全样本,这也是密切相关的。的元素。另一件事是算法的多样性。我们使用静态调用和动态调用,里面的算法也是五花八门。目前有20多种算法,算法也决定了预测bug发生概率的重要参考因素。很明显,一代不如二代,二代不如三代,但是迭代的版本和方法多了以后,原来简单的算法就不适用了。每次添加一个因子,或者每次添加一个参考因子,模型都要进行相应的处理,从而预测bug的发生。现场视频(下)通过这些bug定位的技巧和方法,我们得到了最直接有效的方法。将其作为实际实施的案例,通过它可以为我的公司带来直接的收益。总的来说,之前分析了那么多东西,但是这些东西都无法落地,或者协作效率无法提升,推广应用难度很大。是的,我们可以通过它来实现这四种场景,可以提高大家的效率,辅助开发定位bug。阿里内部有一个视觉质量评分,分为四个维度。第一个是圈复杂度,第二个是面向对象指标,第三个我忘了。每个指标都有因素在里面,每个方面都有一个权重,测试代码后开发,是不是直接关系到代码的质量得分?指标定义好,就能发现问题,指标定义不好,就会闹笑话。bug重复检测,如果我们做crossover,或者比较大,比如我们用外包的方式,从网上免费公开测试的东西,他们提到的bug之后,我们也可以做deduplication,作为以后判断的一个重要指标。bug的自动分配,每个开发提交,根据本场景涉及的case,或者提交一个分支版本,可以直接将bug和创建者关联起来,不需要在某个时候判断是做哪个开发bugoccurs可以看出是这个东西出了问题。然后是案件的等级分类。相信大家在做第四的时候应该都能做到。如果他们不做案例的等级分类,那就意味着连测试都没有做。为什么要提出来?因为我们发现有很多工具也可以帮助我们生成单元测试代码,但是这些单元测试代码和这个没有很强的相关性。大家都知道“8020”法则,80%的bug来自20%的代码,我们所有的case不应该是一个级别的。基于这个理论,我们可以将这20%的代码按案例级别进行分类。越是迭代的版本,开发和测试都在不断维护自己的自动化脚本,包括单元测试脚本。这些东西会慢慢积累起来。此时,第一个版本可以在10分钟内运行。但是跑了半年,或者一年多,这个项目还没死,你会发现测试用例一直在堆。之前跑10分钟,半个小时就可以跑完。现在是时候以空间换时间来看案件的执行情况了。除了用空间换取时间之外,我们还可以使用分层分类的方法来标记这些案例,这样可以使用更少的空间或更少的时间。这是四篇论文。同学们可以上网搜索一下,研究一下哪些可以直接给你实现。今天的分享就到这里。