1. 为什么 AI UI 测试进了生产就“崩”先看清最被低估的 Harness 层AI UI 测试这件事本地演示时几乎人人满意自然语言写一句“点击登录按钮”模型就能把浏览器点得明明白白成功率看着有九成。可一旦把它塞进生产流水线跑真实数据、跑并发、跑长链路成功率经常掉到六成甚至更低。问题往往不在模型“不够聪明”而在模型之上少了一层东西——Harness。Harness 是什么你可以把它理解成 AI UI 测试的“调度台 安全气囊 记忆本”。执行引擎比如 Midscene、Browser-Use、Skyvern 这类只负责把自然语言翻译成浏览器动作它不管失败怎么兜底、Token 怎么省、经验怎么沉淀。真正决定一套 AI UI 测试能不能上生产的是 Harness 层失败分类、自愈策略、Token 缓存、知识注入、可观测性、调度编排。这篇就围绕 AI UI、测试、Harness、Token、自愈这几个关键词给出一份可复制的 Harness 配置骨架和自愈规则示例并演示在生产数据回放下的验证动作。适合正在把 AI 测试从 demo 推向生产的测试工程师、QA 负责人和平台开发者。全文以“能跟做”为目标配置和命令都可以直接抄。2. 前置准备TaoToken 接入与执行引擎选型2.1 为什么需要 TaoToken 这一层AI UI 测试的每一步“看页面、想动作、写断言”都要调用大模型。如果每个执行引擎各自直连模型你会遇到三个麻烦密钥散落各处、Token 账单无法归集、模型切换要改一堆配置。TaoToken 提供统一的 API 入口把模型调用收敛到一处Harness 层只需要面向一个 endpoint 编程。官网入口在这里https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 这个不加 UTM。你需要在控制台创建密钥然后把它注入到 Harness 的环境变量里而不是写死在代码中。2.2 拿到 API Key 并配置环境进入控制台创建密钥https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 密钥管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。创建后建议按环境分 key比如dev、ci、prod各一把方便按环境统计 Token。配置到环境变量Harness 启动时读取export TAOTOKEN_API_KEYsk-你的密钥 export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_MODELclaude-sonnet注意不要把密钥提交进 Git。CI 里用平台的 Secret 管理本地用.env并加入.gitignore。2.3 执行引擎与 Harness 的分工选执行引擎时别只看 demo 好不好看。要问五个问题失败信号是否结构化、日志能否被外部订阅、执行过程能否被干预、能否被外部知识增强、API 能否纳入调度。这五点决定了你后面能不能做自愈和记忆。执行引擎负责“点”Harness 负责“点失败了怎么办、点贵了怎么省、点对了怎么记住”。下面所有配置都围绕 Harness 展开执行引擎可以替换Harness 骨架不变。3. 可复制的 Harness 配置骨架3.1 目录结构先约定一个最小可用的工程结构后面所有文件都放这里harness/ ├── config/ │ ├── harness.yaml # 主配置 │ ├── self_heal.yaml # 自愈规则 │ └── knowledge.yaml # 页面知识库 ├── runner/ │ ├── orchestrator.py # 编排入口 │ └── token_cache.py # Token 缓存 ├── cases/ │ └── login_flow.yaml # 用例 └── reports/3.2 主配置 harness.yaml这份配置把执行引擎、模型、缓存、自愈、可观测性串起来engine: type: midscene # 可替换为 browser-use / skyvern headless: true timeout_sec: 900 model: base_url: ${TAOTOKEN_BASE_URL} api_key: ${TAOTOKEN_API_KEY} name: ${TAOTOKEN_MODEL} max_retries: 2 cache: enabled: true backend: sqlite path: ./reports/cache.db ttl_hours: 72 self_heal: enabled: true rules_file: ./config/self_heal.yaml confidence_threshold: 0.75 # 高于此值自动应用修复 knowledge: enabled: true file: ./config/knowledge.yaml observability: log_stream: true screenshot_on_fail: true structured_error: true关键参数说明confidence_threshold是自愈的“自动应用门槛”设太高会频繁弹人工审核设太低会乱改cache.ttl_hours决定缓存多久失效生产建议 48–72 小时产品迭代快就调小。3.3 用例文件 login_flow.yaml用例用自然语言描述意图Harness 负责翻译成动作name: login_flow steps: - aiAct: 点击页面顶部的“密码登录”标签 - aiAct: 在用户名输入框填入 ${USERNAME} - aiAct: 在密码输入框填入 ${PASSWORD} - aiAct: 点击登录表单底部的“登录”按钮 - aiAssert: 页面出现“控制台”字样${USERNAME}这类占位符由 Harness 在执行时注入避免把测试数据写死在用例里。3.4 编排入口 orchestrator.py这是 Harness 的心脏负责串起缓存、执行、自愈、记忆import os, yaml, time from runner.token_cache import TokenCache class Orchestrator: def __init__(self, cfg_path): self.cfg yaml.safe_load(open(cfg_path)) self.cache TokenCache(self.cfg[cache]) def run_case(self, case_path): case yaml.safe_load(open(case_path)) cache_key self.cache.make_key(case) cached self.cache.get(cache_key) if cached: return self._replay(cached) result self._execute(case) if not result[ok] and self.cfg[self_heal][enabled]: result self._self_heal(case, result) if result[ok]: self.cache.set(cache_key, result) return result def _execute(self, case): # 调用执行引擎返回结构化结果 ... def _self_heal(self, case, result): # 见第 4 节自愈规则 ...make_key用用例内容 环境指纹生成缓存键环境变了缓存自动失效避免“缓存命中但页面已改”的假通过。4. 自愈规则示例从失败分类到置信度门控4.1 失败分类器自愈的第一步是理解失败。把失败分成可处理的门类每类配默认对策# self_heal.yaml rules: - type: wait_timeout action: extend_wait extra_sec: 10 retry: 2 - type: element_not_found action: deep_locate fallback: ai_diagnose - type: assertion_failed action: ai_diagnose - type: network_unreachable action: backoff_retry retry: 3 - type: login_expired action: re_login - type: unknown action: mark_skip分类太粗策略不精准太细证据不足判不准。实践中 8–16 类是平衡点先用真实失败样本校准。4.2 自愈闭环分类完成后走闭环失败信号 → 分类 → 选分支 → 诊断 → 生成修复 → 置信度门控 → 重试 → 固化。核心是“不是所有修复都自动应用”def _self_heal(self, case, result): rule self._classify(result[error]) if rule[action] mark_skip: return result patch, confidence self._diagnose(case, result, rule) if confidence self.cfg[self_heal][confidence_threshold]: self._apply_patch(case, patch) return self._execute(case) else: self._queue_for_review(case, patch, confidence) return result高置信自动应用低置信弹窗人工审核附上 diff 和自然语言解释。这样既不让 QA 看不过来也不让 AI 乱改。4.3 深度重定位落入 AI 诊断一个常见坑深度重定位和模型降级都失败后直接放弃其实元素只是改名了。修复方式是让 deep_locate 失败后落入 AI 诊断分支给模型一次用新名字或按位置定位的机会。这个改动通常能把“元素改名”类失败从救不回变成救回。5. 生产数据回放下的验证动作5.1 回放脚本生产验证不能只跑一次 demo要用真实数据回放。写一个回放脚本把生产采集的用例批量喂给 Harnesspython -m runner.replay \ --cases ./cases/prod_replay/ \ --config ./config/harness.yaml \ --report ./reports/replay_$(date %Y%m%d).json回放时重点看三个指标成功率、单次 Token、单次耗时。这三个数字决定能不能规模化。5.2 验证 Token 缓存效果第一次跑cache miss和第二次跑cache hit对比是判断缓存是否生效的最直接方式# 第一次冷缓存 python -m runner.replay --cases ./cases/login_flow.yaml --no-cache # 第二次热缓存 python -m runner.replay --cases ./cases/login_flow.yaml实测下来一条 19 步的用例冷缓存可能烧掉几十万 Token热缓存能降到十分之一左右。Token 不是优化项是生产化的前提——没有缓存月成本会高到没人敢签字。5.3 验证自愈是否可控自愈必须能被关掉否则关键场景不敢用。验证两个方向# 关闭自愈失败用例应明确跳过自愈 python -m runner.replay --cases ./cases/fail_case.yaml --no-self-heal # 开启自愈应走深度重定位 AI 诊断 python -m runner.replay --cases ./cases/fail_case.yaml日志里要能清楚看到“跳过自愈”或“触发自愈”的字样配置随运行记录持久化方便复盘。5.4 验证知识库注入知识库把页面元素的语义和位置结构化注入到 prompt 里当锚点# knowledge.yaml elements: - name: login_tab semantic: 密码登录 location: 登录页顶部 tab 区域 - name: login_button semantic: 登录按钮 location: 登录表单底部注入后冷缓存 Token 会略涨但热缓存恢复正常且稳定性提升。这是长期投资短期贵一点长期省心。6. 本篇常见错排查6.1 缓存命中但结果不对多半是缓存键没把环境指纹算进去。页面改了、账号换了、模型版本变了缓存键都应该变。检查make_key是否包含用例内容、环境变量、模型名。6.2 自愈越修越乱先看失败信号是否可信。日志里如果有Continue on error这类配置行被当成错误AI 会基于假错误诊断。加一层真实错误提取只扫waitFor timeout、Assertion failed这类真错误行。6.3 记忆写入卡死主流程每跑一次同步写一批记忆记录会把执行线程卡住接口返回空。把写入挪到独立后台线程主流程只入队不等落库读取仍保持同步。主流程耗时能从秒级降到毫秒级。6.4 Token 降不下来检查三处缓存是否真的命中看日志、prompt 是否注入了过多无关上下文、是否每次都在冷启动。缓存没命中时先确认缓存后端可写、TTL 没过期。6.5 CI 里跑挂但本地正常CI 常见差异headless 模式、UTC 时区、缺字体、分辨率不同、资源配额低。逐项对齐本地与 CI 的浏览器版本、时区、视口尺寸多数飘红能定位。7. 下一步把 Harness 接进你的流水线到这里你已经有一份能跑的 Harness 骨架主配置、用例、编排入口、自愈规则、知识库、回放脚本。接下来把它接进 CI加一个 smoke 步骤每次提交后跑 1–2 个用例采集成功率、Token、耗时三个 KPI返回退出码。如果你还在选执行引擎、调模型接入可以先到模型对话页试试不同模型在页面理解上的表现https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。如果你打算长期跑编码类 Agent、把 Harness 和开发流程打通可以看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。接入细节和参数说明都在文档里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 密钥管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。最后留一句实战体会AI UI 测试的成败很少取决于模型多强更多取决于 Harness 层有没有把失败接住、把 Token 管住、把经验记住。先把这三件事做扎实再谈扩用例。
企业数字化 ERP 产品动态
相关推荐
十款免费降AI率工具实测:从检测原理到修改操作全解析 毕业季一到,“降AI率”这几个字几乎成了宿舍夜谈的固定话题。你辛辛苦苦写了几个月,最后论文在AI检测系统里被标出一大片高亮区域,导师一句“这段有AI痕迹,回去改”,就能让人在图书馆坐到天亮。市面上的降AI率工具五花… · 2026/9/26 13:15:08
元宵节Scratch编程案例:接汤圆、猜灯谜与花灯巡游设计详解 1. 元宵节和Scratch碰撞后的第一个问题:做什么才不像"大杂烩"?每次到传统节日,我的Scratch交流群里都会冒出一批"求节日作品"的帖子。中秋要月亮嫦娥,端午要粽子龙舟,到了元宵节,最常看… · 2026/9/26 13:15:02
Vue3项目集成xgplayer播放器:从封装到踩坑的完整实践 最近接了个Vue3项目,要做课程视频播放模块。一开始我拿原生video标签凑合,结果倍速、清晰度切换、键盘快捷键、自定义控制条这些功能写完,UI丑得自己都嫌弃。后来换成xgplayer,半天就把这块捋顺了。网上关于Vue3集成xgplayer的资料… · 2026/9/26 13:15:02
deepseek 在 cursor 上安装使用教程:TaoToken 统一 Key 配置与验证 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 13:51:46
DDPG深度强化学习移动机器人导航:从环境搭建到训练避坑指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 13:51:46
以太网IO模块Modbus TCP对接全攻略:选型、调试、应用 做自动化项目这些年,我经手的远程IO模块少说也有七八个品牌了,综科智控这个牌子是最近两年在中小型项目里用得比较多的一款。它家的以太网IO模块,说白了就是一个把现场开关量、模拟量信号通过网线送到PLC或者上位机的盒子,对外提供… · 2026/9/26 13:51:46
GPT-5.6之后,Codex配TaoToken的config.toml骨架怎么搭? /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 13:51:46
反转链表深入解析:三种解法与多语言实现 反转链表这道题,我前后见过不下十次。不管是校招机试、社招在线笔试,还是现场面试的白板环节,它就像链表题目的默认选项,稳稳坐在替补席第一位。题目描述通常就一句话——给你单链表的头节点 head,请你反转链表,并返回反转后的链表——看起来没什么含量,但真到机试现场,要在有限… · 2026/9/26 13:51:46
自然天气图像分类数据集验收与PyTorch迁移学习实战 简介:面向计算机视觉入门与图像分类任务实践,提供一套已划分好的4种自然天气图像数据集,覆盖晴朗、多云等四类场景,可直接用于训练与测试。数据按ImageFolder格式组织,train与test目录分别存放901张和224张图片&#x… · 2026/9/26 13:51:40
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46