从第一条用例到接入 CI —— 平台使用指南与集成文档都在这里。
平台里有十二个名词。每一节都会讲到自己那个,但「它们之间是什么关系」只在这里讲一次。先看这张流水线,再看每个名词的定义。
一条主线
组织 → 项目 → 版本 + 设备 → 探索 → 功能组 → 用例 → 测试集 → 测试任务 → 报告
前四步是准备,只做一次;从「探索」开始才是测试工作本身。
准备
产出
组织与执行
从零到看见第一份报告,一共五步。每步都可以在界面上完成,不需要写脚本。
权限模型是两层:组织决定你能看到哪些资源,项目决定你在其中能做什么。
执行的前提是两件事:设备在线,且这台设备上装了要测的那个版本。
用例只需要语义明确。怎么定位元素是平台的事,你不需要写任何 locator 或坐标。
一批用例都要先登录,难道每条都写一遍登录步骤?公共步骤就是把这种共用的准备/清理抽出来,定义一次、多处引用。
把多条用例组成一个测试集,一次执行、一份汇总结果。
三个层次各管一件事,分清了就不会用错。
这一节最值得读 —— 看懂结果分档,才知道该找谁修。
报告既给人看,也给流水线看。
让 AI 自己去玩应用,把它理解下来:走过哪些页面、页面上有什么可交互元素、页面之间怎么跳、这些页面合起来是哪几个功能。这些语义数据一旦攒下来,按功能组批量产用例只是它的用途之一 —— 版本对比、功能缺口、覆盖度都建立在它上面。人只做微调,不必从零手写。
平台的操作大多是异步且慢的(执行几分钟、装机十几分钟),通知负责把「跑完了 / 该你了」送到你眼前。
退出码:接入前先看懂这个
| 0 | 通过(也包括「预期失败」xfail:判别器 / 阴性对照用例挂了,符合预期,不要去修它;status 字段能区分) |
| 1 | 用例失败 —— 被测代码有问题,该看(也包括 xpass:预期失败却通过了,说明它盯着的机制不再起作用,先查那个) |
| 2 | 环境错误 —— 设备离线、App 停在登录页等,不是代码的锅 |
为什么把环境错误单独分一档:把环境抖动算成代码问题,几次之后没人再信任这条流水线,最后变成「红了先重跑一遍看看」——那时候测试就白做了。用 --fail-on 可以调整什么算红。
CI 里直接下载,不必装 Go、不必访问 github.com(很多 CI 在内网):
curl -fsSL "https://shiyu.quartzchord.com/v1/cli/download?os=linux&arch=amd64" -o shiyu
chmod +x shiyubash跑一条用例:
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.mdbash跑一整套用例(查询用同一个端点,CI 脚本不必区分跑的是一条还是一套):
shiyu ci run --project "$SHIYU_PROJECT_ID" --apk app-debug.apk \
--suite "回归测试集" --auto-install --wait --junit results/shiyu.xmlbash用 --plan-name / --suite 传名字而不是 UUID:改名后 CI 会明确报错,而不是静默跑错用例。--auto-install 会在设备上没这个包时先装再跑(CI 每次都是新包,基本都要开)。
在你现有的 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/yamlPR 评论需要 permissions: pull-requests: write,并把 GITHUB_TOKEN 传进 env(上面片段已包含)。不传就自动跳过评论、其余照常——我们不会拿一把你没交出来的令牌去写你的仓库。
更喜欢 uses: 写法的话,后续会发布一个薄壳 Action。它与上面的片段能力完全相同,只是省几行 YAML——所有逻辑都在 CLI 里,不依赖任何公开仓库。
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'groovyGitLab 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.xmlyamlMR 评论需要一把带 api scope 的令牌放进 GITLAB_TOKEN(CI_JOB_TOKEN 调不了 notes 接口)。不给就只出 JUnit,不发评论。
装一份 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
# 然后直接说:「帮我在真机上跑一下登录冒烟用例」bashskill 只能给出截图链接。要让 agent 直接「看到」画面并自主修复,需要 MCP Server —— 在规划中。
skill 只能给出截图链接,MCP 能把【截图本身】交给 agent。要做「看图 → 判断 → 改代码 → 重测」的自主循环,用这个:
# CLI 就是 MCP Server,不必另外装东西
claude mcp add shiyu --env SHIYU_API_KEY=shiyu_xxx -- $(pwd)/shiyu mcp
# 然后直接说:「跑一下登录冒烟,挂了就看截图告诉我为什么」bash工具:列项目 / 列用例 / 上传包 / 起执行 / 查进度 / 取失败清单(含截图)。起执行不阻塞,用查进度轮询。
自主探索(会真的在设备上乱点)刻意没有开放给 agent 调用。
不想用 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}/junit | JUnit XML,给 CI 的报告插件消费 |
| GET /test-runs/{id}/allure | Allure 结果文件,给 Allure 报告站点消费 |
| GET /test-runs/{id}/screenshots/{step}/{kind} | 某一步的截图(终态图:该步若重试过,只保留最后一帧;失败排障以此为准) |
完整规格(可用来生成各语言 SDK): https://shiyu.quartzchord.com/api/v1/openapi.yaml
兼容性承诺:字段只增不删;破坏性变更走 /api/v2,v1 至少维护 12 个月;错误 code 只增不改,可以据此写判断逻辑。