Maestro AI 断言源码解析:3 条命令把截图缺陷检测与文本提取接入你的测试流

发布时间:2026/9/11 10:31:59
Maestro AI 断言源码解析:3 条命令把截图缺陷检测与文本提取接入你的测试流 Maestro AI 断言源码解析3 条命令把截图缺陷检测与文本提取接入你的测试流【免费下载链接】MaestroPainless E2E Automation for Mobile and Web项目地址: https://gitcode.com/GitHub_Trending/ma/Maestro本文从源码层面拆解 Maestro AI 的截图断言能力assertNoDefectsWithAI、assertWithAI、extractTextWithAI 三条命令如何截图并调用云端模型以及如何在 5 分钟内接入你的 flow。功能全景Maestro AI 的 4 个能力点Maestro 的 AI 能力集中在maestro-ai模块核心是一个只有三个方法的接口外加一个离线评测工具。四条能力对应关系如下能力对应源码入口一句话说明通用 UI 缺陷检测maestro-ai/src/main/java/maestro/ai/IAPredictionEngine.kt 中findDefects把整屏截图发给云端模型返回categoryreasoning的缺陷列表自然语言断言同接口performAssertion把一句人类语言断言转成是否成立不成立时 flow 失败并附上模型理由截图文本提取同接口extractText用自然语言 query 从截图里抠出文本写入 flow 变量供后续assert使用截图集批量评测maestro-ai/src/main/java/maestro/ai/DemoApp.kt离线跑一批*_good.png/*_bad.png统计模型误报率与漏报率flow 层面的接线则发生在 maestro-orchestra-models/src/main/java/maestro/orchestra/MaestroCommand.kt它把 YAML 里的三条 AI 命令映射到执行管线。最快上手路径不接设备先跑离线评测想不接真机就体验先编译出自带的评测程序maestro-ai-demo。它读本地截图文件对每张图调用云端缺陷检测并打印 PASS/FAILexport MAESTRO_CLOUD_API_KEYyour-cloud-key export MAESTRO_CLI_AI_KEYsk-... ./gradlew :maestro-ai:installDist ./maestro-ai/build/install/maestro-ai-demo/bin/maestro-ai-demo foo_1_bad.png截图文件名必须遵循{应用名}_{序号}_{good|bad}.png约定bad表示这张图应当被检出缺陷否则 DemoApp 会直接报参数错误。两个环境变量都要设MAESTRO_CLI_AI_KEY用于本地模型客户端MAESTRO_CLOUD_API_KEY用于 Maestro Cloud 推理端点。跑通后再接设备即可在正式 flow 里使用。功能深挖先看三个能力共同依赖的接口签名这是整个 AI 模块的最小契约interface AIPredictionEngine { suspend fun findDefects(screen: ByteArray): ListDefect suspend fun performAssertion(screen: ByteArray, assertion: String): Defect? suspend fun extractText(screen: ByteArray, query: String): String }通用 UI 缺陷检测assertNoDefectsWithAI痛点场景视觉回归靠人肉对比截图布局错位、元素截断、文案重叠这类问题在自动化断言里很难表达——view tree 看起来没问题但画面上已经错了。源码实现路径YAML 中的assertNoDefectsWithAI被解析为AssertNoDefectsWithAICommand定义在 maestro-orchestra-models/src/main/java/maestro/orchestra/Commands.kt执行入口是 maestro-orchestra/src/main/java/maestro/orchestra/Orchestra.kt 的assertNoDefectsWithAICommand先maestro.takeScreenshot(imageData, compressed false)抓无压缩 PNG再交给CloudAIPredictionEngine.findDefectsmaestro-ai/src/main/java/maestro/ai/CloudPredictionAIEngine.kt最终由 maestro-ai/src/main/java/maestro/ai/cloud/ApiClient.kt POST 到$baseUrl/v2/find-defectsbaseUrl默认是https://api.copilot.mobile.dev可用MAESTRO_CLOUD_API_URL覆盖。响应体反序列化为Defect(category, reasoning)列表只要列表非空flow 就以Found N possible defects失败且每个缺陷都带模型的推理文本。最小可运行示例flow YAML 里的一行- assertNoDefectsWithAI自然语言断言assertWithAI痛点场景订单卡片上应当显示配送地址这种断言你写不出稳定的 selector正则和文本匹配又太脆。源码实现路径AssertWithAICommand多带一个assertion: String字段同样在 Commands.kt。Orchestra 的assertWithAICommand复用同一条截图链路但调用performAssertion——它在 maestro-ai/src/main/java/maestro/ai/Prediction.kt 里走的是同一个/v2/find-defects端点只是把断言文本放进FindDefectsRequest.assertion字段然后取response.defects.firstOrNull()返回null即断言通过返回缺陷则失败信息直接引用defect.reasoning。可以把它理解为带题目判卷的缺陷检测题目就是你这句自然语言。最小可运行示例- assertWithAI: 订单卡片上显示了配送地址截图文本提取extractTextWithAI痛点场景WebView、canvas、游戏引擎渲染的文本不在 view tree 里assert的文本选择器拿不到而你又不想引入第三方 OCR。源码实现路径ExtractTextWithAICommand携带query和outputVariable两个字段。执行函数extractTextWithAICommand截图后调用AIPredictionEngine.extractText落到 ApiClient 的extractTextWithAiPOST$baseUrl/v2/extract-text请求体是ExtractTextWithAiRequest(query, screen)。关键的一步在最后jsEngine.putEnv(command.outputVariable, text)把结果注入 flow 的 JS 变量环境后续步骤就能用{{变量名}}引用提取结果——这是它与两条断言命令的本质区别它是产出而不是判定。最小可运行示例- extractTextWithAI: query: 提取当前页面显示的用户余额 outputVariable: balance一键跑通用截图集评估缺陷模型maestro-ai-demo痛点场景接入 AI 断言之前你想先知道模型对你家 App 的截图到底误报多少、漏报多少避免把不稳定的判定塞进 CI。源码实现路径DemoApp 按文件名解析出appName、序号和good/bad标签构造TestCaseshouldPass status good对每张图读取字节后走Prediction.findDefects无 prompt 文件时或Performance performAssertion同名.txtprompt 存在时verify()按bad 图没检出 false-negativegood 图报缺陷 false-positive打印 FAIL并把category: reasoning逐条列出。--parallel可并发跑注释里直接提醒May get rate limited--show-prompts/--show-raw-response帮你调试模型行为。最小可运行示例maestro-ai-demo --model gpt-4o --show-raw-response test-ai-fixtures/uber_*_bad.png关键源码地图maestro-ai/src/main/java/maestro/ai/IAPredictionEngine.kt — 能力契约findDefects/performAssertion/extractTextmaestro-ai/src/main/java/maestro/ai/CloudPredictionAIEngine.kt — 唯一实现持apiKey转发到Predictionmaestro-ai/src/main/java/maestro/ai/Prediction.kt — 三个静态入口负责 DTO 到领域结果的裁剪maestro-ai/src/main/java/maestro/ai/cloud/ApiClient.kt — Ktor HTTP 客户端、超时配置、Defect等请求/响应 DTOmaestro-ai/src/main/java/maestro/ai/AI.kt — 直连 OpenAI/Claude 的抽象基类定义MAESTRO_CLI_AI_KEY等环境变量名maestro-ai/src/main/java/maestro/ai/DemoApp.kt — 离线批量评测 CLImaestro-orchestra-models/src/main/java/maestro/orchestra/MaestroCommand.kt 与 maestro-orchestra-models/src/main/java/maestro/orchestra/Commands.kt — YAML 命令的数据模型maestro-orchestra/src/main/java/maestro/orchestra/Orchestra.kt — 运行期截图、调引擎、失败判定、把提取文本注入变量环境maestro-ai/README.md — 构建与使用文档组合实战一个 flow 里串起断言与提取下面的 flow 演示了先泛检、再定向断言、最后提取变量并做正则校验的组合方式appId: com.example.app --- - launchApp - waitForAnimationToEnd - assertNoDefectsWithAI - assertWithAI: 页面展示了登录按钮且没有广告弹窗遮挡 - extractTextWithAI: query: 提取当前页面显示的用户余额 outputVariable: balance - assert: text: {{balance}} matchesRegex: \\d\\.\\d{2}前两条命令守住画面没有明显破损和关键状态成立后两条命令把截图里的动态数字变成可校验的变量——整条链路不需要任何额外依赖前提是MAESTRO_CLOUD_API_KEY已导出。调优与避坑别混淆两套 Keyflow 里的三条 AI 命令只读MAESTRO_CLOUD_API_KEYOrchestra 报错信息也会提示这一点MAESTRO_CLI_AI_KEY只服务于 maestro-ai 模块内直连 OpenAI/Claude 的路径离线评测程序则两个都要。超时是写死的ApiClient 固定为连接 10 秒、socket/request 各 60 秒源码里没有重试逻辑。网络慢时单个 AI 步骤可能吃掉半分钟一个 flow 里别堆太多 AI 步骤CI 超时时间要相应放大。截图是全量无压缩 PNGtakeScreenshot(..., compressed false)意味着高分辨率设备上每次断言都上传原图流量和耗时都成正比没必要时用默认分辨率即可。失败可降级三条命令的optional字段默认为true但默认行为仍是失败即停想在灰度期只告警不阻断可显式配optional: true或把 AI 步骤包进retry:块兜底网络抖动。评测注意命名与限流DemoApp 只接受{app}_{n}_{good|bad}.png三段命名--parallel并发跑同一 key 时容易被限流批量评测建议串行或降低并发。结语Maestro AI 这三条命令全部依赖 Maestro Cloud 的/v2/find-defects与/v2/extract-text端点没有纯本地的模型路径MAESTRO_CLOUD_API_URL只改地址不改协议断言的可靠性取决于云端模型对截图的判定建议先用离线评测程序在自己的截图集上验证。更多构建与用法细节见 maestro-ai/README.md。【免费下载链接】MaestroPainless E2E Automation for Mobile and Web项目地址: https://gitcode.com/GitHub_Trending/ma/Maestro创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考