
做自动化测试的人十个有九个被“半夜红”折磨过。你布置在深夜的Robot Framework任务跑完Jenkins面板上一片红点开日志一看不是登录超时就是某个弹窗晚出现了两秒再不就是测试环境中间件重启了一下。这种“假失败”如果每次都靠人工去认领自动化就真的变成了“自动找活干”。我今天想聊的就是围绕RFRobot Framework做的一整套失败自动重跑机制用例失败之后不急着报红先自动重跑一轮把环境抖动造成的噪音滤掉重跑后仍然失败的用例再堂堂正正地出现在报告里。这套“基于RF自动化重跑”的方案本质上是用Robot Framework自身的能力加上pabot、Jenkins等周边工具把“重跑”做成一个可靠、可追溯、不掩盖真问题的自动化环节。它适合正在搭建UI自动化、接口自动化测试框架的团队适合被Flaky Test时好时坏的用例折磨得想放弃夜间任务的测试开发也适合想在公司Jenkins自动化部署链路里给自动化测试加上最后一道自动闸门的同学。1. 先说清楚为什么自动化测试一定要解决“重跑”问题1.1 假失败才是自动化维护成本的大头很多团队自动化测试做着做着就黄了最常见的导火索不是用例写不出来而是跑出来的结果没人信。同一套用例同一份代码昨晚全绿今早莫名其妙红了十几条你再跑一次它又全过了。这种用例行业里叫Flaky Test翻译过来就是“时好时坏的用例”。它的可怕之处在于它不像真正的功能缺陷那样可以被复现、被定位它只会在你最忙的时候跳出来烦你。Flaky Test在UI自动化里特别常见元素加载速度、浏览器窗口尺寸、图片懒加载、动画过渡时长都会影响结果接口自动化里也不少测试数据状态没复位、上游服务响应慢了半拍、定时任务刚好在跑都会导致某条用例偶发失败。我见过最典型的场景是一百条用例里只有登录接口偶尔慢400毫秒结果后面所有依赖登录态的用例跟着倒了八条从报表上看就是一片“大红大紫”点进去看根因就一处。如果不处理假失败后果很直接开发不信任自动化结果说你天天误报测试自己也不信任每次看到失败都要花半小时去翻日志判断到底是环境还是代码。到最后自动化测试变成了一个“自动给你找活干”的工具团队宁可回到手工测试。这也是为什么我说重跑机制不只是提高通过率数字的小技巧它直接决定了自动化测试项目能不能长期活下去。1.2 重跑不是“点一下重新跑”它要解决三个问题你可能觉得重跑有什么好讲的失败了再点一次不就行了。但真正落地的时候有三个问题必须提前想清楚否则重跑机制即使做了也会变成新的麻烦。第一个问题重跑哪些用例。是全量重跑还是只跑失败的全量重跑成本高一百条用例跑一遍半小时失败8条为了这8条把一百条都再跑一遍时间直接翻倍而且还会引入新的不确定性。增量重跑是对的只把第一轮失败的用例挑出来单独跑其它通过的用例不碰。这样重跑的成本通常只有全量执行的百分之几。第二个问题重跑几次、间隔多久。次数太多会掩盖真实问题也会拉长执行时间次数太少又起不到过滤假失败的作用。间隔时间也得有讲究环境刚抖完还处于半恢复状态你立刻重试大概率还是失败。这个参数的确定需要结合你实际项目的失败特征来调。第三个问题重跑之后的结果怎么汇总。这是最容易被忽略的。原始失败、重跑通过、重跑仍然失败这三类情况如果不在报告里区分清楚都混成一片绿色或红色那报告就失真了。领导看的是通过率但测试人员真正要追踪的是那批“重跑才通过”的用例因为它们往往是真实缺陷的前兆。这三个问题如果不在方案层面提前设计好后面就只能靠人肉看log那就失去了自动化的意义。下面我按方案选型、实操落地、参数细节、问题排查四个层面完整拆解一套基于RF的自动化重跑方案。2. Robot Framework 做重跑的几种方案选型2.1 方案一RF 原生的 --rerunfailed最经典适合老项目Robot Framework 本身没有“一键重跑”的概念但它的CLI工具里藏了一个很实用的参数--rerunfailed。它的作用是读取上一次执行生成的 output.xml 文件找出里面失败的用例然后只跑这些用例。这基本就是为增量重跑量身定制的。手动操作时是三步走。第一步正常跑一遍全量用例生成包含失败信息的 output.xmlrobot -d run1 tests第二步用--rerunfailed指定读取 run1/output.xml只重跑失败的用例结果输出到独立目录robot --rerunfailed run1/output.xml --outputdir run2 tests第三步把两份结果合并成一个报告让最终展示的 log.html 里既有首次失败记录也有重跑结果rebot --output run/combined.xml --merge run1/output.xml run2/output.xml这套方案最大的优点是兼容所有RF版本逻辑透明每一步都能通过脚本控制适合需要高度定制重跑行为的团队。比如你可以自己写一个循环实现“失败后重跑再失败再重跑最多重跑三次”的效果。缺点也很明显你需要自己处理文件名覆盖、目录规划、报告合并这些琐碎问题稍不注意就出错。2.2 方案二RF 5.1 之后的 --retry官方内置配置最简单如果你用的是 Robot Framework 5.1 及以上版本那就有更省心的选择了。RF 官方在5.1版本加入了内置的重试机制一条命令就能搞定robot --retry 2 --retry-interval 5s --outputdir results tests这个命令的含义是跑完第一遍后对失败的用例自动重跑最多重跑2次每次重跑前等待5秒。最终报告会自动记录用例的多次尝试情况不需要你再手动合并 output.xml。相比方案一--retry的优势是干净利落没有中间产物管理问题也不用写rebot合并命令对新人友好很多。我实测下来这个参数在95%的常规场景下都够用。唯一的限制是版本要求你如果还停留在RF 4.x就需要升级到5.1以上才能使用。关于升级我建议在独立环境里先做一轮验证因为RF 4到RF 5之间有一些语法和库的兼容性调整不能直接拿生产测试套件冒险。2.3 方案三pabot 的 --rerunfailed / --retry并发重跑一步到位当你的用例数量到了几百上千条单线程跑一次要一两个小时就必须用pabot做并发执行了。pabot是RF生态里最常用的并行测试工具它同样支持失败重跑相关的能力。基本用法是先并发跑全量用例pabot --processes 8 --outputdir results testspabot支持--rerunfailed和--retry参数不过它俩的语义要稍微注意。pabot --rerunfailed results/output.xml会读取上次结果在并发模式下只重跑失败用例pabot --retry N则是在当前批次内直接对失败用例做指定次数的重试。两者结合使用可以做到“并行跑完失败的自动再并行重跑”。pabot方案适合用例规模大、需要并发加速的团队。它的坑也明显并发情况下重跑失败用例时多个进程同时操作同一个账号、同一批数据很容易互相干扰。我后面在常见问题部分会专门讲这个。2.4 方案对比到底选哪个为了让你能快速决策我把三种方案的适用场景整理成一张表方案适用RF版本是否支持并发配置复杂度报告合并我的建议--rerunfailed 手动串全版本否中要写脚本循环需手动 rebot 合并老项目、不想升级RF、或重跑逻辑要高度定制--retry 内置重试RF 5.1否单进程低一条命令搞定自动展示多次尝试新项目、用例量不大优先选这个pabot全版本是中要注意数据隔离自动合并输出用例量大、必须并发加速的团队还有个现实因素要考虑如果你所在的公司已经有现成的 Jenkins 自动化部署流水线不管选哪种方案最终都要嵌入到 CI 流程里让重跑变成夜间任务的一环而不是靠测试人员每天早上手动跑一遍。现在很多AI自动化测试平台也都把失败重跑做成了基础能力但本质上它们用的还是这套逻辑只是把参数和流程封装成了界面操作。理解底层原理无论用哪个平台心里都有底。3. 实操从零落地一套 RF 失败自动重跑3.1 环境准备与项目结构先讲环境。推荐使用 Python 3.9 及以上版本安装 Robot Framework 6.xpabot 用最新版即可。接口自动化可以配上 robotframework-requestsUI自动化需要装 robotframework-seleniumlibrary。一条命令装齐pip install robotframework pabot robotframework-seleniumlibrary robotframework-requests装完可以先验证版本后面排查问题时会用得到robot --version pabot --version项目结构建议如下把用例、资源、结果分开避免输出文件和测试脚本混在一起rf_project/ ├── tests/ # 测试用例目录 │ └── smoke/ │ └── login.robot ├── resources/ # 关键字、变量文件 │ └── common.robot ├── results/ # 测试输出目录 └── scripts/ # 重跑、打包等辅助脚本我们先写一个非常简单的冒烟用例作为演示。下面的例子用 SeleniumLibrary 打开一个站点并执行登录虽然业务简单但足以验证重跑链路是否通畅*** Settings *** Library SeleniumLibrary Suite Setup Open Browser http://example.com chrome Suite Teardown Close Browser *** Test Cases *** Login Test Input Text idusername admin Input Password idpassword 123456 Click Button idlogin-btn Page Should Contain 欢迎回来3.2 第一步跑一遍基础用例摸清输出文件第一次先不加任何重跑参数正常跑一次看看RF会生成哪些东西robot -d results tests跑完后在 results 目录下会看到三个关键文件output.xml 是机器可读的执行结果log.html 是带日志的关键字级别报告report.html 是测试结果摘要。输出文件中 output.xml 地位最特殊因为--rerunfailed参数和后续的报告合并都依赖它它保存着每条用例的状态、耗时、失败原因等结构化数据。这一步的目的不是跑出多好看的通过率而是让你确认环境没问题、用例能真实执行。如果这一步就报错先解决基础环境问题别急着上重跑。3.3 第二步用 --rerunfailed 实现首次失败重跑现在正式进入重跑链路。第一次执行全量用例robot -d run1 tests假设跑完有若干失败执行第二次只重跑失败用例结果输出到独立目录robot --rerunfailed run1/output.xml --outputdir run2 tests然后合并两份报告rebot --output run/combined.xml --merge run1/output.xml run2/output.xml合并完成后打开 run/combined.log.html你会看到用例级别的状态包括哪些是本轮新增失败、哪些是首次失败后重跑通过的。这套流程手动敲起来字太多很容易路径出错建议写成脚本。我提供一个简化版的 shell 脚本按日期自动归档结果#!/bin/bash set -e STAMP$(date %Y%m%d%H%M%S) mkdir -p runs/${STAMP} robot -d runs/${STAMP}/run1 tests if [ -f runs/${STAMP}/run1/output.xml ]; then robot --rerunfailed runs/${STAMP}/run1/output.xml --outputdir runs/${STAMP}/run2 tests || true rebot --output runs/${STAMP}/combined.xml --merge runs/${STAMP}/run1/output.xml runs/${STAMP}/run2/output.xml fi|| true在这里很关键因为重跑阶段用例仍有失败robot 命令会返回非零退出码如果不加这个脚本会直接中断后面的报告合并就执行不到了。3.4 第三步升级到 --retry 内置重试RF 5.1如果你确认自己装的是 RF 5.1 及以上可以直接用--retry替代上面的脚本体验会好很多robot --retry 2 --retry-interval 5s --outputdir results tests跑完看 log.html每条失败用例的标题下会有类似“1 / 3 attempts”的展示意思是这条用例一共尝试了3次其中第1次失败后2次通过或继续失败。相比手动脚本这种方式生成的报告不需要额外合并对团队协作更友好因为任何人打开 log.html 都能直观看到重跑过程。有一点需要注意--retry是针对所有失败用例统一设置策略如果你想对某些用例单独控制是否允许重试需要通过标签或前置修改器prerunmodifier做更细粒度的定制内置参数满足不了这个需求。3.5 第四步接到 Jenkins 里让夜间任务自己跑重跑机制放在本地命令跑一次很容易真正产生价值的是把它接入 Jenkins 自动化部署流程。我一般用 Pipeline 方式这样重跑、报告发布、结果通知都在同一个流水线里谁都能看到。下面是一个可用的 Declarative Pipeline 示例pipeline { agent any stages { stage(Run RF Tests) { steps { catchError(buildResult: UNSTABLE, stageResult: FAILURE) { sh robot --retry 2 --retry-interval 10s --outputdir results tests } } } stage(Publish Report) { steps { publishHTML([ allowMissing: false, alwaysLinkToLastBuild: true, reportDir: results, reportFiles: log.html, reportName: RF Test Report ]) } } } }这里catchError的作用是把构建标记为 UNSTABLE 而不是直接 FAILURE这样重跑后仍有失败时Jenkins 不会把构建直接打成红色而是橙色便于区分“测试失败”和“构建异常”两种状态。配合 Jenkins 的定时构建设置每天凌晨2点跑一次早上到公司打开消息面板就能看到结果。如果公司已经有部署流水线你可以把这个测试阶段放在部署任务之后作为上线前的质量闸门测试没通过自动阻断发布。4. 重跑逻辑里的关键细节与参数解读4.1 重跑次数和间隔怎么定这个没有标准答案但有一个经验区间接口自动化建议重跑1次就够因为接口返回要么成功要么失败状态收敛很快UI自动化最多重跑2次因为页面加载超时这类假失败往往需要一定的缓冲时间。重跑超过2次基本就是掩耳盗铃了真实的偶发缺陷也会被“跑赢”过去。时间的账也要算清楚。假设你有1000条用例单条平均执行5秒单轮全量约1.4小时如果失败率是5%也就是50条失败重跑一轮只增加250秒大约4分钟。相比全量重跑增量重跑的成本非常低这也是为什么我一直推荐只重跑失败用例而不是重跑全量。重跑间隔同样重要。很多假失败是环境刚重启服务还没完全就绪此时立刻重试大概率还是失败。间隔5到10秒是比较合理的范围既不会让流水线等太久也给了环境缓冲的时间。在CI环境里如果重跑前能先去探测一下服务健康检查接口等健康了再重跑成功率会明显更高。4.2 重跑之前的恢复动作不能省重跑不是机械地重复执行用例它本质上是在给环境第二次机会所以重跑前一定要做恢复动作否则第二次跑可能仍然撞在同一个坑里。恢复动作至少包含三类。第一类是数据清理把第一次执行产生的残留数据清掉比如重复创建的订单、遗留的测试用户。第二类是登录态恢复有些用例会修改账号状态重跑前要把账号密码重置回初始状态。第三类是依赖服务检查确保中间件、数据库、第三方接口都处于可用状态而不是还在重启中。在Robot Framework里我通常用 Suite Setup 来做机制性的恢复检查。如果环境检查失败直接让整个套件跳过执行而不是跑一堆注定失败的用例。一个典型的做法是在 resources/common.robot 里定义一个 Health Check 关键字然后在套件设置里调用它。我实际踩过一个坑第一次做重跑方案时没做数据清理用例第一次失败是因为创建了重复用户第二次重跑时用户还在库里于是又失败。连续重跑三次全部失败最后才发现根因不是功能问题而是我的重跑方案漏了数据复位。后来在用例 Teardown 里统一加上数据清理步骤重跑才真正开始有意义。4.3 真失败和假失败一定要在报告里分清楚重跑之后最忌讳的事情就是报表依然只显示“通过率95%”这种笼统数字。重跑通过和一次通过在质量语义上是完全不同的前者说明用例对环境依赖敏感后者才说明功能本身靠谱。所以报告里一定要把这两类情况拆开。方法一用 rebot 合并报告后每条用例下有多次尝试记录人工可以判断。方法二在重跑命令里给重跑通过的用例自动添加一个retry-passed标签后续统计时专门看这个标签的数量变化。方法三在 Jenkins Pipeline 里写一个小脚本解析 output.xml把“首次失败但重跑通过”的用例单独列表推送给相关开发。我倾向于方法三因为它的提示最显眼不依赖每个人去翻log.html里的细节。邮件通知文案我也建议改一改不要光写“本次构建失败”而是写清楚“本次有 N 条用例首次失败重跑后通过请确认是否存在 Flaky Test”。这句话的实际价值远大于一个红色的构建状态因为它能把团队注意力引向真正需要处理的问题。4.4 哪些场景不适合自动重跑重跑不是万能药有几类用例我是坚决不开启自动重跑的。第一类是数据敏感的用例比如支付、下单、扣库存这类场景重跑极有可能造成重复扣款或重复下单污染业务数据这种问题比分红还严重。第二类是强时序用例依赖实时数据的行情、信令、轮询场景重跑没有意义因为数据已经发生了不可逆变化。第三类是性能测试和压力测试这类测试的目标就是考察系统能否扛住压力、在极限状态下表现如何如果你给它加重新跑等于把故障躲掉了完全失去了测试价值。最后是故障恢复类用例本来就是要验证故障场景下的表现重跑等于没了故障。一句话总结重跑只能用于“预期结果相同、只是环境暂时没跟上”的场景。任何“结果不可幂等”的用例都不应该放进自动重跑的名单里。5. 常见问题与排查技巧实录5.1 重跑后 output.xml 互相覆盖报告合并出错这个是我见过最多的新手问题。症状是跑完第二次之后第一次的 output.xml 不见了或者合并时报错找不到文件。原因很简单robot 默认生成的文件名固定叫 output.xml两次执行如果输出到同一个目录后一次就把前一次覆盖了。解法是每个执行阶段用独立的 outputdir或者用--output参数指定不同的文件名。我的习惯是按时间戳建目录每次执行都写到独立目录里。排查的时候也可以先用find . -name output.xml -mmin -10看看最近生成的文件有哪些确认哪些文件还在、哪些被覆盖了。还要注意一个细节如果用了--exitonfailure它会让测试在第一条失败用例处停止这会使--rerunfailed读取到的失败信息不完整导致后续重跑范围偏小。如果你的目标是收集所有失败用例并统一重跑不要开这个参数。5.2 用 rm -rf 清理输出目录时手滑把测试脚本删了这个必须单独拿出来讲因为我自己就真犯过这种错。当时想清理前一天的测试结果目录敲了rm -rf results_20260601结果因为我是用脚本变量拼目录名变量没赋值命令实际变成了rm -rf results_加一个空字符串参数差点把整个项目目录删掉。还有一种更经典的错误是rm -rf ./ results_xxx多了一个空格语义就从“删除指定目录”变成了“删除当前目录以及指定目录”后果不堪设想。我的教训是清理命令执行前先pwd确认当前在哪里再ls确认要删除的路径确实存在且名字正确最后才执行 rm。更好的是不要在 shell 里裸写 rm -rf而是写一个清理脚本脚本内部判断目录名是否以预期前缀开头不是就拒绝执行并报错。有人会问rm -rf *这种误删到底能不能恢复。如果删除后立刻停止写入部分小文件确实可以用数据恢复工具找回来但目录结构通常已经乱了测试脚本这种单个小文件找回成本很高。所以重点一定是预防尤其是CI机器上尽量让每个构建生成独立目录不要依赖手动清理。5.3 pabot 并发 重跑导致账号互踢、数据冲突用pabot做并发重跑一个非常典型的翻车场景是第一次全量跑并发8个进程没问题重跑时却一堆用例失败看日志全是登录超时、401、会话不存在。原因很简单重跑把此前失败的那批用例集中在一起而它们如果共用同一个测试账号并发重跑时账号会被互相顶下线。解法有两个方向。一个方向是降低重跑阶段的并发数比如首次跑用--processes 8重跑时用--processes 2让重跑任务的资源竞争小一些。另一个方向是数据隔离给每个并发进程分配不同的测试账号、不同的数据前缀从根上避免冲突。我推荐优先做数据隔离因为它不只在重跑时有用在首次并发执行时同样能防止大量用例互相干扰。如果你确实无法做数据隔离也可以考虑在套件层面加锁但Robot Framework层面做跨进程锁比较笨重成本不低能不做尽量不做。5.4 重跑通过了但缺陷其实是真实存在的这个现象最有迷惑性。一条用例怎么跑都失败你开了重跑机制第三次终于变绿了大家松了一口气。结果过两天真实用户踩到了同样的缺陷生产事故复盘时才发现那条用例在测试环境里早就暴露过问题只是被重跑“救”过去了。原因是很多bug是概率性触发比如偶发的空指针、竞态条件、缓存不一致用例本身已经碰到了缺陷但因为重跑次数够多总有一次碰巧绕过去了。这种情况下重跑不是修复问题而是掩盖问题。我的应对办法是给“重跑通过”的用例打上独立标签单独生成一个“重跑通过用例清单”并且设立一个规则——同一条用例连续三天出现在重跑通过清单里就自动生成一条issue推给开发排查。这个规则执行起来非常简单但效果特别好它既给了环境抖动保底的容忍度又不会让重跑成为质量问题的遮羞布。6. 从重跑机制延伸到自动化测试的底层思维说到这我想多聊一句关于自动化测试方向本身的体会。现在各大公司面试自动化测试岗位时重跑策略几乎是必问的考点但它绝不是背一个命令就能过关的。面试官真正想听的是你对“自动化结果如何被团队信任”这个问题的理解。你能不能在方案里区分真失败和假失败能不能防止重跑掩盖缺陷能不能把重跑做成一个闭环流程这些才是拉开差距的地方。另外我最近还在尝试把AI能力引入到重跑后的结果分析里让自动化脚本在发现“重跑通过的用例”时自动聚合根因比如定位到都是“登录超时”、“某个元素找不到”这两个共性根因然后直接在工作群里对应负责人。这个思路在接口自动化和UI自动化框架阶段可以提前预留接口比如在output.xml解析阶段就把失败信息结构化存储后面无论是人工分析还是AI分析都有数据基础。从我个人经验看整个重跑方案做下来最核心的一句话是重跑是手段不是目的。它解决的是环境噪音但绝不能代替你去修根因。现在每天到公司我第一件事不是看通过率而是打开重跑趋势报告看看过去一周哪些用例反复出现在“重跑通过”名单里连续两天出现的直接提给对应开发。这才是重跑机制给我带来的最大价值——让团队从每天判断“这红是不是真的”这种无效劳作里解脱出来把精力放到真正可能变成线上事故的风险信号上。希望这篇关于基于RF自动化重跑的方案整理能帮你把CI里的自动化测试做得更省心也少走一点我走过的弯路。