自动化测试的模型与数据驱动原理

接入与开发

讲清自动化测试里数据驱动与关键字驱动的原理、落地写法,以及怎么判断该用哪种。

写自动化测试时,很多人卡在同一件事上:用例越写越多,改一个字段要动十几个脚本。这篇不谈协议和客户端怎么配,只讲驱动方式的原理和工程做法——数据从哪来、关键字怎么拆、断言和日志怎么留、被测系统换成接口这条路还走不走得通。看完你能给现有用例排一遍该不该重构。

写自动化测试时,很多人卡在同一件事上:用例越写越多,改一个字段要动十几个脚本。问题不在工具选得好不好,而在用例结构和数据之间的关系没理顺。这篇只讲驱动方式的原理和工程做法——数据从哪来、关键字怎么拆、断言和日志怎么留、被测系统从界面换成接口后这条路还走不走得通。

看完你应该能做一件具体的事:把手上现有的用例清单过一遍,逐条判断它属于硬编码、数据驱动还是关键字驱动,再决定哪些该重构、哪些先放着。本文不涉及协议和客户端怎么配,那部分到站内工具目录和指南中心对照着看即可。

为什么要把用例和逻辑拆开

硬编码用例有一套很典型的外观:用例文件里直接写着环境地址、账号、期望值;换一套环境要先改代码;想多加一组参数,最省事的做法是复制一份文件改几个字。几个月后同一段流程出现七八个副本,谁也不敢删。这种结构不是写的人不专业,而是早期赶进度时的自然选择。

驱动方式的本质是把「做什么」和「用什么数据做」分成两层:流程逻辑只写一遍,取值从外部读进来。这样加一组参数就是往数据文件里加一行,换环境就是换一份配置,断言和步骤描述也能集中到一处。改动面从「十几个脚本」缩到「一个数据源」。

硬编码用例
流程和取值写在同一处,改数据必须改脚本
数据驱动
流程固定,取值从外部数据源逐行读入,一行数据跑一遍流程
关键字驱动
把动作封装成带参数的关键字,用例变成关键字的有序序列
混合驱动
外层用关键字描述步骤,步骤内部再吃一组数据

但拆开不是无条件的正确。先量一下收益:如果用例总数只有几十条、字段几乎不变、只有一个人维护,那么引入数据层和关键字层带来的抽象成本,很可能比省下的修改量还高。这种情况不用急着上,先把断言收拢、把环境地址抽成配置就够了。什么时候该动手?当你发现同一条流程被复制了多份,或者每次需求变更都要在多个文件里做同样的修改,那就是拆分信号。

数据驱动的模型长什么样

数据驱动的骨架是三段:先读取数据源,再按行循环执行动作,最后每行独立给出结果。关键是第三段——失败必须能定位到具体是哪一行数据,否则跑完只知道「有个用例挂了」,还得手工复现。落地做法是给每行数据一个稳定标识,输出结果时把它带上,报告里一眼能看出是哪组参数出的问题。

数据源形态适合场景代价
代码里的表结构参数组合少、只在本地跑改数据要改代码,复用性最差
本地表格文件参数组合多、需要非开发人员维护文件容易和脚本不同步,需要专人管
接口返回或数据库查询数据量大、依赖上游系统状态受外部环境波动影响,失败要先排除数据问题

越往后越适合参数组合多的场景,但也越依赖外部条件。选哪一层,看的是数据变动的频率和谁来维护,不是看哪个听起来更高级。另一个必须配上的约束是「数据与用例解耦」:用例文件里不出现具体取值,只引用字段名。这条约束不写进规范,很快就会有人在脚本里顺手写死一个默认值,数据层形同虚设。

判断一个数据驱动实现是否合格,有个简单办法:把数据源换成另一份完全不同的取值,不改任何用例代码,能不能正常跑完并给出逐行结果。能,说明解耦做到了;不能,说明取值还散在流程里。

关键字驱动怎么拆动作

关键字驱动把「打开、输入、点击、断言」这类动作封装成带参数的关键字,用例变成「关键字 + 参数」的有序序列。它适合非测试背景的人维护用例,业务方对着关键字表就能看懂每一步在干什么。代价是多了一层抽象,调试时定位链路变长:出错后要顺着关键字一层层往下看,才能找到真正出问题的底层实现。

  • 粒度按复用频率定:同一动作在多个用例里出现就抽出来,只在一条用例里出现的先别抽
  • 命名要能自解释,参数顺序固定,建议关键字表里保留一列说明,写清每个参数的含义和取值范围
  • 关键字内部不要吞异常,失败要原样抛出并带上上下文,否则上层只看到「断言失败」四个字
  • 关键字表和实现保持一一对应,删除关键字时同步清理用例引用,避免留下死条目
  1. 先做关键字盘点把现有用例里的操作动词列出来,统计每个动作出现的次数,出现频率高的进入候选列表
  2. 定参数接口每个候选关键字确定参数个数和顺序,写进关键字表;参数尽量传字段名而不是传具体值
  3. 改造一条完整用例挑一条代表性用例,整条改成关键字序列,跑通后再推广到同类用例,避免一次性大改
  4. 验证定位能力故意让某个关键字失败,检查报告能否指出是哪个关键字、哪一步、哪组参数,定位不清就回去补上下文

关键字拆得好不好,有个判断标准:一个不熟悉脚本的人拿到关键字表和一组数据,能不能大致读懂这条用例在做什么。读不懂,说明命名或粒度出了问题;读得懂但改一次要动很多地方,说明参数设计太耦合。

两种混用与接口场景的取舍

实际项目里很少只用一种。常见做法是外层关键字描述步骤,步骤内部再吃一组数据。这里有个容易踩的坑:关键字层和数据层都存了同一份取值,改一处忘一处,两边不一致时排查非常费劲。原则是取值只在一个地方定义,另一层只引用标识。

被测系统从界面换成接口时,驱动结构基本不用推翻。关键字换成「发请求、校验字段、比对状态码」,数据驱动那层几乎原封不动,因为接口测试的参数组合通常比界面更多,数据层反而更值钱。这也是为什么建议先把数据层建起来,再考虑关键字层——后者换技术栈时改动更大。

  • 并发和节奏留余量,别把被测环境打挂,具体并发上限到站内工具目录里的压测与测速工具看当时的说明
  • 超时、重试、失败重投按站内工程指南配置,不要在每个关键字里各写一套
  • 结果记录要能回答三个问题:哪一行数据、哪个关键字、什么断言失败
  • 环境地址、账号这类配置统一收口,禁止散落在关键字实现里

补充一个判断:如果被测系统本身还在快速迭代、接口频繁变动,那么花大力气搭关键字层可能不划算,先把数据层和断言收拢,等接口稳定了再抽关键字。判断依据是接口变更频率,不是团队规模。

下一步带上你现有的用例清单,到站内指南中心对照数据驱动与关键字驱动的判定条件,逐条标出该重构和可以先放着的用例;顺路在工具目录里挑一个报告展示工具,先把「哪一行数据、哪个关键字、什么断言失败」这三个问题解决掉。

常见问题

数据驱动和关键字驱动必须二选一吗?

不用。常见组合是外面用关键字描述步骤、里面吃一组数据。只要保证同一份取值只在一个地方维护就行,两层都存一份是后面改不动的根源。

用例不多,直接写脚本不行吗?

行。用例数量少、字段几乎不变、只有一个人维护时,直接写反而更好读。等到出现「改一个字段动十几个文件」的信号,再往回拆也不迟。

换成接口测试,这套还适用吗?

适用,变的是动作层。把界面操作换成发请求和校验响应字段,数据层和断言组织方式基本沿用。跑批前先确认接口的并发限流口径,免得把测试抖动当成缺陷。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。