文章起源:本文节选自 TesterHome 社区爱好者合力编写的《2021 接口测试白皮书》。
接口回归测试面临的问题
迭代状态及组织变动
迭代放慢
在当今的互联网行业的状态背景下,产品需要迭代都更加地谋求疾速交付流动,大部分公司都采纳精益产品研发流程,那么在之家经销商 bu 外部,咱们近 2 年的均匀需要交付工夫≈4 天,而潜在的问题是,因为原自动化接口测试的开发 / 保护老本较高已追不上迭代,咱们大部分的回归测试是被跳过的,更多要依赖开发人员程度 + 测试人员教训,所以一旦惯例的节奏被突破(紧急需要插入、人员状态、人员变动等),回归缺失的问题就会裸露进去,而这种外来变动其实也越来越频繁。
我的项目 / 人员变更
随着公司外部布局的各种变动,也会产生一些我的项目交接 / 重组,或人员
转组的状况,个别在业务上会有一波新的改版,而后端接口技术上也会进行重构。但因为刚刚交接,产品、测试、开发都不会十分相熟原有零碎,传统回归测试伎俩,因为无奈确定预期很难进行。
技术演进
另外随着技术的一直演进,给日常接口回归测试也带来了多元角度的影响:
- 架构或利用外部代码的演进重构的过程自身(容器化、接口合并 /
拆分 / 优化、数据源迁表 / 迁 ES……),须要回归验证撑持。 - 服务节点多,只改了 1 个服务几行代码,可能须要验证所有调用方。
- 服务链条长,跨 BU/ 服务调用多,通过 Mock 单服务测试不能独善其
身,集成 / 联调测试阶段问题多。 - 服务性能类型增多,技术类型需要增多,应用传统回归验证形式效率低,成果差。
解决方案剖析
接口自动化 vs 流量回放
在前述背景下,咱们引入了新的流量回放形式来进行接口回归来解决上述问题,应用上一个版本的响应状况作为基准,默认是正确的,而后与新版本的状况做比照,查看差别项是否为预期内。相比原有的接口自动化测试,这种测试形式的收益比要更高。
整体计划
开源计划
过后的流量回放计划大略有 2 种,原理能够简述为:
• 基于 HTTP 接口纯黑盒的回放,如 Diffy。
拉取线上流量申请信息后,在部署了不同版本代码的 2 套测试环境进行 Http
接口的调用回放,实时或离线的比对接口的 response 响应的区别是否合乎预期,来进行测试。代表的有 twitter 的 diffy 工具
• 基于代码办法级别的回放及验证,如 Repeater
回放思路雷同,但基于代码办法级别的录制和回放验证,个别将查询数据库等操作,在录制时进行记录,回放时进行 mock,从而减少测试数据的稳固。Java 中代表的有阿里的 Repeater
计划剖析
而联合咱们理论诉求,以及计划的优缺点,进行匹配:
- 部门内.net 转 java、接口合并等技术工作,须要这套计划能进行跨语言、平台的回归
- 须要可能合并读 + 写接口的回归,即须要 Mock 或数据还原
- 须要能反对集成联调阶段,即对外实在的内部调用
基于剖析,咱们发现独自基于黑盒的计划,对写接口验证能力较弱(写接口对外只返回一个状态 ok),测试数据不稳固 case 类型偏移(如线上有数据的商家,在测试环境回放后果空)。而独自基于 Repeater 的计划,又只能反对单语言平台(不能反对.Net 转 java 的理论诉求),Mock 性能不能兼容有 IO 变动的迭代(只能匹配到已记录的 db 查问)。
没有完满解决所有问题的银弹
通过综合思考,最终确定:
• 对于读接口(80%):自研 AutoDiff 进行黑盒流量回放测试。
• 对于写接口:应用 Reapeater 进行回放测试。而其余仍不能反对的写接口场景(如有 io 变更、跨语言等情景)再进行惯例的接口自动化测试或手工测试。
整体计划:
在应用层,能够反对各开发阶段及各种回归需要场景,而在底层,读写接口别离由 2 套基于不同实现的计划进行撑持,同时依照流量的子调用状况,进行读写接口计划的适配:
底层的读接口计划,整体架构如下,数据层反对从多种数据源收集并整形流量,通过肯定的荡涤、筛选、解析,精准规定解析并进行用例计算。测试过程采纳实时比对形式,比对算法反对不同接口、进行乐音解决等解决,最终汇总生成报告及后果剖析。
底层写接口计划,是基于 Repeater 进行二开和包装,录制数据上报 kafka
经 flink 生产后,加密后存储到 hbase,并提前进行分词后,再存储到 ES 索引用来检索。录制反对组件进行了落地适配,丰盛了部门内罕用组件的若干插件。并提供了应用层的环境、配置管理等:
外围问题解决
写接口 (Repeater) 回放原理
Repeater 是阿里基于 JVM SANDBOX 开发的一套开源框架,外围性能是提供了通用录制回放能力,其官网介绍:
无侵入式录制 HTTP/Java/Dubbo 入参 / 返回值录制能力(业务零碎无感知);
基于 TTL 提供多线程子调用追踪,残缺追踪一次申请的调用门路;
入口申请(HTTP/Dubbo/Java)流量回放、子调用(Java/Dubbo)返回值 Mock 能力。
也就是说 Repeater 基于 sandbox 提供的能力,能够记录到 Java 办法级调用的入参、返回值、调用程序等信息,并把内部调用的入口申请,定义为入口调用(比方 http 接口默认将 Httpservlet 的拦挡作为入口调用),而将该次申请所产生的上游调用,称为子调用,流量的录制过程就是把入口调用和子调用绑定成一次残缺的记录。
具体哪些上游办法调用会被记录下来,能够由埋点插件自定义,利用于业务时,个别会将 Dao 内部 IO 层调用的 Java 办法进行埋点,拦挡录制,比方数据库查问或内部接口调用的返回后果实体。
像应用 retrofit 的接口调用,录制后的内容是这样的:
录制下流量后,在回放时,会重放入口调用,并在运行时从录制的子调用中依据 MockStrategy 搜寻匹配的子调用,如果有调用到已录制的子调用,则进行 throwReturnImmediately 返回录制时记录的返回值,没有匹配后果则抛出异样阻断流程。
而针对须要录制的上游办法调用类型,官网已提供了若干罕用的插件,在落地过程中针对咱们部门外部罕用的组件,补充了若干插件的开发,截至 21 年中旬反对的插件大略有:
降噪解决
在流量回放测试(能够说是所有接口自动化测试)落地中,误报率始终是生命线个别的指标值,同时影响着稳定性、后果可信度、排查工夫等,是至关重要的一项指标。
读接口 - 智能去噪
对于黑盒的读接口计划,误报最大的因素是乐音,在理论测试中,大部分的接口 response 都会蕴含一些工夫戳或者广告 pvid 等字段,每次申请生成的都不一样,导致比对不统一报错,但其实业务上并没有问题,有的我的项目甚至所有 100% 的 case 都会因而报错。比方上面这几种:
能够看到乐音字段的品种、字段名多种多样,不同我的项目光工夫戳的字段就有 cdntime、timespan、timestamp 等,只提供人工配置疏忽的话,十分繁琐耗时不可承受。
针对乐音字段的个性是,这些字段的变更并非本次变更所导致,也就是说即便本次代码没有变更,同样的环境,屡次刷新下,这个字段值也会变。
由此咱们将黑盒回放的过程进行了优化,由原来的新旧代码各申请 1 次,优化为会对旧代码环境申请 2 次,将差别的字段记录下来,就能够认为是咱们想要疏忽的乐音,在和新代码环境响应进行比对时过滤掉,残余的差别才是实在代码差别所导致的变更。同时也反对人工配置的指定字段。
为了进一步优化这个机制的成果,缩小呈现“申请 2 次旧代码的时候这个字段没变,但申请新代码的时候正好变了,比方秒级工夫戳”的偶发事件,申请程序须要固定为:申请旧代码 –> 申请新代码 –> 申请旧代码。
这样,如果 2 次申请旧代码工夫戳变了那它会被辨认为乐音没问题;而如果 2 次申请旧代码工夫戳没变,那么工夫是流逝的,夹在两头申请的新代码工夫戳必然也是统一的,这样该字段就不在差别范畴。
而对于对雷同代码环境申请 2 次时,哪些类型的 response 差别能够被标识为乐音,次要思考了以下几种:
• json 节点 value 不同:是乐音。此类差别被辨认为乐音的差别项,将记录这些节点 jsonpath,并在新、老代码报文比对时进行疏忽。
• json 节点 key 不同:不视为乐音,尽管咱们的大前提是间断 2 次请
求线上代码环境,但可有可能因环境或第三方问题造成某次申请报文构造不同,咱们的目标是辨认乐音用于前期疏忽,为了避免误加,此类差别,不会视为乐音。
• json 数组个数不同:不视为乐音,理由同上,因为不是叶子节点,
而是数组某个元素的话有可能比拟大的节点,间接作为乐音去疏忽的话,很有可能造成最终漏报。但仍有一些状况是举荐类接口,有可能第一次举荐 3 条内容、第二次举荐 4 条内容,这种状况下数组个数在业务上是应该被视为乐音的,但目前没有对此进行非凡辨认。
• json 数组程序不同:是乐音,次要呈现于局部举荐接口,或不关怀列表排序的接口。
• http 层响应码、响应头不同:是乐音(因为大部分我的项目功能测试不
关怀头信息,所以 AutoDiff 中,默认不比对头,只有配置了要比对头的我的项目,才会提供这部分的查看及去噪)
读接口计划引入这套去噪机制后,效果显著,如果是带有工夫戳的我的项目,报错率能够由 >90% 降到 <10%。
而仍存在的误报,次要是举荐类业务的 List 接口,目前无奈解决,即接口业务上每次会举荐数据不同的数据,这种类型的接口能够设置依据 schema 比对,但为了不漏报,故没有进行固定疏忽。
写接口 - 欠缺 Mock
对于基于 Repeater 的写接口计划,因为其自带的 Mock 反对,呈现乐音的
场景与起因与黑盒并不相同。比方下面提到的举荐数据变更导致的误报,在
Repeater 中开启 Mock 后并不存在(查问时会返回录制的数据,并不会实在反复查问)。
但 Repeater 计划中,因 response 内蕴含的工夫戳等字段不统一导致的误报,
也同样存在,次要是因为这些字段是由 Date、随机数、native 原生办法等生成的,这些办法 jvmsandbox 并不能进行拦挡录制,回放时还是实在调用了。
解决形式是,将这些无奈拦挡的 native 办法用能够拦挡的 java 代码封装一层办法,在我的项目中引入,并在编译阶段,将代码中蕴含这些办法的局部替换为援用咱们本人定义的办法,这样构造方法、原生办法就变成了一般的 java 办法。而后提供插件对这些一般 java 办法感知和干涉,即能够胜利的录制到工夫值,用于后续 mock:
除此外,咱们还不同问题进行针对优化,如下移原 mybatis 插件的 insert
埋点,用于解决 response 内回显插入数据主键 id 场景下,回放值为 null 的误报问题等。
而目前还存在的误报,次要是会因新老版本代码逻辑变动,子查问无奈匹配
到,导致的误报,比方原来查 2 次库,当初只查 1 次,或者间接改成查 solr 了等。以及因局部查问类型未齐全埋点,未被录制下来导致 case 失败误报的状况等。
用例计算
那么在进步用例品质方面,咱们设置了一套组合的测试用例生成规定,生成
时能够依照以下几个规定,别离提取指定数量的 case,合并成一份 case,兼顾时效、与笼罩等维度,互相补救:
A. 近期日志测试(保障时效 + 随机性)
接入各个起源记录的流量,拉取最近期的随机 case。能够进行人工指定配置,在业务上反对使用者的不同测试需要,对整个站点所有接口,各测试局部 case,或是对某个单接口进行的专项测试,能够灵便设置。
B. 人工录入(反对重要 / 打底场景)
间接增加录入,或导入 txt,用于创立局部打底的 case
C. 精准提取(高笼罩低冗余)
提取日志时,依照肯定规定对同一接口的流量,进行分类,依据配置的每个接口所需条数,尽量返回更多不同类的。分类根据有如下:
1)url 参数
依据 url 的参数组合及值进行解决,荡涤掉无关的参数等后,进行相似如图的分组后均匀提取,后续会持续补充一些针对参数值的定制化规定。
2)response
依据历史录制 / 回放过的流量 response,依照是否 json,$.result 节点的类型进行一层大类的分类,而后不同大类抉择不同的特色项,对流量进行标注,并具体计算出具体的特色坐标值。
在生成流量时,每大类都依照 Kmean 算法聚类,对于异样的大类,类簇 k 最多 2 类,而后每个聚类均匀提取。
3)办法调用链笼罩状况
打算能够联合 jacoco,对流量笼罩的办法进行记录,并将笼罩门路雷同的 case 标识为同类的 case。目前还在打算中。
D. 参数化生成(满足局部单接口专项)
录入某条种子申请,将须要参数化的值以 $ 模式标识,如:
GET — /apiprice/api/XXX?seriesId=${series}&withEqid=true&${cidAnddid}
POST–
并别离录入每个参数(如 series、cidAnddid)的数据文件,执行时将依照各参数值,生成笛卡尔积的 case 汇合。
用以撑持线上数据量笼罩不全或心愿全量测试,需依据 db 内现有数据结构生成 case 等状况。
跨平台、跨接口比对
在前述提到如.net 迁 java 我的项目接口、接口优化等的各类须要做回归验证的技术工作中,经常随同着新老版本的接口不能间接比对的状况,比方下图的 2 个新旧版本 json 响应:
因为 2 套新旧代码模板定义的接口 protocol 不同,导致后果内容存在了不
同节点。如果间接比对肯定是会报错,所以咱们在比照时进行了提取配置,别离将 $.Data 和 $.result.list 进行提取,而后再进行比对就满足了这些有变动的场景。
跨接口场景(接口合并 / 拆分 / 优化等类型的变更)
那么如果下面的场景反对了,其实齐全不同的 2 个接口,也是能够通过这个思路,能够将雷同业务逻辑的字段,进行自定义映射关系的配置,进行提取,将
2 个响应都转化为雷同的构造,而后即可进行后续的比对以及可视化的后果展现。
比方咱们有一个流动车型列表接口 A,与另一个业务线的接口 B,返回的车
型应该是同步的,只是附加的其余字段有区别,想要在线上进行定时的比对核验,json 构造如图
能够应用 jsonpath 的映射关系作为 key,各自按门路提取的值作为对应的 value,别离转化组合造成新的 json 构造文本如图。
转化后的 json 构造是雷同的,能够清晰的从 2 个齐全不同的接口中,只提
取展现看到咱们关怀的差别,而后将 2 份新的样本(具备雷同构造)进行比对,相比针对每个需要独自编写接口自动化测试代码更为间接简略。
闭环性能
除了下面一些外围问题的解决,也须要提供配套的闭环辅助性能,以及各性能的易用优化,使工具达到更加疾速、高笼罩的指标。
如与流水线的集成;对报错进行标注,要定期收集,继续解决优化误报的状况;以及别离依照接口、代码维度统计展现笼罩状况,便于对测试以及用例品质状况的一个反馈等。
而对于报错排查,为了缩短理论落地时谬误排查的工夫,咱们继续基于各方反馈,对报告进行了继续大大小小的优化。
比方写接口的报告能够清晰的切换查看 response,以及子调用的详情。读接口的报告将所有 case 集成在一个报告中,可视化的 diff 信息、便捷的设置入口、反对持键盘↑↓键切换查看、切换查看原始 / 解决后的 response。。。目前下一步打算还能够从报错聚合剖析和展现方面,进行一些优化。
成果评估形式
对于整个计划的成果评估,咱们从 3 个角度进行了剖析,基于这些指标进行定时的察看,以便于后续的打算与跟踪:
业务价值
理论落地后,为部门解决的问题,或者发明的业务价值。对于测试工具,更多的是联合咱们以后部门业务特点、技术、以及质保体系的状况,痛点状况来评估引入 Autodiff 流量回放后创立的价值:
- 解决补救了部门内原来回归测试随机发展的问题。为 90+ 个后端服务提供需要交付的回归测试保障。
2. 为原先因无奈全量测试而不敢进行的技术工作,提供了无力撑持。
全年共计反对 15000 + 次回归测试,50+ 次技术专项工作。共计回归约 440 万 条用例 , 在各阶段拦挡 100+ 个问题,节俭人力约 4 人年。
经营推广状况
工具的落地推广经营局部,咱们次要思考统计了:罕用我的项目接入率(数)、罕用接口接入率、我的项目均匀 case 数、已接入我的项目日常发版执行率、代码覆盖率。
工具自身
在工具自身的能力状况方面,依据咱们对这套回归测试工具外围的期许:
可能疾速、高笼罩的实现集成回归测试,对相应的察看指标进行拆解。
疾速局部的指标能够拆解出:接入工夫、执行工夫、保护工夫(用例拉取 / 保护)、排查工夫(千条 case 工夫);
高笼罩局部能够拆解为:能笼罩的诉求场景以及测试类型、代码覆盖率高、理论业务场景覆盖率高;
以上过程指标有的能够间接统计,有的不能间接察看统计,能够采取定期访谈的形式,或者替换拆解为其余二级指标,如排查工夫更多的用误报率代替。
成果评估形式
基于前述几个方向的指标继续察看,咱们下一步会持续优化性能:
- 用例的精准化生成,进步覆盖率,缩小保护老本;
- 报错聚合,缩小排查工夫;
- 尽量能笼罩更多的诉求场景或测试类型;
本文节选自 Testerhome 社区爱好者合力编写的《2021 接口测试白皮书》,点击链接可查看并下载完整版《2021 接口测试白皮书》。
想要学习更多对于测试 / 测试开发技术、测试治理和品质保障的干货常识?
想要结识品质行业大牛和业界精英?
欢送关注第十届中国互联网测试开发大会·深圳站 >>