ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI QA Agent 实战:用大模型自动测试 Vercel Preview 并反馈到 PR

AI QA Agent 实战:用大模型自动测试 Vercel Preview 并反馈到 PR 过去半年如果你的团队在用前端部署平台一定见过这个场景PR 一开机器人自动评论里附上一个 Preview URL然后没人点。直到合并上线后运营拿着截图找过来才发现移动端按钮被侧边栏挡住了。流程上 Vercel 已经做了所有能做的自动化但“质量反馈”仍然停在“等人点一下”这个环节。IronBee 这类产品想补上的正是这个断层。从标题看它的定位非常直白一个 AI QA 工程师在每一个 PR 上自动测试你的 Vercel Preview把结果贴回 PR 对话。第一次看到这个描述很多人的第一反应是“又一个自动化测试工具”。但我认为更准确的判断是它本质上是一个PR 质量反馈闭环的调度器。Vercel Preview 的可访问地址、大模型的视觉和语义理解能力、GitHub PR 评论的反馈通道拆开来看每一项都成熟难的是怎么在正确时机把它们串成一个稳定、可信、低成本的闭环。这篇文章不打算只介绍 IronBee 一个工具的用法因为这类 AI QA Agent 正在快速出现每隔几天就会冒出一个新名字。更有价值的是理解这类工具的架构和工程边界它由哪些环节组成每个环节容易踩什么坑以及如何用最小成本在自己项目里跑通一个类似版本。如果你正在做前端项目、用 Vercel 做部署、尝过 AI 编程的甜头又担心质量没人兜底这篇文章会帮你把“AI 测试”这件事从名词落成可执行的方案。1. 这篇文章真正要解决的问题1.1 传统 PR 质量反馈链路为什么慢现代前端工程化已经把“部署”做得非常自动化。Vercel 会在每次 PR 时生成独立的 Preview 环境CI 会跑单测、Lint、类型检查PR 合并前还有 Code Review。但在真实团队里这套链路对 UI 和质量问题的反馈依然很慢。原因不是工具不够多而是责任落在“人”身上。Preview URL 出来了谁去打开即使打开了谁会认真地按用户路径点一遍注册、登录、下单在大多数团队里这个工作在 PR 阶段是缺失的。QA 人力要安排到版本发布前开发自己在 PR 阶段只会看自己改过的那一块而业务方要等演示环境才能看到完整效果。结果就是Bug 的发现时机被不断推迟。从 PR 阶段推迟到联调阶段再推迟到发布后。而修复成本是随着时间指数上升的。一个在 PR 阶段 10 分钟能改完的问题发布后可能需要走一遍紧急修复、重新部署、通知用户。1.2 AI QA Agent 改变的是反馈时机IronBee 这类工具的真正价值不是“AI 替代了 QA 工程师”而是把质量反馈时机从“发布后”提前到了“PR 中”。当每次 PR 都有一个 AI Agent 自动访问 Preview、检查页面核心状态、把发现的问题按优先级列在 PR 评论里开发者就不需要等有人来做人工冒烟测试。合并前机器已经先看了一遍页面Human QA 只需要关注机器判断不了的高阶问题。这也是为什么这类工具会优先选择 Vercel 生态。Vercel 的 Preview Deployment 是天然的测试环境独立 URL、独立资源、不会污染生产环境而且每个 PR 都有。有了这个前提AI 测试才可能做到“每次 PR 都跑”而不是像传统自动化测试那样靠手工维护一套 staging 环境。1.3 谁最应该关注这类工具我建议下面几类读者认真看一下这篇文章第一正在使用或准备使用 Vercel 的前端团队。Preview 已经生成加一层 AI 检查的成本很低收益却很直接。第二已经在用 AI 编程工具的开发者。Cursor、Copilot 这类工具把代码生成速度拉高了但 PR 里的代码质量方差也变大了。AI 生成的代码需要一个“AI 时代的 QA 兜底”否则问题会在集成阶段集中爆发。第三负责质量平台或 DevOps 的工程师。与其等厂商出一个封闭方案不如先理解 AI QA Agent 的通用架构设计方案会靠谱得多。2. 核心概念Vercel Preview、PR 与 AI QA Agent2.1 Vercel Preview Deployment 是什么先解释一个容易混淆的基础概念。Vercel 有两种部署类型Production Deployment 和 Preview Deployment。Production 对应线上正式环境只有在合并到主分支或手动触发时才会生成。Preview Deployment 则和 PR 绑定每当开发者往 GitHub 提交 PRVercel 会自动为这个分支构建一套独立的前端资源并生成一个形如your-project-xxxx.vercel.app的临时 URL。这套机制最大的价值是环境隔离。每个 PR 可以拥有自己的后端环境变量、自己的 URL、自己的独立数据空间。你不用担心测试时污染线上数据也不需要搭建一套笨重的 staging 集群。有了这个基础AI QA Agent 才能“每次 PR 都跑”。因为每次测试的环境是现成的、隔离的、可销毁的Agent 可以大胆地在里面执行操作而不必担心副作用。2.2 AI QA Agent 到底是什么AI QA Agent 不是简单的“脚本 截图”。Agent 是一个能感知环境、执行动作、根据反馈调整行为的程序。在 IronBee 的场景里它至少要做这几件事感知环境拿到 PR 对应的 Preview URL。理解任务知道这次 PR 改了什么、需要重点验证什么。执行动作打开页面、点击按钮、填写表单、切换设备。形成判断页面是否正常、有没有视觉错位、核心流程是否可走通。反馈结果在 PR 上留下结构化、可读的测试报告。其中第 2 步和第 4 步依赖大模型的语义理解能力第 3 步依赖浏览器自动化工具第 1 步和第 5 步依赖 GitHub 和 Vercel 的接口。IronBee 作为产品是把这些能力封装成一个“开箱即用的 QA 工程师角色”。2.3 Agent 为什么需要一层又一层约束现在社区里有一个越来越明确的共识Agent 不能裸奔。如果有人告诉你“让 AI 自己随便点页面”那大概率会在生产环境惹出麻烦。我在看各种 AI Agent 工程实践时越来越发现一个趋势Agent 需要加上一层又一层的约束。单元测试用来约束函数逻辑Gherkin 测试用来约束业务行为QA 流程用来约束操作边界质量指标用来约束判断标准变异测试用来验证测试本身的有效性。IronBee 这类工具也是一样。它不会让 AI 真的“随便测”而是通过任务描述、检查清单、评分规则、输出结构把 AI 的行为牢牢框在一个安全范围内。AI 的自由度体现在“怎么判断一个问题是否严重”而不是“想去哪里就去哪里”。这一层约束是 AI QA 工具能否在真实团队落地的关键。没有约束的 AI 会产生大量误报误报多了开发者就会把机器人禁掉。2.4 AI QA Agent 与传统 E2E 测试的差异对比维度传统 E2E 测试AI QA Agent用例维护需要手工编写和维护选择器、流程只需要给任务描述和检查清单环境依赖需要稳定的测试环境和测试数据可复用 Vercel Preview 隔离环境反馈速度通常在 CI 或固定时间运行每个 PR 实时运行并回写评论判断能力基于硬编码断言基于大模型的多模态理解稳定性选择器一变就挂视觉判断有一定容错能力最大风险维护成本高AI 误判和不可解释性从表格能看出这不是 A 替代 B 的关系。传统 E2E 适合对核心链路做确定性验证AI QA Agent 更适合做兜底式冒烟和视觉层检查。成熟团队的做法是两者并行。3. 整体架构与核心工作流3.1 一条 PR 从创建到 AI 反馈的完整链路理解 IronBee 这类工具最简单的切入口是看它在一条 PR 上做了什么。整个流程如下开发者提交 PRGitHub 触发事件。Vercel 接收到分支变更开始构建 Preview Deployment生成独立的 Preview URL。与此同时AI QA Agent 被唤醒从事件中读取 PR 号、分支信息、变更文件列表。Agent 拿到 Preview URL 后调度浏览器自动化模块打开页面采集 DOM、截图、控制台日志、网络请求信息。这些原始信息被交给大模型大模型基于预先配置的检查清单和任务描述做判断输出结构化结果。最后 Agent 调用 GitHub API把报告写到 PR 评论并设置一个可识别的状态标签。整套流程看起来不复杂但每一环都有很多工程细节。3.2 触发时机选型什么时候触发 AI QA是一个需要认真决定的问题。最简单的方案是监听pull_request事件在opened、synchronize、reopened类型上触发。synchronize很关键它对应 PR 提交了新 commit说明代码有更新需要重新测试。但“每个 PR 都跑”并不等于“每个提交都跑完整回归”。一次完整的 AI 测试要调用大模型接口有成本也有耗时。如果团队 PR 很频繁建议做分级策略触发条件建议测试级别PR 首次创建全量冒烟测试后续提交只测变更影响页面标记ai-qa-full标签强制全量回归只改 README 或文档跳过测试路径只命中特定目录按目录映射测试套件路径过滤在 GitHub Actions 里可以用paths-ignore或paths实现。比如对docs/**目录的变更完全没必要跑一次昂贵的视觉测试。3.3 关键组件与职责从架构上看一个完整的 AI QA Agent 至少包含五个组件事件源。通常是 GitHub负责提供 PR 事件和变更上下文。预览环境。这里就是 Vercel负责提供隔离、可访问的前端环境。Agent 编排器。这是核心它负责把事件转成任务协调下游组件处理重试和异常。它不负责“思考”只负责流程控制。大模型服务。负责理解页面截图、DOM 内容和任务描述输出判断。它相当于 Agent 的“眼睛”和“大脑”。反馈通道。目前基本都是 GitHub PR 评论有的工具还会配合 Webhook 通知到 IM。这五个组件都是可替换的。不用 Vercel换成 Netlify 或自建环境也可以不用 GitHub换成 GitLab 也可以。IronBee 只是把这一套工程实践产品化。3.4 与现有 CI/CD 的关系AI QA Agent 不是取代 CI而是 CI 的补充视角。CI 里的单元测试和构建检查回答的是“代码能不能跑”AI QA 回答的是“页面看起来和用起来是否正常”。前者是确定性检查后者是感知层检查。所以在设计流程时应该让 AI QA 在 CI 构建通过之后再执行。如果构建都挂了没必要浪费大模型调用。在 GitHub Actions 里可以用needs关键字控制 job 依赖关系让 AI QA 等待主 CI 的 build job 成功后再启动。4. 环境准备与前置条件如果你只想读懂 IronBee 的运作方式这一节可以快速略过。如果你想自己实现一个最小版本那就需要搭建一个能跑的环境。我的建议是先在本地打通流程再迁移到 GitHub Actions。理由很简单本地调试时你能实时看到浏览器行为和大模型输出反馈链路短出问题容易定位。下面以本地开发环境为例列出前置条件。注意版本号没必要追求最新建议以你项目当前可用的稳定版本为准本文不写死版本。项目建议配置说明操作系统macOS / Ubuntu / Windows WSL2GitHub Actions 最终跑在 Ubuntu 上本地建议接近Python3.10AI 脚本和编排逻辑用 Python 比较高效Git任意较新版本本地调试需要克隆仓库GitHub 仓库已接入 Vercel目标是让每个 PR 自动产生 Preview URL大模型 API Key支持视觉理解的多模态模型如 OpenAI、Anthropic 或其他兼容接口PlaywrightPython 版本用于浏览器自动化采集页面同时需要准备下面几个环境变量export GITHUB_TOKEN你的GitHub访问令牌 export LLM_API_KEY你的大模型API密钥 export LLM_ENDPOINThttps://api.openai.com/v1/chat/completions export LLM_MODELgpt-4o-mini export PR_NUMBER123 export VERCEL_PREVIEW_URLhttps://your-project-xxxx.vercel.app这里特别强调一点GITHUB_TOKEN不要随便给权限。如果只在仓库内跑用 GitHub Actions 自带的secrets.GITHUB_TOKEN就够它默认只对当前仓库有权限还能通过permissions字段进一步收缩。如果是本地调试可以创建一个只读代码、并可写 PR 评论的 Fine-grained Token不要使用有整个账号权限的 Token。5. 核心流程拆解这一节把上文提到的链路拆成五个步骤重点讲每一步要做什么、为什么需要、以及判断标准。5.1 第一步捕获 PR 事件Agent 需要有事件入口。最常规的做法是写一个 GitHub Actions Workflow监听pull_request事件。opened对应 PR 刚创建synchronize对应有新 commit 推上来reopened对应 PR 被重新打开。on: pull_request: types: [opened, synchronize, reopened]这一步本身很简单但有一个隐藏在后面的问题如何避免重复触发。你推一次 commit可能触发一次你在 PR 里加了一个 label也可能触发一次。如果不加任何限制AI 测试会被频繁拉起浪费时间和费用。建议在 workflow 入口加一个快速判断如果 PR 变更列表里只有文档或配置文件就跳过如果 PR 带有skip-ai-qa标签也跳过。5.2 第二步获取 Preview URL拿到 PR 号之后最核心的问题是怎么拿到对应的 Vercel Preview URL。从实践来看有三种可行的方式具体用哪一种取决于你的工程流程。第一种最直接如果在触发 AI QA 之前已经有另外的工作流把 Preview URL 存到了环境变量或 GitHub Actions 的outputs中那这里直接读VERCEL_PREVIEW_URL环境变量即可。你的部署流水线可以先把 URL 解析出来再传给 QA 流程。第二种是利用 GitHub 的deployment_status事件。Vercel 在部署完成时会回写 GitHub Deployment Status其中的target_url字段就是 Preview URL。但要注意这个事件不是 PR 事件需要在 workflow 里单独监听deployment_status并且判断当前部署的环境类型是否为 preview。如果一个仓库有多个 PR你还要通过 commit SHA 找到它属于哪个 PR。第三种是手动调试时用的直接从 Vercel 项目里的 Deployment 列表复制 URL或者从 Vercel Bot 在 PR 里的评论中提取 URL。本地测试阶段用这种方式最简单但做成自动化时不可靠。综合来看如果团队已经接入了 Vercel我建议采用第二种让 GitHub Actions 监听deployment_status事件判断environment preview后把target_url作为下一步 AI QA 的输入。这样不需要额外请求 Vercel API事件的完整度最高。5.3 第三步构造 QA 任务描述把 URL 拿到手之后下一个关键步骤是告诉 AI “测什么”。这就是 Agent 和普通自动化脚本的区别。普通脚本只能用代码写死每一步操作而 Agent 收到的是一份任务描述。任务描述的质量直接决定测试结果的质量。一个合格的 QA 任务描述应该包含以下几个方面目标页面。默认是 Preview URL 首页也可以追加具体路径。核心流程。这次测试需要走通的用户路径比如“注册 → 登录 → 创建项目”。检查清单。需要重点确认的视觉和功能点比如“导航栏是否固定”“移动端是否有横向滚动”“表单提交后是否出现成功提示”。输出格式。要求 AI 严格按照 JSON 结构返回包括整体结论、问题列表、严重级别、截图说明等。下面是一个简化的任务描述模板{ task: 对给定 Preview URL 执行冒烟测试, url: https://your-project-xxxx.vercel.app, page_path: /, checklist: [ 页面能正常加载不能出现白屏, 主导航栏显示品牌名和菜单链接, 首屏不能出现明显的布局错位, 点击登录按钮后能跳转到登录页 ], output_format: { passed: boolean, summary: string, issues: [ { severity: critical|major|minor, description: string, suggestion: string } ] } }有了结构化的任务描述大模型的分析才会更可控也更容易避免 AI 幻觉带来的乱打分。5.4 第四步Agent 执行测试任务构造好之后Agent 开始执行。这个阶段包括三件小事打开页面。用 Playwright 启动无头浏览器访问 Preview URL等待页面完成渲染。采集证据。获取页面 HTML、截图、控制台错误、网络请求失败信息。这些信息后续会作为大模型判断的上下文。调用大模型。把任务描述、截图、关键 HTML 片段一起发送给多模态大模型让它基于证据做判断而不是凭空猜测。这里需要特别说明为什么不直接让大模型看整个 HTML。因为现代前端页面的 DOM 动辄上百 KB直接塞给大模型会超过 token 上限成本也很高。更合适的做法是只采样关键片段比如head、title、可见的导航文字、按钮文本、表单字段等。截图反而是更稳定的判断依据因为很多视觉问题只有在截图里才看得出来。5.5 第五步回写 PR 评论最后一步是把测试结果写回 PR。这一步不仅是让开发者看到结果也是闭环的关键。GitHub Issues API 支持给 PR 添加评论因为 PR 本质上是 Issue 的特殊形态。调用接口如下POST /repos/{owner}/{repo}/issues/{pr_number}/comments评论内容可以用 Markdown 排版把通过项、问题项、严重级别、复现建议都列清楚。如果检测到 critical 级别的问题还可以给 PR 打一个ai-qa-failed标签让合并不那么“顺畅”。这一步对团队协作非常重要没有状态标识的测试报告很容易被忽略。6. 完整示例与代码实现下面我用一个最小可跑的示例把上文提到的流程串起来。这个示例会包含 GitHub Actions Workflow、Python 编排脚本、浏览器采集模块和大模型调用模块。它不依赖 IronBee 本身但遵循同一种工程思路你可以把它当成自己项目里 AI QA Agent 的最小骨架。6.1 项目结构ai-qa-demo/ ├── .github/ │ └── workflows/ │ └── ai-qa-on-pr.yml ├── src/ │ └── ai_qa/ │ ├── __init__.py │ ├── run.py │ ├── capture.py │ ├── llm_client.py │ └── comment.py └── requirements-ai-qa.txt6.2 依赖文件文件路径requirements-ai-qa.txtplaywright1.44.0 httpx0.27.0 python-dotenv1.0.1安装依赖后还需要执行一次 Playwright 的浏览器安装命令playwright install chromium6.3 浏览器采集模块文件路径src/ai_qa/capture.pyimport base64 from playwright.sync_api import sync_playwright def capture_page(url: str, wait_seconds: int 3) - dict: 访问页面采集 HTML 摘要、截图和控制台错误。 console_errors [] with sync_playwright() as p: browser p.chromium.launch(headlessTrue) page browser.new_page(viewport{width: 1280, height: 800}) page.on(console, lambda msg: console_errors.append(msg.text) if msg.type error else None) page.on(pageerror, lambda exc: console_errors.append(str(exc))) page.goto(url, wait_untilnetworkidle, timeout30000) page.wait_for_timeout(wait_seconds * 1000) title page.title() body_text page.inner_text(body)[:3000] buttons page.locator(button).all_inner_texts()[:20] links page.locator(a).evaluate_all( els els.slice(0, 20).map(e ({ text: e.innerText.trim(), href: e.href })) ) screenshot page.screenshot(full_pageFalse) browser.close() return { title: title, body_text: body_text, buttons: buttons, links: links, console_errors: console_errors[:20], screenshot_base64: base64.b64encode(screenshot).decode(), }这段代码的核心是页面采集。它不做断言只负责把页面状态变成可交给大模型分析的结构化数据。console_errors和pageerror是判断页面是否报错的重要证据很多白屏问题在截图里不明显但控制台错误会直接暴露。6.4 大模型调用模块文件路径src/ai_qa/llm_client.pyimport json import os import httpx def analyze_with_llm(page_data: dict, checklist: list[str]) - dict: 将页面证据发送给多模态大模型返回结构化 QA 结果。 api_key os.environ[LLM_API_KEY] endpoint os.environ.get( LLM_ENDPOINT, https://api.openai.com/v1/chat/completions, ) model os.environ.get(LLM_MODEL, gpt-4o-mini) prompt ( 你是一个前端 QA 工程师。请根据页面截图和页面文本信息完成以下检查清单。\n f检查清单{json.dumps(checklist, ensure_asciiFalse)}\n 请严格按照 JSON 格式输出{\passed\: boolean, \summary\: string, \issues\: [...]}\n issues 中每一项包含 severity(取值 critical/major/minor)、description、suggestion。 ) headers { Authorization: fBearer {api_key}, Content-Type: application/json, } payload { model: model, messages: [ { role: user, content: [ {type: text, text: prompt}, { type: text, text: f页面标题{page_data[title]}\n页面正文摘要{page_data[body_text]}, }, { type: image_url, image_url: { url: fdata:image/png;base64,{page_data[screenshot_base64]} }, }, ], } ], } resp httpx.post(endpoint, headersheaders, jsonpayload, timeout120) resp.raise_for_status() content resp.json()[choices][0][message][content] # 大模型输出可能是包含 JSON 的字符串做一次安全解析 try: result json.loads(content) except json.JSONDecodeError: start content.find({) end content.rfind(}) result json.loads(content[start:end 1]) return result调用不同厂商的大模型时消息格式可能会有差异。如果你使用的模型不支持图片输入可以去掉image_url那段只依赖页面文本信息和控制台错误但这会损失很多视觉判断能力。实际项目中请以你所用模型的接口文档为准调整 payload。6.5 回写 PR 评论模块文件路径src/ai_qa/comment.pyimport os import httpx def post_pr_comment(pr_number: int, report: str) - None: 把 Markdown 报告发布到指定 PR 的评论区。 token os.environ[GITHUB_TOKEN] repo os.environ[GITHUB_REPOSITORY] headers { Authorization: fBearer {token}, Accept: application/vnd.githubjson, X-GitHub-Api-Version: 2022-11-28, } url fhttps://api.github.com/repos/{repo}/issues/{pr_number}/comments payload {body: report} resp httpx.post(url, headersheaders, jsonpayload, timeout30) resp.raise_for_status()注意GITHUB_REPOSITORY是 GitHub Actions 自动注入的环境变量格式是owner/repo。在本地调试时需要手动设置。6.6 入口脚本文件路径src/ai_qa/run.pyimport os import json import argparse from capture import capture_page from llm_client import analyze_with_llm from comment import post_pr_comment def build_report(result: dict) - str: passed result.get(passed, False) summary result.get(summary, ) issues result.get(issues, []) lines [## AI QA 报告, ] lines.append(f**结论**{通过 if passed else 存在问题}) lines.append() lines.append(f**摘要**{summary}) lines.append() if issues: lines.append(| 严重级别 | 问题描述 | 建议 |) lines.append(| --- | --- | --- |) for issue in issues: lines.append( f| {issue.get(severity, minor)} | {issue.get(description, )} | {issue.get(suggestion, )} | ) lines.append() return \n.join(lines) def main(): parser argparse.ArgumentParser(descriptionAI QA Agent 最小示例) parser.add_argument(--url, requiredTrue, helpVercel Preview URL) parser.add_argument(--pr-number, typeint, default0, helpPR 编号) args parser.parse_args() checklist [ 页面可以正常加载不存在白屏, 主导航栏和页脚正常展示, 按钮和链接没有明显布局错位, 控制台不存在严重 JavaScript 错误, 移动端宽度 375px 下没有横向滚动, ] page_data capture_page(args.url) print(f[capture] title{page_data[title]}) print(f[capture] console_errors{len(page_data[console_errors])}) result analyze_with_llm(page_data, checklist) print(f[llm] raw result{json.dumps(result, ensure_asciiFalse)}) report build_report(result) if args.pr_number and args.pr_number 0: post_pr_comment(args.pr_number, report) print([github] 评论已发布) else: print(report) if __name__ __main__: main()这个入口脚本做了三件事采集页面调用大模型分析把报告写成 Markdown。如果传了--pr-number就回写到 GitHub PR如果没传只打印到控制台方便本地调试。6.7 GitHub Actions Workflow文件路径.github/workflows/ai-qa-on-pr.ymlname: ai-qa-on-pr on: pull_request: types: [opened, synchronize, reopened] permissions: contents: read pull-requests: write jobs: ai-qa: runs-on: ubuntu-latest if: ${{ !contains(github.event.pull_request.labels.*.name, skip-ai-qa) }} steps: - name: Checkout uses: actions/checkoutv4 - name: Setup Python uses: actions/setup-pythonv5 with: python-version: 3.11 - name: Install dependencies run: | pip install -r requirements-ai-qa.txt playwright install chromium - name: Run AI QA env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_REPOSITORY: ${{ github.repository }} LLM_API_KEY: ${{ secrets.LLM_API_KEY }} LLM_ENDPOINT: ${{ vars.LLM_ENDPOINT }} LLM_MODEL: ${{ vars.LLM_MODEL }} VERCEL_PREVIEW_URL: ${{ vars.VERCEL_PREVIEW_URL }} run: | if [ -n $VERCEL_PREVIEW_URL ]; then python src/ai_qa/run.py --url $VERCEL_PREVIEW_URL --pr-number ${{ github.event.pull_request.number }} else echo VERCEL_PREVIEW_URL 未配置请在你的部署流程中注入该变量。 exit 1 fi这个 Workflow 做了几个保护只读代码仓库只写 PR 评论检测到skip-ai-qa标签就跳过依赖VERCEL_PREVIEW_URL注入 Preview 地址。这里要提醒你一件事如果你的 Vercel 部署是自动完成的而这个 Workflow 和 Vercel 的部署几乎同时触发可能出现在 AI QA 启动时 Preview 还没构建完成的情况。有两种处理方式一是让 Vercel 部署完成后再触发 QA 流程二是参考前面 5.2 节说的deployment_status事件把它作为触发源。7. 运行结果与效果验证7.1 本地运行把项目代码放到本地安装依赖后先手动设置环境变量export GITHUB_TOKEN你的GitHubToken export LLM_API_KEY你的大模型Key export GITHUB_REPOSITORY你的用户名/你的仓库名然后执行python src/ai_qa/run.py \ --url https://your-project-xxxx.vercel.app \ --pr-number 123如果一切正常终端会先打印页面标题和采集到的控制台错误数量然后打印大模型的原始 JSON 输出最后打印 Markdown 报告。7.2 预期输出正常情况下的关键输出如下[capture] titleMy Awesome App [capture] console_errors0 [llm] raw result{passed: true, summary: 页面加载正常核心元素可见未发现明显布局问题, issues: []} [github] 评论已发布7.3 怎么判断成功从三个维度判断第一流程完整性。日志里能依次看到采集、分析、回写三个阶段说明链路是通的。第二结论合理性。大模型的passed和summary应该和你人工打开页面的观感一致。如果页面明显有问题而 AI 显示passedtrue说明任务描述或采集逻辑需要加强。第三闭环有效性。打开 PR 页面评论区能看到 AI QA 报告。如果手动运行成功但 Actions 里失败重点排查环境变量和 Playwright 浏览器是否安装在 runner 上。7.4 失败时的第一步排查如果 workflow 失败不要急着改代码先看两件事第一日志里有没有出现VERCEL_PREVIEW_URL 未配置。如果是说明触发链路里没有正确传递 Preview 地址问题出在部署环节而不是 AI 环节。第二大模型调用是否超时。多模态模型处理截图通常需要 10 到 30 秒如果你设置了很短的 timeout很容易误报失败。建议本地先单测llm_client.py确认 API 能正常返回。8. 常见问题与排查思路下表整理了我认为 AI QA Agent 落地时最常遇到的六个问题每个问题都给出了可操作的排查方向。问题现象可能原因排查方式解决方案Workflow 没有触发事件类型没写全或 PR 带skip-ai-qa标签查看 Actions 页面是否有 workflow run补上synchronize和reopened类型去掉标签一直报VERCEL_PREVIEW_URL 未配置部署流程没有把 Preview URL 传到 QA 流程查看部署流程的 outputs 和 Secrets 配置改用deployment_status事件读取target_url大模型调用超时模型处理截图太慢或请求 timeout 设置太短先本地调llm_client.py测响应时间把 timeout 调到 120 秒或缩小截图体积页面截图一片空白Playwright 在 headless 下没有等到异步渲染完成检查networkidle是否命中SPA 可能一直有请求改用domcontentloaded加固定等待时间AI 误报严重任务描述太泛没有给检查清单和输出格式检查传给 LLM 的 prompt 是否明确给passed和issues加字段定义限定问题级别Actions 里没有评论权限permissions没开pull-requests: write查看 workflow 文件权限声明在 job 级别增加permissions.pull-requests: write这张表解决的是“跑不起来”和“结果不靠谱”两类问题。第一次做 AI QA Agent 的团队至少有一半时间会花在这些问题上不是 AI 不可用而是工程链路里的普通问题。9. 最佳实践与工程建议9.1 安全与最小权限AI Agent 一旦接入 CI/CD就拥有了执行操作的能力。给它越多的权限风险就越大。在 GitHub Actions 中建议只给 read 权限和写 PR 评论的权限千万不要为了省事直接给write-all。在本地调试时使用 Fine-grained Token只勾选当前仓库的 Pull requests 读取和写入权限。大模型 API Key 也一样只配置在仓库的 Secrets 里不要写进代码。另外AI 测试应该只访问 Preview 环境永远不要让它访问生产环境。Vercel Preview 的优势就在于环境隔离如果 AI 操作产生脏数据也只影响这个 PR 的临时环境不会波及线上。9.2 控制执行范围与成本AI QA 不是免费的。每跑一次 PR都会产生浏览器计算资源和大模型 Token 消耗。一个中大型前端团队如果每天 30 个 PR一个月下来是笔不小的支出。控制成本的方法有三种一是缩小触发范围。文档改动、配置改动、纯样式微调都可以通过路径过滤跳过。只有涉及核心逻辑和页面结构的改动才需要完整 AI 测试。二是缩小测试范围。不要每次都测全站。根据 PR 的变更文件列表动态生成需要访问的页面路径列表。比如这次只改了登录页那就只测登录页和它依赖的公共组件。三是给大模型分层。简单的页面状态检查用便宜的轻量模型复杂视觉语义判断才用高能力多模态模型。这个策略在 LLM 调用频率高时非常有效。9.3 用结构化约束对抗 AI 幻觉大模型在视觉判断里出现幻觉不是小概率事件。明明页面少了按钮模型可能因为看到导航栏而直接给passedtrue。减少幻觉的方法不是换更大的模型而是增加约束。我在前文强调过Agent 需要一层又一层约束。具体到代码层面至少要加三层第一层页面证据。不只是截图还要采集 DOM 里的实际文本、按钮文字、链接列表。这些是客观证据模型不能凭空捏造。第二层输出结构。强制要求passed、summary、issues是 JSON 字段每个 issue 必须给出严重级别和描述。结构化输出比自由文本更容易被程序校验。第三层自动校验。如果结果是passedtrue但页面文本里找不到任务描述中要求的关键词就自动标记为“无法确认”而不是直接置为通过。这种规则简单但非常有效。9.4 建立人工确认机制AI QA 报告是一个辅助信号不应该成为合并的唯一阻塞条件。尤其是早期阶段模型判断不一定可靠。建议的流程是AI 报告里的 critical 问题由机器人自动标记major 问题提醒人工查看机器人自己的判断必须允许开发者一键忽略并记录“为什么忽略”。忽略的原因可以回传给任务调优逐渐减少误报。从团队协作角度看AI QA Agent 更像一个“勤奋但经验不足的实习生”而不是“权威测试专家”。它的价值是替人跑腿把重复性检查和基础冒烟做掉而不是替代人的
返回列表