›

文档中心

从第一条用例到接入 CI —— 平台使用指南与集成文档都在这里。

名词与关系

平台里有十二个名词。每一节都会讲到自己那个,但「它们之间是什么关系」只在这里讲一次。先看这张流水线,再看每个名词的定义。

一条主线

组织 → 项目 → 版本 + 设备 → 探索 → 功能组 → 用例 → 测试集 → 测试任务 → 报告

前四步是准备,只做一次;从「探索」开始才是测试工作本身。

准备

组织
最外层的容器。成员、设备、项目都属于某个组织。账号加入组织 · 项目和设备归它所有
项目
一个被测应用。用例、报告、探索结果都在项目下。在组织里创建 · 下面挂版本与用例
版本
一个具体的应用包(APK/IPA)。平台自动读出包名与版本号。上传得到 · 装到设备上、被执行引用
设备
真正跑测试的那台手机或云手机。从设备池领用或本地接入 · 执行与探索都要占用它

产出

探索
让 AI 自己去玩应用,边玩边记录。它是产用例的入口。人发起一次 · 产出页面关系图与功能组
页面关系图
探索走过的页面和它们之间的跳转。同一个页面的多次访问会合并成一个节点。探索产出 · 功能分组与产用例都基于它
功能组
把页面关系图按功能切成几块,例如「登录」「消息」「设置」。切分依据是页面之间的连通结构。从图上算出 · 用例按组生成,一组一批
用例
一条测试:若干步骤 + 断言。用自然语言描述,不写 locator。探索生成或人工编写 · 被测试集收编、被执行
公共步骤
可复用的前置或清理动作,例如「登录一次」「清空数据」。多条用例共享同一份,不必各写一遍。在组织或项目下定义 · 被用例引用

组织与执行

测试集
一份用例名单,可反复复用,自己没有状态。人挑用例组成 · 被任务执行
测试计划
某个版本要覆盖的范围与进度。它自己不执行。人为一个版本创建 · 通过其下的任务执行
测试任务
可指派的一份工作:「@张三 在 v2.3 上跑一遍冒烟集」。这是唯一能指派给人的东西。人创建并指派 · 执行测试集、跑完自动完成
报告
一次执行的结果:每步截图、耗时、失败原因与归因分档。执行产生 · 给人看,也能导出给流水线

快速上手:跑通第一条用例

从零到看见第一份报告,一共五步。每步都可以在界面上完成,不需要写脚本。

  • 创建组织与项目 —— 组织是最外层,设备、成员、项目都属于它;项目下再管用例与报告。
  • 上传应用包 —— 在「版本」里上传 APK/IPA,平台自动识别包名与版本号。
  • 准备设备 —— 从设备池领用一台,或用本地设备接入;然后把刚上传的版本装到这台设备上。
  • 写一条用例 —— 用自然语言描述要测什么,平台解析成「动作 + 目标 + 断言」的步骤。
  • 执行并看报告 —— 选设备执行,过程中可实时看画面;结束后报告里有每步截图与耗时。

组织、项目与成员

权限模型是两层:组织决定你能看到哪些资源,项目决定你在其中能做什么。

  • 组织:设备、项目、成员的归属单位。一个人可以属于多个组织,用顶栏切换。
  • 角色:拥有者 / 管理员 / 成员。只有管理员及以上可以创建项目。
  • 邀请:管理员生成邀请码,对方凭码加入;邀请码可限次数、限有效期,也可随时撤销。
  • 项目成员:在项目内单独授予角色,非成员看不到该项目。
  • 跨组织的数据是隔离的 —— 看不到也操作不了别的组织的项目、设备与报告。

应用包与设备

执行的前提是两件事:设备在线,且这台设备上装了要测的那个版本。

  • 上传:在「版本」里上传 APK/IPA,包名是装机的键,不可更改;展示名可以改。
  • 装机是显式动作 —— 在版本管理页对指定设备装,执行时只校验「装没装」,不会临时下载。
  • 设备来源:① 从共享设备池领用;② 本地设备接入(下载 agent,按页面提示配对)。
  • 大包首次装机可能需要十几分钟,进度可见,这不是卡死。
  • 执行前请确认设备状态为在线;离线时执行会报「环境错误」,不算你的应用有问题。

编写测试用例

用例只需要语义明确。怎么定位元素是平台的事,你不需要写任何 locator 或坐标。

  • 用自然语言描述,例如「点击右下角的写信按钮」「输入收件人姓名」「验证消息发送成功」。
  • 目标要说清是哪个元素:方位词(最下方、右上角)和功能名都会被用上,写得越具体越稳。
  • 断言判「当前状态」,不要写「可以进入某页面」这类可达性描述 —— 屏幕上有入口不等于已经到达。
  • 步骤分两个阶段:setup(前置,不计分,用于登录、清理等)与 test(计分的正式步骤)。
  • 支持 CSV / Gherkin 导入、用例克隆、目录归档与版本记录。

公共步骤(Fixture)

一批用例都要先登录,难道每条都写一遍登录步骤?公共步骤就是把这种共用的准备/清理抽出来,定义一次、多处引用。

  • 前置(setup) 在用例正式步骤之前跑,清理(teardown) 在之后跑,且按逆序执行。
  • 前置步骤不计分 —— 登录失败算环境错误,不会被记成「这条用例失败了」。
  • 作用域分两级:组织级(所有项目共用,例如一套测试账号)与项目级(只给这个项目用)。
  • 典型用法:登录态复用。登录一次,后面几十条用例直接从已登录状态开始,省掉几十次重复登录。
  • 另有 `reset_policy` 控制每条用例开始前把应用恢复到什么程度:保持现状 / 清数据 / 回到基线快照。
  • 判据:贵且不能脚本化的(扫码登录)用基线快照;便宜能脚本化的(清缓存、造数据)用公共步骤。

测试集编排

把多条用例组成一个测试集,一次执行、一份汇总结果。

  • 新建方案后加入用例并排序,按顺序串行执行。
  • 可配置:失败重试次数、单条超时、用例之间的依赖关系。
  • 配了依赖时,前置用例失败则后续用例不再执行,并标注原因。
  • 每次执行独立留档,可回看当时用的是哪个版本、哪台设备。

任务、计划与测试集

三个层次各管一件事,分清了就不会用错。

  • 测试集 = 一份用例名单。反复复用,自己没有状态(原来叫「测试方案」,改名是因为专业口径里测试方案指的是技术文档,而这里是一份名单)。
  • 测试计划 = 某个版本要覆盖的范围与进度。它自己不执行,通过其下的任务执行。
  • 测试任务 = 可指派的一份工作:「@张三 在 v2.3 上跑一遍冒烟集」。这是唯一能指派给人的东西。
  • 判据:需要「谁来做、做完没有」的是任务;只需要「包含哪些用例」的是集;需要「这个范围覆盖到什么程度」的是计划。
  • 三条路径:指派给别人(对方收到通知)/ 自己建自己执行(指派人留空)/ 由计划批量组织。
  • 任务完成不用手动点 —— 跑完关联的测试集会自动标记完成,并通知发起人。界面上没有「标记完成」按钮是故意的:给了就会有一批从没真跑过的「已完成」。

执行过程与结果解读

这一节最值得读 —— 看懂结果分档,才知道该找谁修。

  • 执行循环:截图 → 理解画面 → 定位目标 → 执行动作 → 断言校验,逐步推进。
  • 结果分三档,含义完全不同:
  • ① 用例失败 —— 被测应用的问题,该应用开发者去看。
  • ② 环境错误 —— 设备离线、应用未安装、停在登录页等,不代表应用有缺陷。
  • ③ 平台执行缺陷 —— 平台自己没做到(定位不到、动作没生效),请反馈给我们。
  • 每一步都留截图与耗时;失败步骤会附上当时的界面证据。
  • 没有设断言的步骤会显示「未设断言」,不会伪装成「验证通过」。

报告与导出

报告既给人看,也给流水线看。

  • 报告页含步骤明细、每步截图、耗时与失败原因。
  • 可导出 JUnit(接 CI 用)与 Allure(做可视化报告用)。
  • 质量看板汇总通过率趋势与失败分布,用于判断质量走向。
  • 支持按构建版本对比两次执行,定位是哪个版本引入的问题。

应用理解

让 AI 自己去玩应用,把它理解下来:走过哪些页面、页面上有什么可交互元素、页面之间怎么跳、这些页面合起来是哪几个功能。这些语义数据一旦攒下来,按功能组批量产用例只是它的用途之一 —— 版本对比、功能缺口、覆盖度都建立在它上面。人只做微调,不必从零手写。

  • 起一个探索任务 —— 选设备和版本,AI 会自主操作应用,记录访问过的页面与可交互元素。可以同时上传设计文档(PRD、需求稿),让它对照着看。
  • 看功能视图 —— 探索完会得到一张页面关系图,并自动切成若干功能组(登录、消息、设置……)。切分依据是页面之间的连通结构:跨组必须经过枢纽页。
  • 按组产用例 —— 在功能视图上选一个组生成用例。每组会按专业测试准则铺开:主流程、异常处理、边界值、分支覆盖,而不只是把路径抄一遍。
  • 审阅并采纳 —— 生成的用例会先做语义去重(结构指纹 → 步骤序列 → 模型仲裁三层)。判不准时宁可留下重复,也不会误删,所以列表里可能出现相近的两条,由你定夺。
  • 对照设计文档 —— 传了文档的话,可以看四象限差异:文档里有而应用里没走到的(可能漏实现或探索没覆盖到)、应用里有而文档没写的(可能是遗漏的需求)。
  • 两个版本的图可以对比,变更点即测试点。
  • 注意:探索会在真实设备上真实点击。支付、账号安全等敏感操作需要人工授权,不会自动执行。

通知

平台的操作大多是异步且慢的(执行几分钟、装机十几分钟),通知负责把「跑完了 / 该你了」送到你眼前。

  • 顶栏铃铛显示未读数。红点只在真的有未读时出现 —— 它来自服务端,不是估算的。
  • 会通知的事:测试任务被指派给你、你发起的任务完成、用例执行结束、测试集执行结束、探索结束、探索有待授权项。
  • 探索待授权同一会话只有一条通知,后续新增只刷新计数 —— 逐条发会刷屏。
  • 点通知直接跳到对应的执行、任务或探索会话。
  • 账号设置里可以按事件类型配置通知方式。关掉的是打扰,不是记录 —— 即使全部关闭,通知仍会留存,只是不计未读、不亮红点。
  • 邮件与群机器人(飞书/钉钉/Slack)通道尚未开放,可以先保存偏好,开放后即刻生效。

常见问题

执行为什么比较慢?
每一步都要视觉理解画面,模型定位耗时约 3 秒(高峰更慢)。这是视觉方案的固有成本,换来的是不用维护脚本与元素定位。
报「应用未安装」怎么办?
先到版本管理页把目标版本装到该设备上。装机是显式动作,执行时不会自动下载。
为什么结果是「环境错误」而不是失败?
因为问题不在被测应用(比如设备掉线、应用没装)。这样分开是为了不让环境问题冒充应用缺陷。
跨设备的用例怎么写?
给步骤指定设备角色(如发信方 / 收信方),执行时平台把角色绑定到实际设备。设备不足时整个用例失败,不会退化成单机跑完。
用例要写得多细?
语义明确即可。不需要写元素 id、xpath 或坐标;但目标描述要能唯一指向屏幕上的那个元素。

接入与集成

开始接入

  1. 在「设置 → API Keys」创建一把 Key(可限定到单个项目),复制 shiyu_ 开头的字符串。
  2. 存进 CI 的 secret,变量名 SHIYU_API_KEY。
  3. 记下项目 ID(浏览器地址栏里项目页的那串 UUID)。

退出码:接入前先看懂这个

0通过(也包括「预期失败」xfail:判别器 / 阴性对照用例挂了,符合预期,不要去修它;status 字段能区分)
1用例失败 —— 被测代码有问题,该看(也包括 xpass:预期失败却通过了,说明它盯着的机制不再起作用,先查那个)
2环境错误 —— 设备离线、App 停在登录页等,不是代码的锅

为什么把环境错误单独分一档:把环境抖动算成代码问题,几次之后没人再信任这条流水线,最后变成「红了先重跑一遍看看」——那时候测试就白做了。用 --fail-on 可以调整什么算红。

CLI

CI 里直接下载,不必装 Go、不必访问 github.com(很多 CI 在内网):

curl -fsSL "https://shiyu.quartzchord.com/v1/cli/download?os=linux&arch=amd64" -o shiyu
chmod +x shiyu
bash

跑一条用例:

shiyu ci run \
  --project "$SHIYU_PROJECT_ID" \
  --apk app/build/outputs/apk/debug/app-debug.apk \
  --plan-name "登录冒烟" \
  --auto-install --wait \
  --junit results/shiyu.xml \
  --summary-md results/summary.md
bash

跑一整套用例(查询用同一个端点,CI 脚本不必区分跑的是一条还是一套):

shiyu ci run --project "$SHIYU_PROJECT_ID" --apk app-debug.apk \
  --suite "回归测试集" --auto-install --wait --junit results/shiyu.xml
bash

用 --plan-name / --suite 传名字而不是 UUID:改名后 CI 会明确报错,而不是静默跑错用例。--auto-install 会在设备上没这个包时先装再跑(CI 每次都是新包,基本都要开)。

GitHub Actions

在你现有的 workflow 里加一步。不需要安装任何第三方 Action——注解、Job Summary、PR 评论都由 CLI 在检测到 GitHub 环境时自己发:

jobs:
  ui-test:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
    steps:
      - uses: actions/checkout@v7
      - run: |
          curl -fsSL "$SHIYU_ENDPOINT/v1/cli/download?os=linux&arch=amd64" -o shiyu
          chmod +x shiyu
          ./shiyu ci run --project "$SHIYU_PROJECT_ID" \
            --apk app/build/outputs/apk/debug/app-debug.apk \
            --plan-name "登录冒烟" --auto-install --wait \
            --junit results/junit.xml
        env:
          SHIYU_ENDPOINT: https://shiyu.quartzchord.com
          SHIYU_API_KEY: ${{ secrets.SHIYU_API_KEY }}
          SHIYU_PROJECT_ID: ${{ vars.SHIYU_PROJECT }}
          GITHUB_TOKEN: ${{ github.token }}
      - uses: actions/upload-artifact@v7
        if: always()
        with:
          name: shiyu-results
          path: results/
yaml
  • 失败时把摘要贴成 PR 评论(更新同一条,推十次不会刷十条)
  • 环境错误用 warning 而非 error 标注,并明说「不是被测代码的问题」
  • status / run-id / summary 写进 step outputs,后续步骤可直接取用

PR 评论需要 permissions: pull-requests: write,并把 GITHUB_TOKEN 传进 env(上面片段已包含)。不传就自动跳过评论、其余照常——我们不会拿一把你没交出来的令牌去写你的仓库。

更喜欢 uses: 写法的话,后续会发布一个薄壳 Action。它与上面的片段能力完全相同,只是省几行 YAML——所有逻辑都在 CLI 里,不依赖任何公开仓库。

Jenkins / GitLab CI

Jenkins

sh '''
  curl -fsSL "https://shiyu.quartzchord.com/v1/cli/download?os=linux&arch=amd64" -o shiyu && chmod +x shiyu
  ./shiyu ci run --project "$PROJECT" --apk app-debug.apk \
    --plan-name "登录冒烟" --auto-install --junit results/shiyu.xml
'''
junit 'results/shiyu.xml'
groovy

GitLab CI

shiyu-test:
  script:
    - curl -fsSL "https://shiyu.quartzchord.com/v1/cli/download?os=linux&arch=amd64" -o shiyu && chmod +x shiyu
    - ./shiyu ci run --project "$PROJECT" --apk app-debug.apk --plan-name "登录冒烟" --auto-install --junit junit.xml
  artifacts:
    reports:
      junit: junit.xml
yaml

MR 评论需要一把带 api scope 的令牌放进 GITLAB_TOKEN(CI_JOB_TOKEN 调不了 notes 接口)。不给就只出 JUnit,不发评论。

用 Claude Code 接

装一份 skill,让 Claude Code 知道怎么用试玉——改完代码直接说「帮我在真机上跑一下」即可。

# 在你的仓库里
mkdir -p .claude/skills/shiyu-test
curl -fsSL "https://shiyu.quartzchord.com/v1/cli/skill" -o .claude/skills/shiyu-test/SKILL.md

# 然后直接说:「帮我在真机上跑一下登录冒烟用例」
bash
  • 会自己起执行、等结果、拉失败清单
  • 看得懂三档退出码——环境错误不会让它去乱改业务代码
  • 失败时会拉失败那一屏的截图确认,而不是只信文字根因

skill 只能给出截图链接。要让 agent 直接「看到」画面并自主修复,需要 MCP Server —— 在规划中。

MCP Server —— 让 agent 看得见失败画面

skill 只能给出截图链接,MCP 能把【截图本身】交给 agent。要做「看图 → 判断 → 改代码 → 重测」的自主循环,用这个:

# CLI 就是 MCP Server,不必另外装东西
claude mcp add shiyu --env SHIYU_API_KEY=shiyu_xxx -- $(pwd)/shiyu mcp

# 然后直接说:「跑一下登录冒烟,挂了就看截图告诉我为什么」
bash

工具:列项目 / 列用例 / 上传包 / 起执行 / 查进度 / 取失败清单(含截图)。起执行不阻塞,用查进度轮询。

自主探索(会真的在设备上乱点)刻意没有开放给 agent 调用。

直接调 API

不想用 CLI 也可以直接调。所有端点用 Authorization: Bearer [API Key] 鉴权(控制台的登录态不能用于这套接口,反之亦然)。

curl -H "Authorization: Bearer $SHIYU_API_KEY" \
  "https://shiyu.quartzchord.com/api/v1/projects"
bash
端点说明
GET /projects列出该 Key 可见的项目
POST /builds上传应用包(APK / IPA),自动解析包名与版本
GET /builds/{id}查一个构建:包名、版本、abis(null = 没解析过)、装到了哪些设备
POST /installs把包装到设备上(同一个包跑多条用例时先装一次)
GET /test-cases列出用例与测试集
GET /test-runs列出项目最近的执行记录(最新在前,游标分页,可按用例 / 状态过滤)——run id 丢了不必重跑
POST /test-runs起一次执行:选包 + 选用例/测试集 + 按条件选设备 + 按需装机
GET /test-runs/{id}查状态与进度(跑一条和跑一套都查这里)
POST /test-runs/{id}/cancel取消一次执行(排队中或跑到一半都行)
GET /test-runs/{id}/failures失败清单:第几步、做了什么、为什么、那一屏的截图
GET /test-runs/{id}/defect-report缺陷单草稿:可直接贴进 Jira / GitHub 的 Markdown,带截图链接、根因、历史战绩;按归因分档——XFAIL 会被拒,环境错误给自查清单,平台缺陷指向我们
GET /test-runs/{id}/summary可直接贴进 PR 的 Markdown 摘要
GET /test-runs/{id}/junitJUnit XML,给 CI 的报告插件消费
GET /test-runs/{id}/allureAllure 结果文件,给 Allure 报告站点消费
GET /test-runs/{id}/screenshots/{step}/{kind}某一步的截图(终态图:该步若重试过,只保留最后一帧;失败排障以此为准)

完整规格(可用来生成各语言 SDK): https://shiyu.quartzchord.com/api/v1/openapi.yaml

兼容性承诺:字段只增不删;破坏性变更走 /api/v2,v1 至少维护 12 个月;错误 code 只增不改,可以据此写判断逻辑。