mcpField
M
mo-qa

mo-qa

github.com/momentic-ai测试与质量1623.2k 次安装今天更新
代码仓库

关于 mo-qa

mo-qa 是通过 Mo 托管沙盒运行浏览器 QA 的技能,面向执行软件测试的 Agent。它涵盖测试说明准备、会话启动与监控,以及在保持目标稳定的前提下报告发现。

主要功能

  1. 01准备范围明确的 QA 说明
  2. 02启动 Mo QA 会话
  3. 03监控会话状态与发现
  4. 04处理阻塞情况和用户输入
  5. 05附证据报告复现问题

适用场景

  1. 01在托管浏览器沙盒中测试 Web 应用
  2. 02验证 GitHub PR 中的行为变更
  3. 03针对本地或私有目标运行 QA
  4. 04跟踪发现并报告测试状态

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/momentic-ai/skills --skill mo-qa

安装后在 Claude Code 中输入/mo-qa确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
references/
authentication.md
browser-settings.md
installation.md
remediation-loop.md
reports.md
tunneling.md

详细介绍

使用 Mo 运行 QA

Mo 在托管沙盒中运行浏览器 QA。它的文件和进程都位于远程。

Mo 运行期间的工作

在初始 QA 检查及其复现期间,保持受测版本稳定。Mo 使用目标时,不要更改目标提供或热重载的任何内容、重启应用、将应用部署到其 URL,或修改共享测试数据。代码审查等其他工作不受影响。对于较长运行期间的隔离 Bug 修复,请遵循修复循环。

通过 qa status "$session_id" --full 获取发现结果。kind: "bug" 条目表示问题已独立复现。kind: "flag" 条目表示静态的单帧错误(如拼写错误),记录时未进行复现。Agent 的判定结果包括 verified、issues_found 或 blocked。向用户报告发现结果时,请包含其名称、证据、状态和 web_url。

如果 Mo 遇到阻碍,且你能从需求说明、代码仓库或获准访问的环境数据中找到答案,就据此回答。否则,请用户提供缺失的访问权限、许可或决策,然后将答案发送给根 Mo。根 Mo 会将上下文转达给内部子 Agent。绝不要编造或泄露秘密。

准备需求说明

运行 qa version。如果缺少 Mo 或版本过旧,请阅读安装。遇到身份验证错误后,请阅读身份验证。

使用请求中指定的目标。对于本地或私有目标,请阅读隧道。

向 Mo 说明测试目标和操作边界。按需提供以下信息:

  1. 已知的目标 URL,包括相关路径和查询参数。
  2. 用户的目标、相关产品意图和已知要求。
  3. 登录方式、测试账户标签以及允许使用的测试数据。
  4. Mo 禁止执行的操作,以及不得更改的数据。
  5. 用户希望测试的内容和要求排除的内容。
  6. 任何非默认浏览器设置。必要时请阅读浏览器设置。

提供来自请求和代码仓库的事实背景,不要将其变成规定好的测试计划。只有当缺少范围、访问权限或许可会影响运行时才询问。

设置高层参数,默认让 Mo 规划

在符合用户请求的范围和预算内,让 Mo 自行选择流程和子 Agent 编排。说明用户希望测试的内容。保留用户指定的覆盖范围;否则不要规定检查清单、交互步骤或固定检查次数。提供实现细节作为背景信息。

目标设置、身份验证以及 Mo 无法远程执行的操作由你负责。开始前,移除未经请求的测试限制。保持正常并发;只有在用户明确要求或已证实目标存在限制时,才降低 --max-concurrency,并记录原因。

向 Mo 提供商定的时长或花费预算,并让它自行安排覆盖优先级。“轻量”不代表固定检查次数或串行执行。Mo 没有适用于整个会话的时间或测试数量选项。对于用户指定的硬性上限,请监控实际耗时或运行 qa cost <session-id>,达到上限时运行 qa stop <session-id> --subagents 停止,并报告未完成的覆盖范围。

启动会话

将需求说明作为一个参数传给 qa start。 对于要求进行快捷结账冒烟测试并检查标准结账回归的用户:

brief=$(cat <<'EOF'
Target: https://preview.example.com/checkout?variant=express
Goal: Keep the selected shipping method after returning from payment.
Sign in: Use the staging QA buyer account.
Test data: Create test carts and orders only.
Do not: Submit payment, send email, delete data, or change the shared catalog.
Coverage: Smoke the express-checkout happy path and standard checkout. Skip other flows and failure states.
Pass criteria:
- The shipping method stays selected.
- The total does not change.
- Standard checkout still works.
EOF
)
session_json=$(qa start "$brief")
session_id=$(jq -r .sessionId <<<"$session_json")
web_url=$(jq -r .webUrl <<<"$session_json")
created_at=$(jq -r '.createdAt // empty' <<<"$session_json")

启动命令会在 Mo 完成之前返回。保留以下值:后续每条命令都需要 session_id;用户可以通过 web_url 查看或加入会话;created_at 记录会话开始时间。若服务器运行的是较早版本的 API,createdAt 可能不存在。

例如,测试 Mo 无法构建或运行的未发布 CLI 时:

请让我使用此分支的未发布 QA CLI 启动会话。发送所需参数并等待会话 URL,然后在 Web 界面中验证该 URL。

对于 GitHub PR,请使用 PR 模式,而不是只在需求说明中填写 PR 引用。使用 --url 传入你创建或验证过的部署 URL;任何 HTTP 或 HTTPS 预览主机均可:

session_json=$(qa start "$brief" --pr https://github.com/acme/shop/pull/412 --url https://preview.example.com)

--pr 接受完整的 GitHub PR URL,包括评论固定链接和带查询参数的链接。Mo 会保留仓库和 PR 编号,并丢弃查询参数和片段。owner/repo#number 也适用。请明确指定 PR;不要根据当前分支或远程仓库推断。Mo 会获取远程 PR 修订版,并测试其中变更的应用行为和回归问题。若要使用此默认范围,请省略测试说明。没有可测试应用行为的变更会直接结束,不会启动测试 Agent。

对于 PR 会话,让 Mo 根据 PR 上下文识别变更行为和受影响的流程。计划约 10 分钟的累计交互时间,以及包括规划和复现过程在内约 20 分钟的总耗时。Mo 的 PR 指令会引导它进行有针对性的验证,并减少探索者数量。若用户明确指定了范围、时长和并发要求,请遵从这些要求,而非采用默认值。这些只是规划目标,并非强制限制;如果用户设定了硬性上限,请监控会话并及时停止。

环境会提供目标,无需预览 URL。否则,Mo 会在 Vercel、Cloudflare Pages 或 Netlify 的机器人帖子中查找与 PR 提交关联的预览。发现失败或结果不明确不会阻止启动:Mo 可以检查 PR,也可以询问目标。不要根据分支名称编造 URL。若所选部署是本地或私有的,也请使用 --tunnel。 不带 --pr 时,--url 和 --patch 会被忽略;请在常规会话的说明中填写目标 URL。

每个 PR 会话都会发布一条包含会话链接的 GitHub 评论,并在结果生成后更新该评论。新会话会将较早的 Mo 评论折叠为已过时;其中的会话链接和报告链接仍可访问。同一提交上的 Mo 检查会跟随最新请求。请以会话报告查看发现,不要将已被取代的评论视为当前结果。

对于本地变更,只要获得授权,启动前请先提交并推送到该 PR。如果不允许推送,请从 PR 检出目录使用 --patch FILE 传入经过筛选的 Git 补丁。CLI 使用本地 HEAD 作为基准;它必须与已发布的 PR head 一致,否则启动会被拒绝。请使用包含这些本地变更的目标;已知目标时使用 --url,必要时使用 --tunnel。 补丁会为 Mo 提供源代码上下文,但不会部署这些变更。

只选择测试变更所需的文件和代码块,包括相关的未跟踪文件。发送前请检查补丁。排除机密信息、凭据、日志、临时文件、大型二进制文件、不相关的变更或客户数据。不要收集整个工作树,也不要强制添加被忽略的文件。补丁必须是纯文本 Git 差异,且大小不超过 256 KiB。

若要在不更改实际 Git 索引的情况下包含已跟踪和未跟踪的文件,请使用临时索引和明确的文件列表。运行此示例前,请确认本地 HEAD 与指定的 PR head 一致,然后将示例中的路径替换为你已检查的文件:

patch_base=$(git rev-parse --verify HEAD)
patch_file=$(mktemp)
(
  set -eu
  patch_index=$(mktemp)
  rm "$patch_index"
  trap 'rm -f "$patch_index"' EXIT
  export GIT_INDEX_FILE="$patch_index"
  git read-tree "$patch_base"
  git add -- src/checkout.ts src/discount.ts
  git diff --cached --no-renames --no-ext-diff --no-textconv "$patch_base" -- src/checkout.ts src/discount.ts > "$patch_file"
)
git apply --stat "$patch_file"

启动 Mo 前,请使用文件读取工具读取 patch_file 中的每个代码块。移除所有应排除的内容,然后启动会话:

qa start "$brief" --pr https://github.com/acme/shop/pull/412 --url https://preview.example.com --patch "$patch_file"
rm -f "$patch_file"

请在初始启动请求中发送补丁。不要先启动会话再上传补丁:上传完成前,Mo 可能已经开始读取代码。Mo 会结合 PR 修订版和提供的补丁进行源代码调查。在测试和复现期间,请保持目标和补丁不变。使用干净补丁运行时,GitHub 检查会显示为中性状态,因为其源代码包含尚未发布的变更。

Momentic 环境会将一个 BASE_URL 与可复用的非机密变量组合在一起,并使用 staging 这样的名称。--environment NAME 会选择在 Momentic 控制面板的 Environments 下创建的环境,而不是 shell 或 momentic.config.yaml 中的环境。Mo 会在会话启动时将其中的变量复制到会话中。 使用可重复指定的 --env-file 或 --env-var NAME 选项传入本地值和密钥;它们会覆盖匹配的环境变量。--env-var 会转发 qa start 进程环境中已存在的变量;它不接受 NAME=value。切勿将密钥值写入命令或简报。使用 --tunnel 进行私有访问。并发限制在会话启动时固定。如果目标过载,需要降低限制,请运行 qa stop --subagents 并启动新会话。如果目标需要将浏览器交互放慢至人类节奏,请使用 --interaction-speed <default|human>。

跟进会话

使用此监视器打印新发现的错误名称、判定状态和显示状态变化。Mo 需要你提供输入或报告终止状态时,监视器会退出:

seen=""
while :; do
  snapshot=$(qa status "$session_id" --full) ||
    { echo "status request failed"; sleep 30; continue; }
  events=$(jq -r '"displayState \(.displayState // .state)",
    (.findings.bugs[] | "\(.kind) \(.name)"),
    (.findings.verdicts[] | "verdict \(.status)")' \
    <<<"$snapshot" | sort)
  comm -13 <(printf '%s\n' "$seen") <(printf '%s\n' "$events")
  seen=$events
  if [[ $(jq -r '.attentionPending // false' <<<"$snapshot") != true ]] || [[ $(jq -r '.displayState // .state' <<<"$snapshot") == needs_you ]]; then
    case $(jq -r '.displayState // .state' <<<"$snapshot") in
      needs_you | blocked | findings | incomplete | replied | ready | sleeping | cancelled | failed_start | failed | waitingOnUser | idle | stopped) break ;;
    esac
  fi
  sleep 30
done

对于较旧的、仅包含生命周期信息的响应,idle 或 stopped 并不能证明子 Agent 已完成;请在 Web 会话中确认任务已完成。

工作时,请使用能报告监视器输出的主机工具;如果环境支持接收运行中 Agent 消息的执行器子 Agent,也可以使用它。 否则,请保留命令会话,并在各项任务之间检查其输出。

在没有执行器子 Agent 的 Codex 中,请在长时间运行的 exec_command 前台运行监视器,保留其返回的会话 ID,并使用 write_stdin 获取输出。不要追加 &、将其分离运行,或在其仍运行时结束本轮对话。 Shell 变量不会跨独立命令保留,因此请直接填入 Mo 会话 ID,或在设置该 ID 的同一个 Shell 中启动监视器。

你需要处理阻塞问题,并将用户的决定告知 Mo。

displayState 是会话在 UI 中显示的状态。status、read 和 report 都会报告其中相同的状态词:

状态含义
runningRoot Mo 正在工作。
waiting_on_agentsRoot Mo 当前空闲;其内部子 Agent 正在工作。
needs_youMo 需要访问权限、决定或答复。阅读其回复,并使用 qa send 作答。
blocked请求遇到了工具、访问权限、配额或 Agent 故障。检查回复并解决阻塞问题。
findings没有 Agent 正在运行;需要审查错误或问题。
incomplete没有 Agent 正在运行;报告覆盖范围受阻或未经验证。
replied没有 Agent 正在运行;Mo 已回复,但未提供完整的 QA 报告。
checkingMo 正在检查其最新回复。继续轮询结果。
ready没有 Agent 正在运行;已保存的报告完整且无问题。
sleeping没有 Agent 正在运行,也没有报告或最终回复。
cancelled工作已停止。
failed_start会话从未启动。请启动新会话。
failed会话失败。检查其记录。
sessionState 是生命周期状态(starting、working、
waitingOnUser、waitingOnAgents、idle、stopped 或 failed),在三个命令中的值也完全相同。state 是旧版字段,在出现的地方都是
sessionState 的别名。createdAt 是会话创建时间,
lastActivityAt 是最后一次持久化更新的时间。latestTurn 包含
最近一次持久化的助手计时元数据:startedAt、completedAt 和
durationMs。部分计时值使用 null。运行较早版本 API 的服务器可能会在 read 和 report 中省略 displayState;此时请使用
qa status 获取显示用状态词。

对于 Mo 的提问和回复(而非发现),请使用此有界读取:

qa read "$session_id" --from start --timeout 45s --json

它会读取已持久化的对话消息,以及等待期间流式传输的面向用户的消息。 --from latest 也会漏掉在读取开始前完成的轮次。在 read 响应中,displayState 与 status 状态词一致,而 state 和 sessionState 表示生命周期状态。运行较早版本 API 的服务器会省略 displayState;此时请使用 qa status 获取显示用状态词。 timedOut: true 表示 Mo 仍在工作。

使用 --json 时,read 会向 stdout 写入一个 JSON 响应,不输出进度文本。 不使用 --json 时,若读取等待超过两秒,则会向 stderr 输出运行状态信息。返回的消息会写入 stdout,而超时或停止状态文本会写入 stderr。

qa wait "$session_id" --json 会在根 Agent Mo 的轮次结束、停止或需要输入时返回。退出代码 2 表示 Mo 需要输入;4 表示它已停止。 内部子 Agent 可能仍在运行。请确认 qa status 不再报告 running、waiting_on_agents 或 checking,然后检查结果。needs_you 和 blocked 需要处理;findings、incomplete 和 replied 是已结束的结果,但并不能证明 QA 已通过。所有工作结束后,可使用 qa report --require-idle 导出已保存的部分报告。

切勿发送消息询问进度。请使用 status、read 或 wait。 仅在回答阻碍问题,或有意引导或重新检查工作时发送消息:

qa send --session-id "$session_id" --wait 45s "Use the staging account."

在工作进行期间发送消息,会在工具调用之间引导根 Agent Mo,而正在执行的工作会继续进行。Mo 空闲时,消息会启动它的下一轮。若未使用 --wait,请通过 read 确认回复。

完成或修复

呈现最终结果前,请阅读报告。确认覆盖范围符合用户的要求。会话空闲或未发现错误,本身并不能证明 QA 已通过。

如果用户要求修复,请阅读 修复循环。否则,请勿更改应用代码。

选择停止方式:

  • qa stop <session-id> 仅中断根 Agent Mo。子 Agent 会继续测试、提交发现并产生费用。根 Agent Mo 会保持停止状态,直到你下次运行 qa send。使用此命令可在不丢失正在进行的测试的情况下重新引导 Mo。
  • qa stop <session-id> --subagents 还会停止所有正在运行的子 Agent。使用此命令可停止产生费用。仍可通过 qa send 恢复会话。
  • qa archive <session-id> 会取消所有工作、隐藏会话,并拒绝后续的 qa send。只能通过 Web 取消归档。

qa upload 会返回一个沙盒路径。请将该路径发送给 Mo,因为本地路径在它的沙盒中不存在。如果 --output 指定的是目录,请在运行 qa download 前创建目标目录。运行 qa <command> --help 查看语法。

备选方案:无法访问代码仓库时提供源代码上下文

优先在 Mo 中配置 Git 访问,以获取代码仓库上下文。如果无法访问,请告知用户并建议配置访问权限。

无法配置 Git 访问时,请准备一个临时源代码快照,其中只包含 Mo 所需的文件。上传前请检查其中的内容;排除 .env 文件、凭据、私钥、令牌、node_modules、构建输出以及无关的客户数据。测试未提交的工作时,请包含相关的本地更改或经过审查的补丁。

启动会话后,使用 qa upload 上传快照,并使用 qa send 将返回的沙盒路径发送给 Mo。上传后请删除本地临时快照。告知 Mo 将其用作只读上下文、哪些路径具有权威性、它代表的是基线代码还是修改后的代码,以及哪些命令或依赖文件说明了如何使用它。本地路径在 Mo 的沙盒中无法使用。

评论

支持 Markdown