做接口自动化测试,最怕遇到什么?不是接口报错,而是接口没报错但用例挂了,一查,发现是历史脏数据把断言带偏了。这种事我遇到太多次了,所以后来在团队里定了一条规矩:任何一套接口自动化脚本,执行前必须做初始化,把旧数据清干净。这个"初始化清空旧数据"的活儿,听着简单,真要落到Jmeter里做顺手、做安全、做可复用,坑也不少。这篇内容就是围绕这个场景,把我实际用过的方案、踩过的坑和推荐的做法完整梳理一遍。
先说明一点,这套初始化方案适合谁:正在用Jmeter做接口自动化测试的QA、测试开发,以及想把手动接口测试脚本升级成可持续回归脚本的人。不管你的被测系统是电商、金融还是后台管理系统,只要接口涉及增删改查,数据一旦叠加,用例结果就会不可控,这篇文章就是解决这个问题的。
1. 为什么接口自动化必须处理初始化清空旧数据
1.1 脏数据是接口自动化跑挂的头号原因
接口自动化和单次手工调接口最大的区别是什么?是重复执行。手工测一遍,环境是干净的,数据量也少,怎么调都舒服。自动化是同一套脚本反复跑,今天跑了明天还要跑,甚至每天定时跑。问题就出在"反复跑"上。
举个我实际经历的例子。一个下单接口,第一次跑脚本,创建订单、支付、查询订单,全部通过。第二次跑同一个脚本,直接失败——因为下单接口要求用户维度在同一个时间窗口内不能有重复消费记录,第一次跑完留下的订单把第二次的单子顶掉了。再打开数据库一看,订单表里躺着几十条历史测试数据,断言里统计出来的订单数量和预期对不上,整个测试报告全是红的。
这就是脏数据的典型杀伤力。具体来说有三类影响:一是唯一性约束,重复插入相同业务主键或业务编号,接口报"数据已存在";二是聚合统计失准,比如对账接口、报表接口这类带SUM、COUNT的查询,旧数据会把统计结果整体抬高,断言永远算不对;三是状态流转错乱,流程类接口依赖数据的初始状态,比如"待审核"才能"审核通过",历史数据可能已经把状态推到"已完成",脚本再执行就找不到可操作记录了。
所以接口自动化里的初始化,本质上不是"清理数据"这么简单,而是在每个测试轮次开始前,把被测系统的数据基线复位到一个确定状态。基线不确定,后面所有断言都是空中楼阁。
1.2 初始化清空旧数据的典型场景与路径
什么时候需要做初始化?我归纳下来主要是三种场景。
第一种是回归测试开始前,把几个核心业务表清空。比如订单表、用户表、商品表,保证这一轮测试跑出来的数据是从零开始的。第二种是定时任务触发后留下的历史数据,比如每天凌晨跑自动化脚本,前一天的数据必须清掉,否则当天用例一上去就撞车。第三种是测试环境被多人共用,别人调试留下的半截数据,你根本不知道是什么时候生成的,最稳妥的办法就是跑用例前统一清一遍。
针对这三种场景,Jmeter里有几条常规路径可以走:
- JDBC直连数据库,通过JDBC Request执行DELETE、TRUNCATE语句清掉旧数据;
- 调用业务系统提供的清理/重置接口,让系统自己处理关联数据;
- 用BeanShell或JSR223脚本读取外部SQL文件,循环执行批量清理。
这三条路径我在实际项目里都用过,各有各的使用边界,下一章详细对比。
2. 方案选型:三种清空旧数据的技术路线
2.1 三种方案对比
先把三种方案的核心差异摆出来。做技术选型最忌讳凭感觉,我拿一个对比表说明:
| 方案 | 实现方式 | 适用场景 | 优点 | 缺点 | 上手难度 |
|---|---|---|---|---|---|
| JDBC直连数据库 | Jmeter配置JDBC Connection,JDBC Request执行清库SQL | 有数据库权限、技术团队内部使用的回归环境 | 清理彻底、速度快、可控性强 | 需要懂SQL、需要库权限、跨库外键要实现处理 | 中等 |
| 调用业务清理接口 | 通过HTTP请求调用系统自带的初始化/重置接口 | 系统提供了专门的数据清理或环境重置能力 | 无需数据库权限、跟随业务规则、安全 | 依赖接口存在、接口本身可能也有数据依赖 | 低 |
| BeanShell/JSR223脚本 | 脚本读取SQL文件或调用JDBC工具类批量清理 | 需要灵活处理动态表名、批量执行多环境SQL | 灵活、可扩展、适合复杂清理逻辑 | 脚本调试成本高、性能受限于脚本引擎 | 较高 |
2.2 JDBC直连为什么是首选
如果被测系统在测试环境能拿到数据库权限,我强烈推荐用JDBC直连的方式做初始化,这也是我目前的主力方案。原因很简单:清得最干净、最可控。
接口调用清理接口虽然省事,但你受限于业务方的实现。比如系统只提供了"清订单"接口,但没提供"清用户"接口,你还是要回数据库处理;或者清理接口本身有权限控制、有复杂的校验逻辑,自动化脚本时不时会被它自身的问题绊倒。JDBC直连就没有这层顾虑,你对数据有着绝对的控制权,想清哪张表、想重置自增ID、想关掉外键检查,都是SQL一句话的事。
从Jmeter的实现原理看,JDBC Connection Configuration本质上就是维护了一个数据库连接池,JDBC Request负责往这个连接池提交SQL,跟你在Navicat里执行SQL是一样的效果。它天然适合放在setUp线程组里:setUp线程组在主线程组之前运行,专门用来准备测试环境数据,跑完初始化再进主流程,顺序完全可控。
还有一个关键点:JDBC直连清库通常比接口清理快得多。TRUNCATE一张十万行的订单表是一瞬间的事,走接口一条条删可能要删几个小时。自动化测试的初始化越短越好,最好控制在秒级到分钟级,否则整个执行链路会被拖得很长。
2.3 接口清理和脚本清理的适用边界
当然,JDBC也不是万能的。有些场景你拿不到数据库连接,比如被测系统是外部供应商提供的,或者公司有明文规定QA不能直连生产相关的测试库。这时候就比较适合走接口清理。我遇到过一种情况:系统的用户数据做了逻辑删除,所谓"清空"其实是要把用户的status改成disable,同时联动清理Redis缓存。这种业务逻辑在SQL里做容易漏,调用业务接口反而更安全。
BeanShell/JSR223脚本则适合清理逻辑特别复杂的场景。比如你要根据某张配置表动态拼出需要清理的表清单,或者要按日期批量清理七天前的数据,SQL本身是动态生成的。这种活交给脚本更顺手。我的经验是:脚本方案不要一上来就用,等JDBC方案解决不了再加复杂度,否则初始化逻辑会越写越重,维护成本直接起飞。
这里也给一个组合策略:JDBC为主,接口为辅,脚本兜底。能直连清的就直连;直连涉及业务缓存联动时,补一个接口调用;遇到动态表名、多环境多租户这种高度定制化的清理诉求,再上JSR223脚本。
3. Jmeter里初始化清空旧数据的完整实操
3.1 先配置JDBC连接
先讲JDBC连接的配置,这是整个初始化方案的地基。在Jmeter的测试计划里添加"JDBC Connection Configuration",需要填一组关键参数。
以MySQL为例,我常用的配置是这样的:
JDBC Driver class: com.mysql.cj.jdbc.Driver JDBC URL: jdbc:mysql://test-db.internal:3306/order_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true Username: qa_automation Password: xxxxx Max Connections: 10这里有几个细节要特别注意。
第一,驱动类名取决于JDK版本和MySQL驱动版本。JDK8 + MySQL 5.x用com.mysql.jdbc.Driver,JDK8 + MySQL 8.x要用com.mysql.cj.jdbc.Driver,驱动包也必须是对应的mysql-connector-java-8.x.jar。我曾经在一个老项目里看到过No suitable driver found的错误,把驱动从版的jar换掉就解决了,问题就出在驱动类名和jar版本不匹配。
第二,URL里的allowMultiQueries=true是给执行多条SQL用的。如果你打算在一个JDBC Request里连续放多条清库语句,这个参数必须开启,否则会报语法错误。我在3.2节还会细讲多条SQL的处理方式。
第三,JDBC Configuration里有两个容易忽略的字段:Transaction Isolation和Result Set Type。初始化场景下默认值就行,但如果你的清理SQL里涉及大批量更新,建议把Transaction Isolation保持默认,不要改成SERIALIZABLE,否则多个清理语句互相锁等待,初始化能卡成乌龟。
配置完成后,在测试计划里添加一个"JDBC Request"元件,放一条最简单的验证SQL,比如SELECT 1,跑一次如果能正常返回,连接就通了。这一步务必先验证,后面的清库脚本都依赖这个连接。
3.2 表结构设计与清空SQL的正确写法
JDBC连接通了,接下来是核心部分:清空SQL到底怎么写。这里头学问不少,我直接放一套我常用的清库脚本模板,并解释为什么这么写。
假设被测系统涉及用户、订单、订单明细三张表,标准的清空SQL是这样的:
-- 关闭外键检查 SET FOREIGN_KEY_CHECKS = 0; -- 先清子表,再清父表 TRUNCATE TABLE t_order_detail; TRUNCATE TABLE t_order; TRUNCATE TABLE t_user; -- 重置自增主键 ALTER TABLE t_user AUTO_INCREMENT = 1; ALTER TABLE t_order AUTO_INCREMENT = 1; ALTER TABLE t_order_detail AUTO_INCREMENT = 1; -- 恢复外键检查 SET FOREIGN_KEY_CHECKS = 1;为什么先清子表再清父表?因为外键约束的存在,父表被引用时不允许直接清空。TRUNCATE和DELETE还有一个显著区别:TRUNCATE是DDL语句,执行效率高,不走事务日志,但它会隐式提交;DELETE是DML语句,可以配合事务,但是逐条删,数据量大时慢到怀疑人生。所以能TRUNCATE就TRUNCATE,除非你需要保留表结构下的某些初始化种子数据。
关于AUTO_INCREMENT重置,这也是一个比较关键的实践。TRUNCATE本身会把自增计数器重置为0,但为了保险起见,我一般还是显式加一条重置操作。千万注意:如果你删了数据却没有重置自增,执行几次自动化后主键会越来越大,一旦某天用例里写死了"第一条数据ID=1",就会被历史自增ID坑到。
多条SQL在Jmeter里的执行方式,有三个细节:
- JDBC Request的Query Type在下拉框里要选"Callable Statement"。这样多条SQL用分号分隔可以直接执行。选"Select Statement"只能跑单条查询,选"Update Statement"虽然也能跑,但对多条的支持不够好。
- 一条JDBC Request里不要堆超过20条SQL。一旦某条SQL报错,排查起来很痛苦,日志里只告诉你第几条语句出错,你还得去数。我在实际中更倾向于把清库SQL按业务模块拆成多个JDBC Request,比如"清用户表"一个、"清订单相关表"一个,中间用注释标识清楚,出错时一眼定位。
- 每条清库SQL执行完,建议勾选JDBC Request里的"Response Data"选项。这样可以在查看结果树里看到受影响的行数,方便确认这条SQL确实把数据清掉了。
3.3 用setUp线程组编排初始化流程
清空SQL写好了,放在哪里执行?答案是用setUp线程组。我先画一个流程概念:setUp线程组 -> JDBC Connection Configuration -> 若干个JDBC Request -> 紧接着一个断言判断初始化是否成功,全部通过后才进入主线程组跑接口用例。
setUp线程组的执行顺序是Jmeter规定的,它在普通线程组之前运行,tearDown线程组在最后运行。这个机制天然适合初始化场景。我最开始做初始化是在普通线程组前面加一个"初始化"线程组,用线程组间执行顺序来控制。后来发现有个坑:如果普通线程组并行启动,初始化线程组还没跑完,用例就已经开始执行了。虽然多数时候不至于挂,但确实会撞上数据竞争。换成setUp线程组后,这个问题彻底没有了。
在setUp线程组里,具体的执行步骤我一般这样编排(以图形化界面操作说明):
- 添加"JDBC Connection Configuration",放在setUp线程组的"配置元件"下;
- 添加"JDBC Request",名称按业务含义命名,比如"清空用户表数据";
- Query输入清空SQL;
- 在JDBC Request后面加一个"BeanShell Assertion"或"JSR223 Assertion",执行完检查返回的受影响行数为0行时正常(TRUNCATE返回0行是正常的;DELETE返回删除的行数,如果表本来就是空的,返回0不影响);
- 再往下放几个JDBC Request,按顺序清其他模块的数据;
- 所有清理操作完成后,加一个"开销断言"性质的JDBC Request,例如
SELECT COUNT(*) FROM t_user,断言返回值为0,确保初始化真正完成了。
这里有个我犯过的错误要提醒:setUp线程组里的线程数和循环次数要设置成1。初始化只需要执行一遍,如果你设置成多线程,同一份清空SQL会被并发执行,可能会出现两个线程同时TRUNCATE一张表,结果第二个线程永远在等待表锁,初始化卡死。这种问题不好查,我第一次遇到时,看到Jmeter的日志停在某个JDBC Request那里不动,光排查锁就花了好几个小时。
另外,如果清空操作涉及多张表之间的外键关系,建议在setUp线程组里把"边界"控制好:关闭外键检查 -> 清理 -> 重置自增 -> 开启外键检查。每一步单独一个JDBC Request,顺序执行。千万不要把SET FOREIGN_KEY_CHECKS=0; TRUNCATE ...; SET FOREIGN_KEY_CHECKS=1;塞到一个JDBC Request里,因为连接池可能复用同一连接,状态残留会影响后续用例的连接。
3.4 初始化失败时如何自动中断
初始化脚本执行失败该怎么办?这是比"怎么清"更关键的一个问题。如果清库失败,后面的接口用例还在傻傻地跑,跑出来的结果一半是失败一半是误报,整个自动化报告没有任何价值。更糟的是,某些用例可能依赖"刚才插入的数据",初始化失败导致数据残缺,用例报错又查不出原因。
所以我在setUp线程组里加了“初始化失败即终止”的保护机制。具体做法是:在关键JDBC Request后面加一个Assertion,如果受影响行数不符合预期或SQL执行报错,就用"Flow Control Action"元件选择"Stop test"直接终止整个测试计划。
Jmeter里Flow Control Action的位置在“测试计划 -> 逻辑控制器 -> Flow Control Action”,它的Action有两个重要选项:Stop test表示停止整个测试,Stop test now表示立即停止。我在初始化场景里推荐用Stop test now,因为初始化失败后继续等待线程结束没有意义,越早终止越省时间。
如果你不想让脚本停止,而是希望"跳过本轮用例,等下一个循环再跑",可以用Start next thread loop。这个设置用在凌晨无人值守的定时任务里很实用:初始化失败,本轮直接跳过,等日志告警,第二天人工介入。
除了Flow Control Action,我还会配合一个"初始化结果检查"机制:在每个清库JDBC Request后,通过SELECT COUNT(*)查询核心业务表的记录数,然后用JSR223 Assertion判断返回结果是否等于0。判断不成立,直接就stop test now。这个保险是我吃了好几次亏才加上的,之前只依赖JDBC Request成功与否,但"执行成功"和"清理干净"是两回事,SQL执行成功不代表数据真的清零了。
4. 常见问题与排查技巧实录
4.1 外键约束和清空顺序
先讲外键约束问题,这是清库时遇到最多的报错。报错信息大致长这样:Cannot delete or update a parent row: a foreign key constraint fails。
遇到这种问题,第一反应不是去SQL里写SET FOREIGN_KEY_CHECKS=0然后硬清,而是要判断:这个外键是业务上必须保留的关联关系,还是历史设计遗留?如果是业务上一层套一层的关系,我建议先梳理表关系,按“先子后父”的顺序清。实在梳理不清楚才用关闭外键检查的兜底方案。
但有几个注意事项:
- 关闭外键检查的SET语句和TRUNCATE语句,尽量在同一个JDBC Request里通过Callable Statement执行,或者至少保证它们在同一个连接上执行。连接池如果切换了连接,外键状态可能没有按预期关闭。
- 初始化结束后,一定要在最后一个JDBC Request里重新开启外键检查,否则后续用例里如果涉及插入子表数据,外键校验失效,测试场景和真实线上行为脱节。
- 有些系统是基于MyISAM引擎的旧表,根本没有外键约束,但存在关联代码逻辑。这种“软关联”清库时不会报错,但会导致业务侧数据混乱。清库前先看建表语句,把逻辑关联也梳理进清理顺序里。
4.2 大批量数据的清理性能
数据量一大,清理就慢。我第一次清一张两百万行的日志表时,用DELETE FROM跑了一分多钟都不结束。原因很简单:DELETE逐行删除并记录日志,百万行级别性能很差。后来我换成TRUNCATE,秒级完成。
但TRUNCATE有一个限制:它不能像DELETE那样带WHERE条件。如果业务上只需要清理一个月前的数据,TRUNCATE直接全清会把有用数据也干掉。这种场景我会退回到DELETE,但会分批次执行:
DELETE FROM t_log WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY) LIMIT 5000;用LIMIT分批,一次删5000行,循环执行。在Jmeter里可以用一个循环控制器套一个JDBC Request,通过SELECT FOUND_ROWS()或ROW_COUNT判断是否还有剩余,自动跳出循环。实测下来,两百万行的表按批删,总时间也能控制在几十秒内,锁粒度小,还不会拖垮测试环境。
另外,清库语句执行期间,Jmeter本身会等待数据库返回。这个等待时间默认没有显式超时,如果连接卡死,整个初始化就会一直挂在那里。建议在JDBC Connection Configuration里把Validation Query设置为SELECT 1,并设置连接超时时间,这样至少能快速失败,而不是无限期等下去。
4.3 自增主键与断言基线
这个问题的隐蔽程度比外键还高,因为脚本不会报错,只会让断言在某个时间点莫名其妙地出错。具体场景是这样的:第一次跑,用户表主键从1开始,你创建了一个用户,ID=1;第二次跑,你没清表或者清了但没重置自增,新用户ID变成2。你用例断言里如果写死了"取createdUserId=1",第二次必挂。
这种问题排查起来特别费劲,因为日志里可能没有任何报错,只是最终断言失败。我的建议是:
- 初始化的SQL脚本里显式重置所有核心表的AUTO_INCREMENT,不要依赖TRUNCATE的隐式重置。
- 断言里不要写死ID。尽量从接口响应中动态提取返回值,比如用JSON Extractor把
$.data.userId提取出来,后面断言直接引用变量。 - 如果实在要断言“第一条数据ID是1”,请在初始化完成后先执行一个JSR223脚本,用数据库查询把最新ID读出来存成变量,再在主线程组里引用。这也算是一种“数据基线快照”的做法。
4.4 多环境切换与误操作防护
初始化清空数据是高风险操作,因为它本质上是在删东西。我见过不止一次测试脚本因为数据库连接配错,清到了别人正在用的共享环境,甚至差点清到生产库。这个问题必须通过流程和参数化双重防护。
先说参数化。不要把数据库IP、端口、库名、用户名、密码写死在测试计划里。我在Jmeter里用JMeter属性或用户自定义变量统一管理,测试计划里所有连接配置都引用变量:
${__P(db_host)} ${__P(db_port)} ${__P(db_name)} ${__P(db_user)} ${__P(db_pass)}运行的时候通过命令行参数注入环境:
jmeter -n -t init.jmx -Jdb_host=192.168.1.100 -Jdb_port=3306 -Jdb_name=test_order这样就杜绝了脚本里写死一个环境的IP导致误连别的环境。同时,可以在JSR223脚本里加一个白名单校验:只允许库名包含test或qa的环境执行TRUNCATE操作。我写过一个简单的校验逻辑:
if (!db_name.contains("test") && !db_name.contains("qa")) { throw new RuntimeException("禁止对非测试环境执行初始化清空操作!当前库:" + db_name); }这个校验我放在setUp线程组的最前面,每次初始化前先过这一关。虽然有点偏执,但清库这种事,多一道保险总比出事后悔强。
还有个细节:清空SQL执行时,建议把Jmeter的“查看结果树”调试功能关掉,尤其是执行大批量清理时,响应数据全量打印会拖慢性能,有时还会把敏感SQL显示在日志里。我在正式跑自动化时,只用简单的"Summariser"输出汇总,需要排查时再临时打开结果树。
4.5 初始化完成后接口用例仍然受脏数据干扰
有时候你会发现,表被清空了、自增也重置了,但接口用例跑起来还是传出了旧数据。这一般不是数据库的问题,而是缓存或索引没有刷掉。典型的场景是Redis缓存了用户信息,数据库清了,接口查缓存还能查到旧用户,导致断言里的用户状态和预期不一致。
处理方式是:在清库SQL执行完之后,追加一个"清理缓存"的步骤。如果系统有提供缓存清理接口,直接HTTP调用;如果没有,可以通过JDBC去查Redis持久化文件不现实,那就走系统的管理端API。我目前的组合是:清库 -> 调一个内部的缓存刷新接口 -> 然后再执行主接口用例。这个过程中间还会加一个等待时间,用Jmeter的"固定定时器"或者Groovy脚本sleep几秒,确保缓存完全失效。
还有一类隐蔽情况是消息队列里的历史消息还没消费完,用例跑快了会读到旧消息。这种我建议在初始化后加一个"消费延时"处理:比如停止消费端,等队列积压消息清空后再开始用例。这个控制有些复杂,不是在Jmeter里能直接搞定的,需要和开发团队配合,把环境初始化做进部署流水线里。
5. 把初始化做成可复用的数据工厂
5.1 从清空旧数据到主动造数
初始化做到及格线,是清空旧数据;做到优秀线,是清空的同时主动准备测试所需的种子数据。我开始做接口自动化时只清数据,后来发现很多接口用例需要前置数据,比如"登录用户已存在"、"商品已上架",如果每次都用接口去创建,脚本会变得又长又脆。
所以我把初始化扩展成了“数据工厂”:清空后,立即用JDBC或业务接口把基础种子数据批量插入。比如在setUp线程组里,清完用户表后,接一个"插入标准测试用户"的JDBC Request,SQL里插入一个固定的QA测试账号。主线程组的用例直接用这个账号登录,不用再走注册流程。
这里有个执行顺序的细节:种子数据的插入语句要放在清空SQL后面,但不要放在同一个JDBC Request里。我习惯把"清空动作"和"造数动作"分成两个独立的JDBC Request,中间用注释和命名区分。这样哪天种子数据需要调整,直接改对应请求,不会污染清空逻辑。
5.2 初始化脚本纳入版本管理
自动化和手工最大的区别就是可维护性。我强烈建议把整套初始化Jmeter脚本、SQL脚本、环境参数都纳入Git管理,跟着接口自动化代码一起做版本迭代。SQL文件的修改走代码评审,这样团队里每个人都清楚初始化逻辑动了什么,避免出现"谁偷偷加了一张表的清理"这种事。
对于SQL脚本,不要全都塞在JDBC Request里,更推荐把大段SQL放到外部.sql文件,然后在Jmeter里用${__FileToString(init.sql,,)}读取进来,填充到JDBC Request的Query里。这样做的好处是:SQL可以在Navicat里单独调试,改SQL不用反复打开Jmeter改元件;同时.sql文件走Git diff非常清晰,评审效率高。
我在项目里是这样组织的:
jmeter-automation/ ├── jmx/ │ ├── init_setup.jmx # 初始化线程组 │ └── main_flow.jmx # 主接口用例 ├── sql/ │ ├── clean_user.sql │ ├── clean_order.sql │ └── seed_base_data.sql └── config/ └── env.properties # 多环境参数5.3 集成进持续集成流程
最后一步,把初始化自动化做成流水线的一环。我所在团队用的是Jenkins,流程是这样串的:代码构建后部署测试环境 -> 环境初始化任务执行(清库+造数据)-> 触发Jmeter接口自动化 -> 生成报告并推送通知。
在这个流程里,初始化Jmeter脚本不需要和主用例脚本放在同一个JMX文件里,可以单独跑。这样好处是:环境初始化可以一键手动执行,接口用例也可以随时手动单跑,两者解耦。如果你更想用一条命令完成初始化+用例执行,那就像第3.3节那样,在一个JMX里用setUp线程组和普通线程组串联,也是完全没有问题的。
6. 最后聊几句实在话
做了这么多年接口自动化,我最大的感受是:初始化这个问题,看起来只是整个自动化链路里不起眼的一环,但它决定了自动化脚本能不能长期稳定跑下去。脏数据一天不解决,你的断言就一天不可信,脚本跑得再勤快,也只是在制造一堆需要人工人工复核的红绿报告。
在团队里推行这套初始化方案时,我定了三条铁律:一是初始化脚本必须幂等,无论跑几次,环境都回到同一个基线状态;二是初始化脚本必须能快速执行,超过三分钟就要优化;三是初始化脚本必须带环境标识保护,非test/qa库一律拒绝执行。这几条铁律帮团队少踩了很多坑。
最后再分享一个小技巧:在清空SQL执行完成后,别急着跑主用例,先花五秒执行一条SELECT COUNT(*),确认核心数据表是空的,再做断言。这个习惯看起来多余,实际排查问题的时候能帮你省下大把时间——至少你不会再为了一个被脏数据干扰的用例,去翻几个小时的历史数据了。