系列06-Playwright UI 自动化 AI 自愈实战定位器失败如何自动修复做过 UI 自动化的同学几乎都踩过这个坑产品把按钮文案从「提交订单」改成「立即下单」30 条用例 overnight 全红。测试开发花半天改 XPathPR 还没 merge nightly 又跑了一轮。业界把这类能力叫Self-healing自愈步骤因locator 失效失败时不立刻判死刑而是让 AI 结合步骤语义 当前页面 DOM试一组候选定位器短超时重试成功则本次执行继续确认无误后再写回用例资产。本文基于开源平台BrickCore的实现讲清什么时候有效、怎么开、源码怎么走。即使不用该平台Runner 采集 DOM → Backend LLM → 候选重试 → 人工确认写回的设计也可复用到自建框架。先看效果在线演示与体验入口不用 clone 代码可以直接打开官方功能演示页看「UI 定位器自愈」录屏约 12 分钟能看懂全流程项地址演示首页含自愈章节http://43.142.83.156/showcase/直达自愈录屏http://43.142.83.156/showcase/#ui-heal平台在线体验http://43.142.83.156/ admin / BrickCore123456UI 录制/自愈试跑页http://43.142.83.156/showcase/demo-ui.html demo / demo123演示页说明与线上能力一致用例执行定位失败 → 平台结合页面快照由 AI 推荐新定位器并自动重试 → 报告内可写回用例见 BrickCore 功能演示 中「UI 定位器自愈」一节。建议阅读顺序先看#ui-heal录屏 → 再按下文第五节自己跑一条「故意写错 locator」的用例 → 对照第六节源码。一、为什么 locator 是 UI 自动化第一大维护成本写法典型失败原因绝对 XPath/html/body/div[3]/...DOM 层级一改就断绑死文案text提交订单文案/国际化/改版仅 class.btn-primary样式重构、多个按钮撞车动态 id#el-id-8848每次构建 id 变Playwright 官方推荐getByRole、data-testid但历史资产里往往堆满 XPath。全量重写不现实自愈针对的是「小改还能救」的那一批。二、AI 自愈解决什么、不解决什么✅ 适合自愈❌ 不要指望自愈按钮 class/文案微调整页重构、流程删除同级 DOM 顺序小变新增弹窗、缺步骤单个元素属性变化业务逻辑变更老用例续命争取改 selector 的缓冲期替代 push 前端加 test-id结论自愈是降本不是免维护大改版仍要人工或重新录制。三、一次自愈的完整链路UI 步骤执行click_ele / fill_value … ↓ 原 locator 超时 / 找不到 Runner是否在 HEALABLE_METHODS 且 ai_heal_enabledtrue ↓ 是 capture_page_context → aria_snapshot 可见元素列表≤80 ↓ POST /ai/generate/locator-heal/internalX-Internal-Token ↓ Backend heal_locatorPromptManager「ui_locator_heal」→ LLM → 新 locator ↓ 后端校验非空、≠旧值、文案不能「缩小匹配范围」 Runnerapply_healed_locator 替换本步 locator**立即重试一次** ↓ 成功 → 本步继续报告步骤详情带 locator_healed原 → 新 ↓ 用户在报告点「写回用例」/「写回全部自愈」→ apply-to-case 持久化三个入口同一套 Backend 逻辑入口谁触发场景Runner 自动步骤异常且ai_heal_enabledtrue套件/计划 nightly 续命步骤编辑页人工点「AI 自愈」调试单步 locator调/ai/generate/locator-heal报告写回「写回自愈定位器」/「写回全部自愈」确认后apply-to-case持久化四、实战案例改 class 名后如何「救」回来背景某步 desc 为「点击提交按钮」原 locatorcss.btn-submit前端把 class 改成.btn-primary用例执行报错Timeout 20000ms exceeded。自愈后示例非固定输出get_by_rolebutton,name提交 或 button:has-text(提交)报告侧Runner 重试成功后步骤结果里会带locator_healed: { original, new }见runner/WebEngine/runner.py写入step_info。用例 JSON 里仍是旧 locator直到你在用例报告时间线点击「写回自愈定位器」或「写回全部自愈 (N)」——前端CaseReportTimeline.vue调apply-to-case才落库。错误示范Backend 会拒绝原意图「基础设置」AI 若返回只匹配「设置」的宽泛 locator_reject_shortened_text_match会拒掉避免点到别的「设置」链接——这是质量上比裸调 LLM 多的一层安全网。五、如何开启与自测6 步Step 0看演示可选打开 http://43.142.83.156/showcase/#ui-heal 对照录屏要在平台里亲手试继续下面步骤。Step 1LLM 与场景绑定平台配置 → AI 模型配置LLM 模型配置Tab新增并启用一条模型如 DeepSeekAPI Key 测通场景绑定Tab为locator_healUI 定位器自愈绑定上述模型Runner 自动自愈、步骤编辑页手动自愈都走_get_ai_config(..., scenelocator_heal)。Step 2项目自愈策略同一页面「执行与自愈」Tab策略存Project.global_vars.ai_settingsBackend 计算后写入 MQ 的ai_heal_enabled配置项含义默认启用定位器自愈项目总开关开执行时默认开启跑用例/套件/计划时的默认值开允许运行弹窗覆盖运行弹窗里能否临时关自愈开页面提示Runner.env的AI_HEAL_ENABLED仅运维熔断日常以项目配置为准。运行 UI 用例/套件/计划时若允许覆盖弹窗里可看到「AI 自愈」开关Case.vue/Task.vue/Suite.vue。Step 3Runner安装 BrickCoreRunner Release连接 http://43.142.83.156/ 并上线设备。Step 4准备页面与用例试跑页http://43.142.83.156/showcase/demo-ui.htmldemo / demo123或业务测试环境复制一条 UI 用例故意改错某步params.locatorStep 5执行并观察跑单用例或套件。Runner 日志示例[case_id] AI 自愈定位成功: css.btn-submit - get_by_rolebutton,name提交报告步骤详情会出现自愈信息原 locator → 新 locator。Step 6写回用例可选在报告时间线对该步「写回自愈定位器」或点多处自愈时的「写回全部自愈 (N)」→ 确认后调用POST /ai/generate/locator-heal/apply-to-case更新case.steps[step_index].params.locator。六、源码视角Runner → Backend → 安全校验6.1 Runner 采集与调用runner/tools/locator_heal.pyHEALABLE_METHODSfrozenset({click_ele,fill_value,hover,wait_for_element,kw_assert_visible,kw_assert_element_text,extract_text,...})deftry_heal_step(page,step,error_msg):snapshot,elementscapture_page_context(page)# aria JS 抓可见元素payload{method:method,failed_locator:failed_locator,step_desc:step.get(desc)or,error_message:(error_msgor)[:1000],page_url:page.url,accessibility_snapshot:snapshot[:50000],page_elements:elements,}resprequests.post(f{BASE_URL}/ai/generate/locator-heal/internal,jsonpayload,headersrunner_auth_headers(),timeout90,)仅点击/输入/断言/提取等与元素相关的关键字会走自愈纯等待、自定义脚本不在集合内避免误伤。6.2 Runner 引擎失败 → 自愈 → 重试runner/WebEngine/basecase.py步骤执行核心exceptExceptionase:ifpageandself.config.get(ai_heal_enabled):fromtools.locator_healimporttry_heal_step,apply_healed_locator new_locatortry_heal_step(page,step,str(e))ifnew_locator:retry_stepapply_healed_locator(step,new_locator)retry_step[_healed]{original:orig,new:new_locator}success,resultself._step_executor.execute(retry_step)self._last_step_healretry_step.get(_healed)returnresultraise要点Backend 一次返回一个通过校验的 locatorRunner只重试当前这一步不会 silent 改库里的 steps。报告里的locator_healed供人工确认后再写回。6.3 Backendheal_locatorbackend/app/core/ui_locator_heal.pyasyncdefheal_locator(...,call_llm,...):ifmethodnotinHEALABLE_METHODS:return{success:False,reason:f方法{method}不支持 AI 自愈}# snapshot 优先级Runner 上传 aria → page_elements → 按 page_url 拉 DOMsystem_prompt,user_promptawaitPromptManager.render(ui_locator_heal,{...})parsed_extract_json_object(awaitcall_llm(...))new_locatornormalize_locator(parsed.get(locator)or...)ifnew_locatorfailed_locator:return{success:False,reason:建议定位器与原定位器相同}shorten_reason_reject_shortened_text_match(failed_locatorfailed_locator,new_locatornew_locator,step_descstep_desc)ifshorten_reason:return{success:False,reason:shorten_reason}return{success:True,locator:new_locator,confidence:...}要点Prompt 模板在core/ai_prompts.py的ui_locator_healsnapshot 优先级Runner 上传 aria→page_elementsDOM 列表 → 仅传page_url时 Backend 拉取编辑页手动自愈常用6.4 写回用例需权限generate.py→apply_healed_locator_to_case更新steps[step_index].params.locator并清理冗余selector字段。必须人工确认默认自愈仅本次执行生效防止 AI 污染资产。七、与录制、步骤片段、失败分析的分工手段作用时机录制 / Agent新用例、更稳 locator新功能步骤片段登录等公共流程改一处日常维护AI 自愈老用例小改版续命发版后 nightly 红了一大片AI 失败分析平台另能力解释日志、归类原因自愈仍失败时不要混业务流程多了「同意协议」弹窗 → DOM 里根本没有目标元素 →应加步骤或重录不是自愈能解决的。八、常见失败排错现象原因处理从不触发自愈项目locator_heal_enabledfalse项目 AI 设置打开从不触发自愈运行弹窗关了 AI 自愈运行 UI 任务时选「开启」401/403 internalRunner Token / INTERNAL_API_KEY对照 Runner 连接配置自愈失败无法 snapshot无头页未加载完 / 页面空白加 wait查截图自愈失败文案缩小被拒安全校验生效人工改 locator 或改 desc 更明确本次绿、下次又红未在报告写回点「写回自愈定位器」或「写回全部自愈」LLM 乱给 idPrompt/模型弱换更强模型推动 test-id九、和纯 Playwright 脚本方案对比本地 Playwright 自写 heal平台 AI 自愈DOM 采集自己写Runner 内置 aria 元素列表LLM自己接 API场景化 Prompt 校验写回改 Git 代码Web 采纳写回 steps JSON权限/审计无RBAC 可选记录适用单仓库脚本多人在 Web 维护步骤十、小结AI 自愈 步骤失败 → DOM/aria desc → LLM 新 locator →Runner 重试本步。适合小改不适合新流程/大重构。报告展示原→新持久化须报告写回 / apply-to-case。Backend_reject_shortened_text_match防文案缩小误点。先看http://43.142.83.156/showcase/#ui-heal再动手配置。与test-id、片段、录制组合维护成本最低。附录 A源码文件索引进阶读码顺序文件关注点1runner/tools/locator_heal.py触发、采集、internal API2core/ui_locator_heal.pyheal_locator、安全校验3routers/ai/generate.pylocator_heal/internal/apply-to-case4core/ai_project_settings.py三档项目开关5routers/ui/exec.pyresolve_locator_heal_for_execute→ MQai_heal_enabled6runner/WebEngine/basecase.py异常捕获、重试、_last_step_heal7frontend/.../CaseReportTimeline.vue报告写回 / 批量写回关于 BrickCore项链接自愈章节直达http://43.142.83.156/showcase/#ui-heal在线体验http://43.142.83.156/ admin / BrickCore123456源码https://gitee.com/BanZhuanKeOrz/BrickCore支持与交流觉得有用欢迎Star⭐问题反馈Gitee Issues 或评论区留言