从入职到如今已经有3个多月了,从最初的对于电商广告业务和算法测试的一头雾水,到如今的渐渐了解,基本上已经能够胜任项目的常规质量保障任务。然而,目前的质量保障手段依然停留在手工测试层面,自动化相对来讲依然是比较空白。git
关于持续集成和自动化,早已不是新鲜的话题。可是搜了下内网上关于自动化的一些话题,发现最近的一些文章仍是有很多关于自动化价值的讨论,我以为自动化测试其实跟任何一种其它测试类型(包括功能测试、异常测试、性能测试、稳定性测试等)同样,它自己属于测试范畴的一种。既然是测试,咱们首先要明白的是“测试需求”是什么。盲目地为了自动化而自动化,致使自动化使用姿式不当或者目标不明确,甚至不知道痛点在哪,是没法将自动化作好的。github
以前在TesterHome发表过一篇关于自动化的文章《我对自动化测试的一些认识》,可能随着当前行业测试技术的快速发展,有一些技术手段已经有些陈旧,可是其中的大部分观点至少到目前为止与当前本身的思想仍是比较一致的。欢迎有兴趣的测试同窗一块儿探讨,对不足之处进行指正批评。web
目前我负责的是广告算法的质量保障工做,测试开发比将近1:20,按目前的状况来看,开发数量还有增大的趋势。整个团队并行在推动的项目可能在10个左右,整体来讲测试资源很是紧张。算法
一方面,做为一个测试开发同窗,在兼顾业务保障的同时,每每还须要保障多个组内外平台及工具的开发或者其余流程沟通推进的相关工做。另外一方面,咱们的开发同窗其实都有较高的质量意识,有强烈的自测诉求,可是缺少高效的自测手段。数据库
所以,如何将项目测试过程固化沉淀、造成自动化保障体系,赋能开发自测,释放测试本身的资源,是当前不得不进行的一个事情。apache
算法由于其自身的特殊性,大部分广告算法其实是对已有算法的改进和结合,涉及的技术包括点击率预估、搜索、推荐、图、NLP、图像等。以搜索广告为例,在流量变现方面,它的主要优化方向集中在两个方面:排序(点击率预估、出价优化)和匹配(召回、相关性)。从工程的角度来看,大部分项目对工程结果的影响是广告商品的排序不一样或是召回商品的内容和数量变化。不一样于传统的网站应用/工程测试(可能会有不断的新功能的产出),相对来讲,若是抛开算法效果测试来看,在功能层面,算法的工程结果是比较稳定的。框架
算法的开发主要包含两部分:离线任务开发和在线工程开发。离线任务开发包括数据分析、业务建模、特征提取、模型训练、模型调参等。在线工程开发主要是将算法模型服务化,以接口的形式提供给外部去调用。从集成测试的角度来看,算法的功能测试能够归为“接口测试”的范畴。工具
传统的接口测试,除了校验接口的返回状态码是否正确外,比较容易根据业务的处理逻辑对返回的结果字段进行校验。好比查询类的get接口,咱们能够经过接口的返回结果与数据库的结果进行比较;好比提交类的post接口,咱们也能够经过调用接口,根据传入的参数的不一样,结合对系统的不一样处理逻辑的了解以及数据库获得一个肯定的预期返回。post
与之相对的,算法的接口没有一个肯定的预期。同一个接口,传入彻底相同的参数,在不一样的时间段调用可能会返回不一样的结果。由于不少时候,算法的接口返回是一个几率值,如“某个商品被某个用户点击的几率”,影响算法返回结果的因素,除了服务代码以外,还包括索引的版本、特征词典的版本。特征词典的版本每每是日更新,而索引包含日级别的全量更新和实时的增量更新。虽然算法的功能相对稳定,可是算法的不断调整,其实是对同一批接口的不断调整。性能
目前算法工程质量的保障,主要仍是集中在在线部分的测试。离线部分由于其时效性,每每会有T-一、T-2的延迟,更多的采用监控保证其质量。而对于在线部分的测试,主要的保障方式包括:
线上请求日志回放主要是基于线上的access_log日志,分别在新版本的环境和base环境进行请求回放,比较返回结果各个字段值的差别。是一种对功能验证的补充,避免人为地构造数据可能没法覆盖线上的全部场景。
前面说了,当前算法自动化测试的目标主要是想解决工程测试方面的效率问题,释放测试在工程质量保障方面的人力投入,所以本文主要是针对算法的“工程”测试自动化方面的一些思考。
理想的自动化测试链路应该是:
整条链路的回归时间控制在一个小时之内,过程当中既有中间测试结果的即时透出,也有最终报告的展示。下面是对于自动化测试链路的各个环节存在的一些挑战的思考:
目前的开发代码大部分都是用git去管理,可是并无一个明确且严格遵照的代码分支管理策略,且没有打Tag的习惯。算法和引擎开发同窗有不一样的开发习惯:
从测试的角度来看,这两种都存在一些问题:
在分支管理上不妨能够参考一些优秀开源项目(如 apache/spark、apache/flink、tensorflow/tensorflow等)的广泛作法:
静态代码检查是一项低投入高回报的工程,从集团推出Java开发规约可见其重要性。“低投入”是由于只要一次配置,能够无限次的检查。“高回报”是它不只能够帮咱们纠正代码书写规范的一些问题,还能够发现一些诸如“空指针异常”、“I/O及数据库链接资源使用后未关闭”、“冗余变量”等一些重大的工程风险。
对于Java,有集团规约插件、PMD、CheckStyle、FindBugs等能够很方便地使用,而算法的开发则大可能是使用C++,相应的静态代码检查工具还须要调研。目前了解到的有cppcheck、clint等。
目前RS服务已经使用了Google C++单元测试框架“Gtest”进行单元测试的编写,可是还处于刚刚起步状态,这部分须要去推进开发好好地补充测试用例,给出单元测试的覆盖状况统计,不让单测仅仅是流于形式。后续须要将单测的经过率和覆盖率数据透出到报告中。
不一样于Java工程,基于Maven或Gradle,能够经过命令行很方便地实现整个工程“一键编译打包”,并且目前集团的Java应用大都已经能够基于Aone平台很方便地发布。而算法的发布由于其索引和词典的特殊存在,没法经过Aone很好地集成。算法包的发布包含三块内容:so文件(代码编译后的结果)、conf(配置)、data(词典),过程一般包含RPM打包和词典更新两个步骤,其中RPM包会包含so文件、conf和部分data。目前不一样算法模块发布的平台各异,包括suez、drogo、autoweb等等,如何去规整并实现测试环境的自动发布是一项挑战。同时,在环境部署完毕后,咱们还要保证新版本环境和base环境索引的一致性,或者当索引的构建也发生改变时,须要保证构建索引的商品库的一致性。
这一块须要对每一个算法服务的使用场景进行具体的分析和细致的梳理,好比RS服务,它有来自bp、rsproxy、dump、rspe等不一样的调用方的请求,每一个调用方的可能的使用场景都须要一一梳理,从而提取出必要的冒烟接口测试用例。前面提到过算法接口每次调用的返回值可能会变化,
所以这部分用例的意义在于检测服务接口是否针对各个场景有正常的返回,返回结果的各个字段的值是否在一个合理范围内。
相比人为地构造数据,和AB切流实验,线上日志回放是一项相对覆盖面广且高效低成本的方式,经过自动化地回放大量的日志请求,咱们能够发现新的算法版本是否对某一些不应产生变化的结果字段产生了影响,也能够发现一部分算法的效果问题:如出价优化时,总体价格是调高了仍是调低了。
Java中有成熟的Jacoco能够用于工程覆盖率(深刻到行、方法、类等不一样级别)的统计,结合git的diff日志,还能够去挖掘工程两个不一样版本间变化的代码的覆盖状况。而C++的覆盖率统计方式仍须要调研。
性能压测包括模块压测和集成压测。模块压测指的是如RS这样单个服务的压测,而集成压测是从ha3端或者SP端去看总体性能的状况。一般,性能的测试都是须要有必定经验的测试人员基于测试分析来制定详细的压测方案并予以执行和结构分析。可是,以前提过,算法的项目发布有很大的共性,正是基于这些共性,使得自动化压测成为了可能。要实现自动化地压测,除了要编写通用的压测脚本,还要有稳定的施压环境做为持续集成的节点机器。同时还须要去实现自动化地采集被压环境的系统性能变化数据(如cpu、内存、磁盘i/o、网卡性能等)。
要实现最终报告的自动化生成,须要涉及到整条链路的各个环节数据的自动采集,以及各项数据呈现和报表的展现,透出和提炼出对研发过程有帮助的数据,给出相应地测试结论。
以上是我的对于算法工程质量保障的一些小小的想法,目的是将本身从“项目轮流转”的现状中解放出来。整条链路看似冗长,可是罗马不是一天建成的,我相信只要朝着正确的方向前进,自动化的效果会一步步地显现出来。