Hoppscotch 常用 CLI 命令与工具详解
@hoppscotch/cli 0.31.4(ALPHA)实测:hopp 单命令体系与参数速查、集合 JSON 文件模式(含 v:1 版本号与 auth 对象格式要求)、数据驱动迭代与 JUnit 报告、pw.test 断言要点、PAT 对接自托管实例的团队集合/环境联动与错误面排障。
Hoppscotch 常用 CLI 命令与工具详解
目标:讲清 Hoppscotch 官方命令行工具 @hoppscotch/cli 的完整用法——
hopp test的参数体系、集合文件格式要求、数据驱动测试与 JUnit 报告、测试脚本断言写法,以及通过个人访问令牌(PAT)对接自托管实例执行团队集合。全部命令与回显在 Ubuntu 22.04 实测,对接受测实例 Hoppscotch 2026.9.0(部署见《Hoppscotch Docker Compose 部署指南》)。
一、环境信息
- 操作系统:Ubuntu 22.04(x86_64)
- CLI:@hoppscotch/cli 0.31.4(官方 npm 源,标注 ALPHA 阶段)
- 运行时:Node.js v24(npm 全局安装)
- 对接实例:Hoppscotch 2026.9.0 自托管(后端 API http://localhost:8143)
- 演示账号:
admin@example.com
二、CLI 定位与安装
CLI 是 Hoppscotch 的 CI 执行器定位:无头运行集合测试、产出 JUnit 报告接入流水线,而不是全功能调试客户端(请求构建、脚本编辑仍在 Web/桌面端完成)。
npm i -g @hoppscotch/cli
hopp -v
实测回显:
hopp: The Hoppscotch CLI - Version 0.31.4 (https://hoppscotch.io) ALPHA
💡 说明:CLI 当前为单命令形态——只有
hopp test一个主命令。查看版本用-v/--ver(长选项--version不存在,实测报INVALID_ARGUMENT unknown option '--version'):
$ hopp --version
INVALID_ARGUMENT unknown option '--version'
三、hopp test 参数速查
hopp test --help 实测原文:
Usage: hopp test [options] <file_path_or_id>
running hoppscotch collection.json file
Arguments:
file_path_or_id path to a hoppscotch collection.json
file or collection ID from a workspace
for CI testing
Options:
-e, --env <file_path_or_id> path to an environment variables json
file or environment ID from a workspace
-d, --delay <delay_in_ms> delay in milliseconds(ms) between
consecutive requests within a collection
--token <access_token> personal access token to access
collections/environments from a
workspace
--server <server_url> server URL for SH instance
--reporter-junit [path] generate JUnit report optionally
specifying the path
--iteration-count <no_of_iterations> number of iterations to run the test
--iteration-data <file_path> path to a CSV file for data-driven
testing
--legacy-sandbox Opt out from the experimental scripting
sandbox
-h, --help display help for command
参数要点:
| 参数 | 用法 | 说明 |
|---|---|---|
<file_path_or_id> | 位置参数 | 本地集合 JSON 文件路径,或实例内集合 ID(需 PAT 模式) |
-e, --env | 环境文件路径或环境 ID | 变量注入,<<变量名>> 插值依赖它;实例环境 ID 同样需 PAT |
-d, --delay | 毫秒 | 同集合内相邻请求间隔,压测保护用 |
--token | PAT 令牌 | pat- 前缀令牌,对接自托管实例工作区 |
--server | 实例地址 | 自托管后端地址(如 http://localhost:8143),与 --token 搭配 |
--reporter-junit | 可选路径 | 生成 JUnit XML,路径可省略(默认 junit-report.xml) |
--iteration-count | 次数 | 整个集合重复执行次数 |
--iteration-data | CSV 路径 | 数据驱动:CSV 首行为变量名,逐行注入 |
--legacy-sandbox | 开关 | 退出实验性脚本沙箱(脚本行为异常时的回退项) |
四、文件模式实测
4.1 集合文件格式要求
CLI 按版本化 schema 校验集合 JSON,两个必守格式(均为实测踩坑结论):
- 请求级:
v为字符串"1",且auth必须是对象形态{"authType":"none","authActive":true}——写成旧版字符串"none"会被拒绝; - 集合级:必须带数字版本号
"v": 1——Web 端「导出集合」的原始产物不含该字段,需手工补上。
实测错误面(导出原样文件直接跑,缺集合级 v):
$ hopp test hopp-collection.json -e hopp-env.json
MALFORMED_COLLECTION hopp-collection.json
Please check the collection data.
合规文件最小结构(实测可用,hopp-collection-v1.json):
[
{
"id": "cmvh16hs200030qpf6p8bm6am",
"name": "Demo API",
"folders": [],
"requests": [
{
"v": "1",
"name": "Health Check",
"method": "GET",
"endpoint": "<<baseUrl>>/ping",
"params": [],
"headers": [{ "key": "Accept", "value": "application/json", "active": true }],
"auth": { "authType": "none", "authActive": true },
"body": { "contentType": null, "body": null },
"testScript": "pw.test('status is 200', () => { pw.expect(pw.response.status).toBe(200); });"
}
],
"data": null,
"v": 1
}
]
环境文件(hopp-env.json,<<baseUrl>> 的取值来源):
{
"name": "Local Env",
"variables": [
{ "key": "baseUrl", "value": "http://localhost:8143", "secret": false }
]
}
4.2 运行回显
hopp test hopp-collection-v1.json -e hopp-env.json
实测回显:
Running: Demo API/Health Check
GET http://localhost:8143/ping 200 : OK (0.013 s)
Ran tests in 0.071 s
Test Cases: 0 failed 0 passed
Test Suites: 0 failed 0 passed
Test Scripts: 0 failed 1 passed
Tests Duration: 0.071 s
Requests: 0 failed 1 passed
Requests Duration: 0.013 s
Pre-Request Scripts: 0 failed 1 passed
五、数据驱动与 JUnit 报告
一次带全选项的实测(间隔 200ms、迭代 2 轮、CSV 数据文件、输出 JUnit 报告)。CSV 格式为首行变量名、其后逐行取值(iter-data.csv):
baseUrl
http://localhost:8143
http://localhost:8143
hopp test hopp-collection-v1.json -e hopp-env.json -d 200 --iteration-count 2 --iteration-data iter-data.csv --reporter-junit junit2.xml
实测回显:
Iteration: 1/2
Running: Demo API/Health Check
GET http://localhost:8143/ping 200 : OK (0.012 s)
Ran tests in 0.072 s
Iteration: 2/2
Running: Demo API/Health Check
GET http://localhost:8143/ping 200 : OK (0.003 s)
Ran tests in 0.065 s
Test Cases: 0 failed 0 passed
Test Suites: 0 failed 0 passed
Test Scripts: 0 failed 2 passed
Tests Duration: 0.137 s
Requests: 0 failed 2 passed
Requests Duration: 0.015 s
Pre-Request Scripts: 0 failed 2 passed
Successfully exported the JUnit report to: junit2.xml.
生成的 junit2.xml 实测内容(每轮迭代一个 testsuite,可直接接入 Jenkins/GitLab CI 报告解析):
<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="0" failures="0" errors="0" time="0.137">
<testsuite name="Demo API/Health Check" time="0.072" timestamp="2026-10-20T18:57:58.949Z" tests="0" failures="0" errors="0"/>
<testsuite name="Demo API/Health Check" time="0.065" timestamp="2026-10-20T18:57:58.949Z" tests="0" failures="0" errors="0"/>
</testsuites>
六、测试脚本断言要点(pw.* API)
断言 API 为 pw.expect(实际值).toBe(期望值),但 0.31.4 ALPHA 实测存在关键差异:裸 expect 失败不计数、不影响退出码——对照实测:
裸断言失败(pw.expect('a').toBe('b');):
Test Cases: 0 failed 0 passed
Test Suites: 0 failed 0 passed
Test Scripts: 0 failed 1 passed
退出码 0——CI 中会静默漏报。改用 pw.test(用例名, 回调) 包装后,失败被正确统计且退出码非零:
$ hopp test hopp-col-wrapped.json -e hopp-env.json
Running: Demo API/Health Check
GET http://localhost:8143/ping 200 : OK (0.013 s)
✖ status is 500
Ran tests in 0.071 s
Demo API/Health Check failed tests:
⦁ status is 500
- Expected '200' to be '500'
Test Cases: 1 failed 0 passed
Test Suites: 1 failed 0 passed
Test Scripts: 0 failed 1 passed
Tests Duration: 0.071 s
Requests: 0 failed 1 passed
Requests Duration: 0.013 s
Pre-Request Scripts: 0 failed 1 passed
Exited with code 1
⚠️ 注意:CI 场景务必用
pw.test('用例名', () => { ... })包裹断言,裸 expect 的失败在当前 ALPHA 版本中不进统计。响应体在脚本中是对象而非字符串(如pw.response.body.trim()会报 not a function),按需先取字段再断言。
七、对接自托管实例(PAT 模式)
--token + --server 可直接拉取实例内集合执行,免维护本地文件。令牌为个人访问令牌(PAT),在已登录状态下经后端 REST 创建:
curl -s -X POST http://localhost:8143/v1/access-tokens/create \
-H 'Content-Type: application/json' -H "Cookie: $COOKIE" \
-d '{"label":"cli-demo","expiryInDays":7}'
实测回显:
{"token":"pat-e1b00c6e-f299-455d-b484-8989fda22e93","info":{"id":"cmvh1r4w300000ptie5h0tj7h","label":"cli-demo","createdOn":"2026-10-20T18:58:53.187Z","expiresOn":"2026-10-27T18:58:53.183Z","lastUsedOn":"2026-10-20T18:58:53.187Z"}}
错误面一:假令牌(hopp test <集合ID> --token pat-invalid-token --server http://localhost:8143):
TOKEN_INVALID The specified access token is invalid. Please provide a valid token: pat-invalid-token
错误面二:PAT 访问个人集合(实测被拒——PAT 模式仅开放团队工作区):
INVALID_ID The specified collection/environment (ID or file path) is invalid or inaccessible. Please ensure the supplied ID or file path is correct: cmvh16hs200030qpf6p8bm6am
正确路径:团队集合 + 团队环境。 在 Web 端创建团队工作区并建集合/环境(或经 GraphQL API:createTeam → createRootCollection → createRequestInCollection → createTeamEnvironment),然后以团队集合 ID 运行:
hopp test cmvh1rfm300020ptijsdy34t6 \
--token pat-e1b00c6e-f299-455d-b484-8989fda22e93 \
--server http://localhost:8143 \
-e cmvh1rfmp00040ptibcih4c7q
实测回显(-e 传入团队环境 ID,<<baseUrl>> 正常插值):
Running: Team Smoke/Health Check
GET http://localhost:8143/ping 200 : OK (0.003 s)
✔ status is 200
Ran tests in 0.074 s
Test Cases: 0 failed 1 passed
Test Suites: 0 failed 1 passed
Test Scripts: 0 failed 1 passed
Tests Duration: 0.074 s
Requests: 0 failed 1 passed
Requests Duration: 0.003 s
Pre-Request Scripts: 0 failed 1 passed
退出码 0。PAT 模式小结:--token 走 PAT、--server 指后端 API、集合与环境都必须是团队工作区资源且用实例内 ID。
八、常见问题速查
| 症状 | 报错关键字 | 根因 | 解法 |
|---|---|---|---|
| 文件跑不起来 | MALFORMED_COLLECTION | 集合级缺数字 v:1 或请求 auth 为旧字符串形态 | 补集合级 "v": 1、auth 改对象形态 |
| 断言失败但 CI 绿了 | Test Cases: 0 failed(退出码 0) | 裸 pw.expect 失败不计数(ALPHA 行为) | 用 pw.test('用例名', ...) 包装断言 |
| 插值不替换、请求 URL 无效 | REQUEST_ERROR / Invalid URL | 未带环境或变量缺失 | -e 指定环境文件/环境 ID |
| 拉实例集合报令牌无效 | TOKEN_INVALID | --token 非 PAT 或已过期 | 重新创建 PAT(/v1/access-tokens/create) |
| PAT 拉不到集合 | INVALID_ID | 指向了个人工作区集合/环境 | 换团队工作区资源 ID |
脚本里 body.trim() 报错 | not a function | 响应体是对象非字符串 | 取字段后断言,或用 --legacy-sandbox 回退 |