优品软件培育计划【第七期】—— 基于AI的模型测试在工业界的应用
2021/01/11
优品软件培育计划百场前沿技术系列讲座直播的第七场邀请到的是美国内布拉斯加大学林肯分校计算机科学与工程系博士,全美Top5软件测试实验室计算机哲学博士师江帆。他从模型测试在工业界的使用现状到应用情况分析,深入探讨TestOps的实现路径。现将整场讲座的内容整理出来,供大家继续学习使用。
“模型即代码,模型驱动99%的情况下大家并不需要看到代码。”
“把测试用例的设计,通过搭积木的方式,把不同的流程图组合起来,是组合爆炸的一个方式。”
“45分钟通过搭积木的方式,将100个流程图串起来,串成一个4500行的测试代码。”
首先我们先分析一下国内软件测试的痛点,根据国内18年工业和信息化部的报告,目前国内和全球的自动化测试市场都非常大。全球DevOps(开发运维一体化)正在兴起,TestOps(测试活动一体化)是其中非常关键的一个环节,如果TestOps中各个闭环的环节没有做到自动化或者智能化的话,DevOps也达不到应有的效果。我们分析了一下国内软件测试的一些痛点,我本人是98年毕业,在软件测试行业也有20多年了,刚开始是在中国长城集团,后来又在美国微软,基于在工业界的工作经历和在学术界的学习经历,跟这其中的朋友、专家一起探讨,我们认为国内软件测试有五大痛点:测试人才缺口非常大,国内大学少软件测试专业,社会上短期培训难以满足实际需求国内设置软件测试专业的可能只有北大、清华、南大、浙大这些比较知名的一些院校,更多的高校可能都没有这个专业,这个专业主要是软件工程下面的一个专业,主要培养的是软件测试的一些算法和一些难点。像我目前的博士导师Matthew Dwyer他目前研究的点就是AI和软件测试的结合。缺乏一站式测试活动平台,各种测试活动需要各种工具,甚至没有工具各种测试都有自己的平台,中间的的衔接上是比较匮乏的。大家都知道,比如说性能测试,需要设计发现性能瓶颈的测试用例,这个测试用例本身也是一个功能测试用例,如何在成千上万个功能测试用例中找到、重用相应的测试用例,比如说最长路径或者说使用网络最长、磁盘最多等等这些跟时间效能相关的测试用例。如何去选择、如何去重用,这是功能测试和性能测试之间的一个结合点。目前是缺乏这样的平台,可以使测试用例之间可以相互转换。软件高频发布,目前测试工具无法满足快速发布软件产品需求20多年前,98年我们发布了一款软件,我们是给国税局做软件,基本上是三个月一个周期或者半年一个周期甚至是一年一个周期去进行发版。微软的操作系统也是一年一发版。当时这种较长的发布周期,就可以进行瀑布式的开发,可以进行一个长周期的测试。但是现在软件的高频发布是非常普遍的,各个公司都想尽快把产品推向市场,去抢占市场。
高频发布再加上手工测试,就造成了很多bug就溢出到了市场外面。国外产品垄断开源工具,难使用难维护,价格昂贵及无法本地化定制(HP及IBM工具)(道普云测试平台实现了将LoadRunner、Fortify、WebInspect这三款工具的二次开发,使用更灵活,按需租用,价格大大降低,可添加vx:daopuyun,申请产品试用)
根据这些痛点,我们因此提出了三个中国软件测试的需求。
就像我们刚才说的,各种测试之间的转换。或者说有一个“测试中台”的概念,如果说各个前端伸展到各角度的测试,后面会有一些共享的资源,比如说测试数据、测试的转换。
通用测试工具不但可以测Android、ios也可以测小程序、微信公众号、PC的应用、web应用或者更加复杂的车联网、工业物联网......
基于以上几点,接下来我们就谈一下模型测试以及加入AI的应用是否能够解决这些痛点。
下面这张图我们可以看到有3个步骤,最左边是各种类型的被测软件,中间有一个业务流程图,这个我们就称之为模型,它类似于脑图。有了业务流程图之后,自动化和智能化就体现在代码自动生成和报告自动生成。
接下来我们一下看一下模型驱动平台是如何画业务流程图的,下面演示视频的界面是一个白版,演示的是百度搜索,一个比较简单的业务的描述。可以进行点击操作、输入操作、断言操作,包含了测试的三要素:数据、流程和断言。画的步骤基本上是属于自然语言,代码会自动生成,左边是数据,右边是数据驱动的测试代码。
模型驱动的理念是模型即代码,这个代码本身是可以被隐藏掉的,高级用户可以针对模型去进行修改,模型驱动99%的情况下大家并不需要看到代码。接下来我们一起看一些案例,比如说我们想测试滴滴。左边是一个业务流程图,是一个树型的业务流程图,抽取出一条线放到右上角放大,可以看到这是海外租车的一个流程:自驾租车页面→海外租车页面→去选车页面→选择一辆车页面→基础保险套餐页面。步骤完全是按照自然语言去描述,按照人工测试用例设计的方式把excel或步骤的方式搬到流程图上面。有了这个模型以后,整个的代码就不用去生成、自动去运行,像下面案例所示的,每一个步骤都有一个截图。在谷歌也是每个测试用例对应一个视频,或者一组测试用例对应一个大视频,点击测试用例可以跳转到视频的各个步骤,方便浏览整个测试用例的状态或者debug。针对滴滴这个例子,我们可以看到最后一个截图是点击保险信息,保险信息弹出框本身有一个关闭的按钮但是关闭不了,就造成了整个海外租车流程完成不下去。
从模型驱动的角度我们可以看到,一个业务流程图本身去描述一个复杂的软件,是基本上不可行的。复杂的软件有上万个测试用例,我在微软的时候待过几个组,像ERP组,至少也有上万个测试用例。一万个测试用例或者一万个行为描述到一张图上面,必然是很密集,很多时候也设计不好。因此我们提出了一个像“搭积木”一样的思路,由简化繁,把测试用例的设计,通过搭积木的方式,把不同的流程图组合起来,是组合爆炸的一个方式。
大家可以假设一个场景,用户登录,登录之后去借钱,去借钱本身有两个行为,去借钱的时候有没有设置好银行卡号,如果设置好了是一个流程,没设置好银行卡号是另外一个流程,登录的话可以通过用户名密码、通过手机短信、通过微信扫码的方式去登录。登录的3个行为和借钱的两个行为如果去组合一下的话,2×3是6个行为,如果去录制,这6块是非常重要的点。模型驱动的话,本身是有模型和一些语义在里面,有一些数据算法可以直接去应用。比如说我们刚才说的,可以自动组合爆炸。上面举的这个例子一个是两个行为,一个是三个行为,我们画图的时候只需要画5个行为,2+3是加法,它会自动组合出来6个行为。这个就是一个质变,“无中生有”,因为模型的存在,计算机可以构建出一个新的测试用例,一个我们没有想到的测试用例。比如说我们有个测试有10个模块,每个模块有2个行为,组合到一块的话 ,就会瞬间生成1000个组合出来的行为,设计出来非常复杂的,非常长的,数量也非常多的测试用例。这就是由于模型驱动的存在带来的好处,录制的话是1000个测试用例需要录1000次,通过模型驱动,即使要录制,也是只需要录制每一个小的模块的行为,各个小的模块的行为录制好以后,通过搭积木的方式就自动组件出来了。
这是我认为模型驱动做测试非常重要的一个价值所在。在这个视频案例的最后,我们可以看到代码也是可以自动生成的,我们有一个案例是45分钟通过搭积木的方式,将100个流程图串起来,串成一个4500行的测试代码。一个测试用例有4500行,整个运行时间有45分钟,通过IE去运行。搭积木的方式适合于各种平台,尤其是适合于复杂的软件。如果你的软件复杂度特别低,或者不是用来赚钱的,只是用来展示静态的一些东西的话,测试用例非常少,就不需要搭模型这种额外的工作量。但是如果软件非常复杂,重复度非常高,就非常有必要通过搭模型的方式去沉淀、去做一些回归。最后给大家介绍一个搭积木测试混合应用的案例,这是一个澳门美团由卖家接单app、用户点餐app、骑手送单app,再就是还有一个后台调度的Web应用,通过搭积木的方式,一个测试用例就直接运行了。
这是模型驱动,目前我们认为模型驱动具有很多的优势,另一个最新的技术那就非AI莫属了。AI在目前国内测试圈里,也是有很多应用,OCR是很标准的一个AI应用。OCR是做文字识别,有些是图标,没有文字,就通过 Mobilenet, 是tensorflow的一个更具体的针对与轻量级的app的训练深度学习的框架。这样的话,像支付宝的好多设计,icon的设计、图标的设计,打上“支付宝”这三个字的标签,有了这个语义以后,在测试用例里面,我们就可以直接用汉字“支付宝”这三个字去定位到整个icon或者图标。
定位功能在自动化测试里面是非常重要、非常核心的。尤其是在前端经常修改的情况下,如何使得定位的方式更智能、更自适应。这也是AI在某种程度上能够适应软件变化的一个方式。另外一个是多个页面场景的测试,这个是比较关键的,也是非常重要的。比如说携程的订飞机票和去哪儿的订飞机票非常相似,如果把携程的订飞机票测试用例学习好了,AI学会了,应用到去哪儿的订飞机票,就不用写了,因为AI已经学会了,它知道在这个页面或者出发地、目的地填什么内容,内容在某种程度上我们可以去提供,但是整体的流程它会自动去操作。整个场景的AI化在未来具有非常大的前景。这个可以和模型驱动非常好地结合起来,因为模型驱动本身是结构化的数据,AI学习起来就会比非结构化的内容要快。这是从AI的角度上能够把我们刚才提出来的流程图、积木图AI化了。AI化的意思就是把流程图都消掉了,比如说“登录”,这是非常通用的,不管是web页面还是app,所有的软件都有登录,几乎都是一样的,非常简单,就是输入用户名、密码再去登录。通过AI的学习,非常简短的流程、非常简单的操作,可以作为一个通用的流程放在里面。大家通过拖拉拽的方式组建出自己的测试代码。甚至很多行业内的代码也可以通过AI学习出来进行行业内的共享。
我们有个客户,是top3的支付平台,也想做UI的自动化测试,但是维护成本非常高,因为现在的软件迭代速度非常快,通过模型驱动,可以发现,维护成本就是在某一个流程图。一个流程图可能在上百个模型中被用到,但是维护的的时候就只需要维护一个流程图OK了。可维护性、可读性;元素中心、数据中心、各种可视化的模型测试平台使得维护变得非常容易。还有一些更容易维护的录制工具、记录工具把之前的一些元素、流程给覆盖掉,就维护好了。某家地铁IOS上线,通过人员去开发测试用例进度缓慢,通过模型驱动的模式,在7天内就可以达到127条自动化测试用例的开发和调试。而且都是小白用户,不会开发代码,是个手工测试人员,模型测试非常方便于这90%的群体。这也是从手工测试人员转变成自动化测试人员的一种方式,通过工具来实现自己角色的转变。我们刚才提到的DevOps里面有一个环节叫TestOps,TestOps本身自成一个体系,什么是TestOps?他的内容包含什么?我们也提出了自己的看法,供业内人士去探讨。TestOps我们认为有六大模块,第一个模块是AI系统,软件测试代码自动化生成。目标有很多测试代码,比如说接口测试、功能测试,辅助于AI代码去进行一些测试代码的自动生成,生成一些自适应的一些测试代码。再就是被测软件的隔离(龙测Mocking),一个软件,尤其是复杂系统的软件,比如说电力系统、银行系统、电信系统,复杂系统都是由各个子系统组建的,一个子系统有可能是A公司开发的,另一个子系统有可能是B公司开发的,AB之间的交互基本上都是通过接口,有的时候是通过后台数据的共享。A系统的数据状态改变了,造成了B系统可以现在测,因为他的数据是从A系统流过来的,有数据依赖,有时候也有控制依赖。这样测试的即时性就不高,因为我不可以随时测。隔离本身也可以叫做挡板,就是为了把软件隔离开来,使得它随时可以测。另外,隔离开来之后,你测出的bug就是这个软件本身的bug,没有任何理由去赖到别的系统上去。有了测试代码了,也有了被测软件的隔离了,需要运行在硬件上面,现在的硬件比二十多年前多多了,二十年前可能有PC机,有服务器,操作系统有Linux、各种的Windows等等,现在的话有手机、有Android、有Ios,现在还有智能家居、智能汽车、pos机等等,要运行的话都是要在这些系统上去运行,因此整个系统的硬件需要自成一个体系,能够一站式地创建出来。在大的公司,比如说微软,在ERP组甚至整个微软内部是有一套硬件系统的。现在也有叫云端系统、云计算中心等等,云计算本身可能更偏向于PC机或服务器,这块是非常大的一个管理体系。一个TestOps平台,至少是要具备这三块,测试代码的自动化生成、被测软件的自动化隔离、测试硬件的自动化准备。有了这三块之后,在内部做CI/CD,做自动化的测试是没有任何问题的。在产品的发布以后,我们会看到一个持续的监控(龙测Monitor),还有一个更前沿一点的软件bug自动修复(龙测Repair)。目前为止在业内99%的开发组、或者产品组,bug本身是由测试组去发现,递交到bug管理系统,由产品经理、开发经理和测试经理一块把bug赋给某个开发人员,让他去修复。但是bug不一定非要开发人员去修复,这也是软件bug自动修复本身的意义所在。像北大的教授开发出来的一些工具,在开发代码的时候,有一些自动推荐,代码敲到一半的时候,后面的代码会自动推荐出来,使得写代码变得简便很多。之前VB、Java等会把一些包里面的类,类里面的一些方法给你提示出来。现在不光是这些,还有一些非常通用的代码、整合的模块会提供出来。
这是写代码,同样的在修复bug的时候,我所了解的至少有两种技术可以做到bug的自动修复,一种技术是符号执行,叫Symbolic Execution,这个是在NASA或者一些形式化验证的方式的软件中使用,一些非常复杂的软件、一些高可用性、高可保障性的软件,需要大量的形式化的测试。大部分的形式化的测试都是在模型上面,或者状态机上面,或者抽象的对软件的描述上面,进行一些推测,进行一些属性的描述,进行一些类似于数学,但是还没到数学那么深的,一些逻辑上的一些推测,展示出来在整个的系统内部或者模型上面是不是有问题,这是比较抽象的层面。在实现层面上,我们开发人员用的是Java或者Python或者C++等等,符号执行也可以在语言级别,有NASA的Java PathFinder,国内也有一些工具。这个方式可以做一些非常有用的测试,比如说可以做一个从入口全面的扫描,然后去分析。代码开发完整个行为也就描述出来了,在符号执行的基础上把行为展示出来。通过一些if语句的串联去收集。if语句有可能条件是ture的,有可能条件是false的。如果是ture的说明路径从刚开始入口到这个点是可以达到的,ture的同时也反映出来所有的条件本身都符合,条件本身在代码级别是由很多变量组成的,变量是由不同的类别组成的,这些变量本身,一旦返回一个ture或者false的时候,还会返回一个中间值,不确定。这个问题在计算机界叫NPComplete,是非常难的一个问题。一般这种问题都是通过指数级的方式或者最笨的一种方式去解决,没有一种聪明的方式可以快速地解决。一旦返回ture或false就说明,整个变量是有一个赋值,这个赋值正好是我们所需要的,从入口处所需要的测试数据,这个测试数据是指哪打哪,路径一旦找到,条件一旦积累起来,返回ture同时返回一个数据,这个数据就是所需要的测试数据。这个技术本身是非常好的一个技术。它正好是在整个的if条件里面,从刚开始的if条件到下面的if条件的一些串联,所以对if条件本身是敏感的。比如说a>b,如果a>b本身产生一个bug了,那么它试着去a<=b,它就会尝试以这种方式去修复。另外一种bug的自动修复方式叫做AI的机器学习,因为目前我们也知道,像github这种测试代码库,还有很多开源的测试代码库,里面有很多bug描述也有很多相应的代码片段,这种就是通过bug的描述和提交的代码的关联进行一个大量的学习。在某种程序上,当提交一个bug的时候,可以提示以前是怎么修复的,我们应该怎么修复,推荐一些修复方式。这种在facebook、在学术界、工业界都有相应的应用。在TestOps平台我们也想把测试活动一体化的本身扩展一些,不光局限在发现bug,我们还要去修复bug。这也是一个目标。
另外一个就是Pipeline,把这几块整合起来,不管是数据流也好,控制流也好,都控制好,使得被测软件能够被一键化地被测试。以上就是我们认为的整个TestOps的整体机构。
下期直播将在下周二(11月19日)举行,由Micro Focus资深技术顾问陈学锋为大家带来《敏捷测试-回归本质》讲座,他从业18年,在开发,测试,项目管理和运维领域都有丰富的理论和实践经验。对DevOps和Agile有深刻的认识。具体直播信息将在直播前通过微信公众号或社群进行通知,请大家随时关注。