你录了一条后台系统的用例:填写表单,点击"保存",返回列表,打开刚创建的记录。手工操作时,每一步都很顺;自动回放时,却偶尔在列表页报"找不到记录",重跑又通过了。
第一反应往往是:"在保存后等 5 秒吧。"这可能暂时让用例变绿,但也留下两个问题:快的时候白等,慢的时候 5 秒仍不够。更关键的是,页面能继续操作,不代表本次业务结果已经出现。要让回归测试跑得稳,得先分清自己在等什么。
页面打开了,为什么还不能马上点?
一次页面操作通常会经历几个时刻:浏览器完成导航、前端显示骨架屏、接口返回数据、按钮解除禁用、列表渲染新记录。它们不会同时发生。
例如点击"保存"后,系统可能先显示成功提示,再刷新列表;列表区域已经出现,目标记录却还没有更新。自动化如果把"成功提示出现"当作整条流程的终点,就可能漏掉真正的业务错误。
把等待目标分清楚,会更容易选择处理方法:
| 要等什么 | 常见场景 | 可以观察的信号 |
|---|---|---|
| 页面加载 | 进入新页面、切换标签页 | 加载状态结束,目标页面出现 |
| 元素可操作 | 按钮、输入框、下拉选项稍晚渲染 | 目标出现,且没有禁用或被遮挡 |
| 业务结果成立 | 保存、审批、异步任务 | 本次记录出现,状态或关键字段更新 |
| 一段固定时间 | 短动画、暂时没有可靠信号的局部组件 | 设定的等待时间结束 |
前三种都有明确的状态目标;最后一种只是时间过去了。能用状态表达的地方,尽量不要只靠计时。
CueCast 如何处理等待:先看状态,再决定何时执行
回演 CueCast 对等待做了比较多的逻辑处理。
CueCast 的等待并不是简单地在每个步骤之间暂停几秒。录制时保存的目标元素信息,会在回放时用于重新定位;目标暂时没出现,回放会在限定窗口内重复查找,而不是第一次没命中就失败。页面有可识别的 loading 状态时,还会单独观察加载是否结束。这样,正常的页面加载不必全靠手工估算等待时长。
定位到元素,也不意味着马上发送点击。对点击等交互步骤,回放还会检查目标是否真正可操作:例如按钮是否被禁用、组件是否还在 loading、输入框是否只读、目标是否被遮罩挡住。先确认目标,再确认能否操作,条件满足就继续执行。如果页面其他区域仍有加载提示,但当前目标已经可以操作,也无需为无关区域一直等待。
这套方式能适应"有时 1 秒、有时 5 秒"的正常波动:快的时候尽早继续,慢的时候在等待窗口内继续检查。等待仍有明确上限。如果目标始终没有出现、一直不可操作,或者页面已经报错,CueCast 会结束当前步骤并给出失败信息,不会无限卡住;同一步的多次定位也受统一的等待预算约束,避免查找次数叠加成漫长的隐性等待。
手工配置是这套机制的补充。遇到短动画、局部组件需要额外缓冲,或页面暂时没有可靠的就绪信号时,可以在用例详情中给当前步骤设置"执行前等待",单位为毫秒。例如展开高级筛选后,面板动画偶尔影响下一步输入,就可以只为输入步骤增加一小段等待,再单条回放验证。它是固定时间:设置 3 秒,每次都会等满 3 秒,因此不宜给所有步骤统一加上等待。
这些处理回答的是"下一步操作何时可以执行"。按钮可点击仍不能证明数据已保存、审批已完成或异步任务已有最终结果;业务是否成功,要通过后面的结果断言确认。

点击成功以后,还要等"本次业务结果"
继续看创建记录的例子。下面三句话看似接近,验证的其实是三件事:
- "保存按钮可以点击":证明页面允许发起操作。
- "页面出现保存成功":证明页面给出了提交反馈。
- "本次新建记录出现在列表中,字段和状态正确":才证明这条回归用例关心的业务结果。
前两件事不能代替第三件。尤其是在异步处理的系统里,成功提示可能表示"请求已受理",实际结果稍后才可见。
录制用例时,可以给本次记录填写唯一标识,例如 回归记录-{时间戳}。点击保存后,进入列表查找这个标识;再对该记录的名称、状态或详情字段增加断言。这样等待的目标是本轮运行产生的对象,而不是列表里任意一条相似的旧记录。
CueCast 的文本断言支持"等待断言成立"和"立即检查"。对于列表刷新或状态更新,通常选"等待断言成立",让同一个明确的预期在限定窗口内出现;如果业务要求点击后立刻呈现某状态,才选择"立即检查"。断言也有时间上限,长期没有得到预期结果,应当报告失败,而不是继续无限等待。
要留意一种反向断言:刚点完删除就立刻检查"列表不包含该记录",此时列表若仍在加载,暂时看不到记录并不能证明删除成功。应先确认列表已加载或刷新完成,再判断本次记录确实消失。
超时了,先看现场,再决定改哪里
"超时"只是结果,不是原因。同样是等待目标失败,可能是接口真的变慢、页面出现错误、按钮被遮罩挡住、用例进错页面,也可能是目标定位已随改版失效。
遇到超时,可按下面顺序排查:
- 看失败步骤和截图。 页面还在 loading,已经显示业务错误,还是停在了意料之外的页面?
- 看目标元素。 它不存在、已出现但不可操作,还是页面上有多个相似元素导致定位错误?
- 回查上一步。 保存或跳转是否真的发生?目标数据是不是根本没创建成功?
- 确认等待目标。 此处应该等元素可点击,还是等列表中的本次记录出现?
- 做局部修复。 修正前置操作、定位或断言;确有局部缓冲需求时,才配置执行前等待。修改后先单条回放,再放回执行计划。
| 看到的现象 | 优先检查 | 常见处理 |
|---|---|---|
| 截图里仍有 loading 或骨架屏 | 页面与接口状态 | 确认加载能结束、目标最终会出现 |
| 按钮已出现,却不能点击 | 禁用状态、遮罩、动画 | 等待可操作状态;必要时局部设置执行前等待 |
| 点击已完成,列表没有新记录 | 提交结果与异步业务处理 | 查本次记录,补业务结果断言 |
| 页面已经报错,却一直在找按钮 | 登录、权限或业务错误 | 先修页面错误与前置条件 |
| 页面正常,但总找不到同一个目标 | 定位与页面改版 | 修定位或局部重录,而非一味增加超时 |
不要把"再等久一点"当成所有超时的答案。 如果系统本来应该在合理时间内完成,持续变慢就是需要发现的问题;如果目标定位写错,等待再久也不会命中正确对象。
让每一次等待都有明确目的
稳定的 UI 回归用例不需要到处填固定等待。CueCast 在回放时自动寻找目标、检查能否操作,能减少常规异步加载带来的手工配置;"执行前等待"让特殊步骤仍可按需调整;结果断言则回答业务是否真的成功。
下次遇到超时,可以先问一句:我希望页面出现什么变化,才允许这条用例继续? 把这个变化写进步骤或断言,再根据失败现场修正等待方式,比给整条用例统一加几秒更可靠。