2019年10月26日,由Testin主办的第二届NCTS中国云测试行业峰会在京召开,此次峰会以“AI+未来”为主题,汇聚来自国内外测试领域的知名专家学者、领先企业决策者、高层技术管理者、媒体从业者等,共同探讨高端云测试技术,帮助测试从业者了解最前沿行业趋势,及最新的行业实践。
会上,京东物流资深测试开发工程师樊宇做《如何让配送地址更准确——带你走近京东物流大数据算法测试探索之路》主题演讲。樊宇指出,“做算法测试,首先要建立算法测试模型,然后获得真实有效的历史数据,再完成算法相关接口的调用,最后,改进我们的测试过程。”
以下为樊宇演讲实录:
大家好,我先自我介绍一下,我来自京东物流,我在2013年加入京东,我们大数据算法测试大概是2016年底,2017年初逐渐开始的。我们最开始也做一些自动化测试,UI自动化,接口自动化,自动化测试工具平台,还有数据集成。今天我给大家分享大数据算法方面的测试。
先介绍一下目录,第一部分是项目背景,第二部分是算法模型建立,第三部分是测试数据的获取,第四是算法测试执行过程,然后是总结,主要分这么几部分。
首先我介绍一下技术背景,京东快递从去年年底逐渐开始支持微信小程序下单了,原来京东只是能送快件,现在还可以上门取,所以说在微信小程序里面增加了这么一个功能叫做“京东快递”,小程序界面当中做了自动提取关键字的算法,可以把整个地址都复制到微信小程序里,然后会把地址信息,电话、通讯录提取出来,这个过程可以减少人工输入的过程,提高我们的用户体验,因为大家的地址都是共享的,比如从一个应用复制出来放在另外一个应用,这样就很方便。
这里有一个截图,这是我们系统的界面,就是你输入一个地址后下面自动把姓名、电话和详细地址都提取出来,这个是我们的项目背景。
再说一下算法模型的建立,前面介绍我讲的比较快,这部分讲慢一点。我们想象一下,配送地址是很长的字符,S2、S2一直到S7,就是一级地址,二级地址,S6是姓名S7是电话。这个模型如何建立呢?
算法测试很多时候要建立模型,左侧这部分是经常用到的算法测试的模型,比如说第一个是准确率,召回率,大家如果做搜索相关测试都会了解一些,大家知道准确率、召回率就是一个真值表。例如期望为真,实际为真与期望为假;实际为假的这个统计是准确率的情况。召回率就是我期望结果是假,但实际上结果是真和期望结果为真,实际结果为真的情形,就是说有一部分的结果都是真值的情况,这个就是召回率。下一部分的概率,很多算法是用概率衡量的,最后一部分是余弦相似度,这在很多算法测试当中用的多一些,因为余弦相似度是衡量高倍向量结果,这会有很多维度,我们衡量两个向量之间的差异多半是用余弦相似度比较,当然不限于文本的比较,其他的也是可以的。
既然是算法模型,我们就要考虑一下分子是什么?分母是什么?我们回头看一下左侧这四个统计模型,他们结果都有一个特点,就是0到1之间的一个数,我们想象一下我们的分子如何构建?分母如何构建?
我们再回到刚才讲的技术背景,我们被测算法应用其实是跨领域的,用现在经常说的新词就是跨界,一个是自然语言处理,另外是地理位置服务,这就和一般的算法测试不太一样,是跨的这两个领域的界限。大家都知道跨界这种东西一般是有难度的,可能和我们平时测试差别比较大一些。
最开始,我们会拿到用户的是一个地址,这个地址我们可以认为是测试的最开始数据,地址有两部分,第一个地址就是寄件地址,第二个是收件地址,功能测试角度来讲,我们可以把地址颠倒过来,收件地址作为寄件地址也可以,这样可以增加测试覆盖率,下一步就是涉及到地理编码的概念,大家如果知道LBS测试功能,应该知道地理编码的概念,一个是正向地理编码还有一个是逆向。正向地理编码就是我给你一个地址街道门牌号会生成经纬度坐标,另外一个是给你一个经纬度坐标,给你一个最近的地址,我们会对这两个作为一个地理编码的计算。然后会得到对应的坐标,根据坐标我们可以算一下距离,大家应该知道距离也可以用最简单方式,就是算两点之间的距离,我们用的也是这种方式,相对来讲这种模型比较简单。
但是我们要衡量转换以后坐标是不是准确度,或者说原来的地址转化是不是有问题,如果地址转化差就会有差别,距离就会达到几千米甚至说十几公里的距离,所以我们转化计算距离会计算阈值,低于这个阈值就是可接受的。
我们再继续,我们会统计计算正确转换的地址数量,就是说有多少地址是转换正确的,这个就是我们刚才说的分母,我们还会做一些过滤,就是说计算匹配范围内的地址转换错误的地址数量。因为我们刚开始做的时候,京东配送不是全国都支持,现在都是全国支持了,当时只是北京、上海等部分地区支持,所以超出范围不会被支持,所以我们要把这部分数据排除掉。最后我们再看一下这个数据,我们相当于用召回率统计的,看一下地址的转换有多少东西是有问题的,这个就是我们的算法模型的建立过程。
算法测试很多时候和我们的功能测试不太一样,功能测试都是自己造的数据,比如说订单数据,一些商家的数据还有一些其他的数据,或者说用一些开发给定的原形中的数据。但是算法测试很多时候是用线上历史数据做的,因此我们就会涉及到第三部分的内容,就是测试数据的获取与提取。
这个PPT大家看的不是太清楚,第一框架是“历史数据”,左侧是“运单数据”,中间这个框是“小程序日志数据”,最后一部分就是配送员PDA日志。因为我们有配送运单数据,我们会把运单数据里所有有效的地址都拿出来,运单里就我刚才说的有两个地址,一个是配送的收件地址,一个是取件地址,然后因为我们已经妥投的,地址肯定是有效的,当然这个数据并不是我们小程序里面的,这是京东里原来的一些历史数据。然后我们再说PDA这部分,它收集同用户在较小时间内地址变更的行为情况。为什么说是同一段时间内较小时间呢?就是用户输入地址可能输入的时候是输入错了,大家会想到的一种情况,本来是家的地址,但是实际上想输入公司的,输入以后就直接改了这个时间间隔会比较小一些,我们设定一个时间间隔,比如,一个小时或者两个小时之内变更的地址。
还有变更行为可能意味着前面的地址是输入错的,这块我们都会作为一个输入数据。最后一部分是配送员PDA日志数据,配送的时候也会有一个经纬度坐标的定位,我们会取这个经纬度坐标去作为我们用户的输入,我需要再强调一下,配送员取件的时候也有异常数据,比如说用户下单下错了,本来应该是往A地址发,结果下的是B地址,这时候会给配送人员打电话,让他往B地址取件,这时候PDA有变更记录,配送员送件时也会产生上述类似的行为,我们会把变更记录拿过来作为我们输入数据。
我们实践过程当中拿用户的地址数据是相对来讲比较复杂的,我们再考虑中间遇到的新问题,如何对新地址进行地址转换,前面的S当中的地址来进行片段,这个其实和我们经常用探索性测试很类似,大家想探索性测试属于原有工程基础上发现有没有潜在问题,因为很多时候,最开始时候我们测试没有介入之前都是开发根据以前的用户反映到的问题找一些问题,发现一个解决一个,这样效率比较低,体验不是特别好。因此我们最主要的一点就是对新地址做一个处理,大家可以想像,我们看一下新地址的来源实际上有两个来源,第一个来源是新配送区域,假设我所在城市原来是京东上门取件是不支持的但是现在支持了,这就属于新的配送区域。还有一个情况更长更复杂一些,这个配送区域是支持的,但是新增了地址,比如我所在区域,北京朝阳区是支持的,但是这块新修了一个小区,小区是新的,这就属于后一种情况,大家可以想一下这个问题如何解决。
这是我们这次讲的最核心内容,就是生成一个新坐标的情况,我们其实是用这种极坐标解决这个问题的。大家上学时候可能记得极坐标概念,这和传统的笛卡儿坐标不一样,一个坐标代表距离,一个坐标代表角度。我们把用户所有的地址进行聚类,聚类以后我们会把簇的质点做为圆心,我们会用两重循环去生成一个新地址,然后再过滤一下,用这些地址得到可配送地址,因为有时候逆地址生成的不是可配送的,比如是某一个街道交叉路口或者公交车站,我们要把这些过滤掉然后做一个去重,比如,一个小区方圆几公里,会把这个去重。小区我们测试时候会精确到每一个楼,并不需要精确到单元和楼层,因为这个对于地址来讲其实是一样的。
这部分是我们讲的比较重要的一部分,就是算法测试执行的过程。首先,先获得历史数据,把历史地址和坐标都拿出来,然后,进行地理编码,根据地理编码后进行计算坐标聚类,最后有效去重,去重以后做逆地理编码计算,再生成一个新坐标,蓝色这部分严格来讲对于我们其他测试都属于测试的准备阶段,就是造数据,但是我们的数据是根据真实数据生成的。我们看右半部分,这个其实是我们实际测试执行的过程,我们会把这个地址作为分词,我们会增加噪点和冗余信息,比如,增加姓名和电话,然后,调地址识别和转换的接口,比较预期值,再根据预期值生成地理编码,再比较我们的距离,如果这个距离大余阈值就有问题,如果小于阈值就是没有问题的,这个就是我们整个测试过程的执行。
重点说一下中间的过程,比如聚类这块我讲一下,大家如果对法测试有所了解应该会知道,比如常见聚类就是均值聚类,我们用的并不是均值聚类,因为数据量比较大。结合业务特点,京东配送站有一个经纬度坐标,我们以这个经纬度坐标作为初始簇点。然后以这个半径范围内的坐标划簇,如果这个坐标达不到簇内数据量的要求,就把两个配送站地址作为合并。如果说达到我们的要求,比如说我们这个簇要求一万个座标点,如果超过一万个我们就终止,聚类就结束了,然后按照簇的元素从大到小排序取前N个值,最后按照质点生成极坐标,这就是我们聚类的过程。
地址转化算法是算法类测试,那如何提供类似缺陷列表的内容?大家想我做一个功能测试,不管手工测试还是自动化测试,测试完一轮都会产生一些Bug,我们提到缺陷管理系统,但是我们算法测试,可能最后只是一个数,比如召回率是80%或者90%,但是没有缺陷的这种,对于一般来讲产品、开发和测试本身就觉得不是特别喜欢,我们怎么提供这种类似于缺陷列表的功能呢?我们看一下是如何做的,取这些历史记录当中出现最多的前N个坐标对应的地址,然后取距离较大的前M个,这前M坐标肯定大于阈值的,然后我们在前N个当中选取前M个出现的地址,这就相当于一个TOP N的问题。我们会和工程师做核实,如果有问题,就作为缺陷贴到缺陷系统里或者直接发个邮件附带一个表格,因为有的缺陷比较多,一轮测试发现几百个,然后提供给开发,开发根据缺陷列表看是程序问题还是数据问题还是其他的配置导致的问题。这样的话比只是召回率通过不通过好,有一定说服力。
再看一下另外一个问题,如何生成入参,后台是一个接口,输入一个地址反馈S1到SN的地址,如果我们增加一个噪点呢?我们是这么做的,假如我这里有一个地址,北京市丰台区樊羊路多少多少号,为什么去这里呢?这里有一个坑稍候给大家讲。我们做一个分词,北京市/丰台区/樊羊路这么分。因为我自己姓樊就可以把我姓名加进去,就都是黄色,樊羊路后面多少号,樊宇再加上我手机号,这个模拟一个用户真实收件地址或者取件地址,判断这个系统,因为都是樊,但立义不一样,一个是街道,一个是姓,这就是增加了一种测试噪点。还有一种情况,把这个位置颠倒过来,姓名完了直接是手机号,最后输入门牌号,因为我们看日志情况也有这种情况,就是顺序不一样是规定的,我们会把这个颠倒顺序,这样的话也会产生一定噪点。
最后这部分噪点,我们对应着一个写字楼或者小区,我们就把这些具体地址换成一个小区多少多少号楼,用户很多时候也会用这种寄件,实际上都是一个地址,但表现形式不一样,最后用这种形式替换。大家可以看一下有黄色字部分都相当于增加的噪点,这样就可以增加我们转化率测试的覆盖率情况了,就可以更好发现转换的算法存在的潜在问题。其实我们做的方法就是把街道当中一些涉及到姓氏提取出来,然后根据姓氏随机生成一些名字。
如何加速我们测试执行的过程呢?这块我们用了并行的一些计算,因为我们用并行计算还有一个原因,地理编码这种运算,逆地理编码运算会很长,一个地址逆地理编码大概需要几百毫秒时间,累积出来会很多,所以我们用并行计算,读取历史数据,信息不全这些都放在缓存里,地址可能有重复的,有缓存的话我们不用调接口,直接在缓存当中拿数据,可以放在数据库等地方,最后我们进行召回率的计算来得到我们所需要的结果,这样就可以加速执行、调试过程中就执行一两条就可以了,实际跑的时候用并行计算跑的。
最后我们再给大家介绍算法测试方法论,这个是我们团队的理解,一般任何算法测试首先需要建立一个算法测试模型,像我们这个用的是召回率计算的,其他的可能召回率不合适,就得用余弦相似度。第二部分我们获得历史数据,这是真实有效数据,用它做回归测试可以反映出有算法和没有算法情况的前后对比。第三部分是算法相关接口,但是有些算法可能调其他的周边接口,上下游接口可能都会有,就需要大家有这方面考虑。最后一部分是改进我们的测试过程,我们刚才讲的如何生成新坐标就是我们的一个改进过程,这也是一种创新,还有一个是如何增加噪点,这种都属于改进我们的测试过程。
这部分就给大家一个介绍,很多公司我想都要开始,或者逐渐想从事这种算法测试,算法测试究竟需要哪些方面的基础?我给大家简单做了总结,第一部分就是要有数学基础,我们这个案例当中涉及到的极坐标,距离等等都是属于数学方面技术。你可能对开发算法不一定了解,这是一个纯黑核,但是对自己的算法是需要有了解的,这就是建立算法模型,召回率计算,分母分子如何取都是需要考虑的。第三部分,自动化接口测试,我想很多团队都有这个能力,因为接口比较快,基本上不会涉及到UI,都是通过接口触发实际测试还有数据获取的。第四部分是并行计算能力,大家可能需要多线程,多进程,分布式计算能力来提高测试速度。因为你不可能说一个测试跑一天还没有跑完,因为开发很多需要等着上线的。还有一个是需要我们有数据挖掘的能力,就是我测试的这个东西需要从哪里获取数据,我要转换成什么样的数据,这个是需要知道的。最后一部分我个人觉得所有的测试都需要掌握的一个东西,就是业务场景,不同业务场景的测试重点是不一样的,导致我们用的一些算法模型,还有一些结果都会有一些差距。以上这几点就是算法测试给大家的一些期望。
最后一部分,对未来做一个展望,因为我们现在是在线下做的测试,因此未来我们要做一个线上测试环境,就是把它完全放在线上采用我们的CI/CD,数据集成的方式去做,做完这个我们准备在运营期间,超区的测试,因为现在京东配送基本上已经支持全国,但是有超区情况,超区就意味着分配是有问题的,本来是很近的,但是分配早几公里之外的站点,这会导致运营效率会降低。我们会做京东第三方地址转化测试,把它作为取件地址去做。因为京东物流也会接触到很多商家,商家那种实际上都属于第三方地址。
最后两部分,就是非内地的,就是国外地址,因为京东物流有很多国际化的业务,因为国外地址和国内不一样,因为很多都是英文,分子系统和咱们也不一样,这块以后都需要介入的。最后一部分就是我们准备降低一下我们人工识别的比重,因为现在我们很多东西还是人工识别的,有时候可能计算阈值很大,但是实际上情况可能是正常的,比如有一条河,河上有几个桥,要过河取件肯定要过桥,过桥距离就会长,这时候就需要人工识别,我们以后会通过其他手段降低人工识别的难度。
以上就是我给大家做的分享。