- 新增/修改
packages/cli/src下的 command(commands/catalog.ts登记、defineCommand实现、options/usage) - 新建或扩展
packages/cli/tests/e2e/*.e2e.test.ts用例 - 为命令补 help / 缺参 / dry-run / 真实集成测试
以上情况必须同步维护 packages/cli/tests/e2e/<topic>.e2e.test.ts。跑测与环境变量见 .cursor/skills/bailian-cli-e2e/SKILL.md。
- 路径:
packages/cli/tests/e2e/<kebab-topic>.e2e.test.ts - 框架:
vite-plus/test;子进程跑 CLI:runClifrom./helpers.ts - 解析 JSON stdout:
parseStdoutJson;输出目录:makeE2eOutputDir(e2eLabelFromMetaUrl(import.meta.url)) - 长任务:
cliTimeoutPrefix();视频用例加test(..., 3_600_000)等显式超时
// 1) 不 skip:分组 + --help,无密钥、无真实 API
describe("e2e: <topic>", () => {
test("<group> 分组展示子命令帮助且成功退出", ...);
test("<subcommand> --help 正常退出", ...);
});
// 2) skipIf:缺参 / dry-run / 真实集成;原有集成用例放最后、勿改逻辑
describe.skipIf(<ready>)("e2e: <topic>(DashScope …)", () => {
test("缺少 --<flag> 时退出为用法错误 (2)", ...);
test("<cmd> --dry-run ...", ...); // 若适用
test("【model】真实流程", ..., LONG_TIMEOUT);
});| 场景 | 条件 |
|---|---|
| 文本/搜索/记忆/配置 | isDashScopeE2EReady() |
| 图像/语音 | isBailianE2EMediaEnabled() && isDashScopeE2EReady() |
| 视频 | isBailianE2EVideoEnabled() && isDashScopeE2EReady() |
| 知识库 | isKnowledgeE2EReady() |
| 视频 download/task | 另需 BAILIAN_E2E_VIDEO_TASK_ID |
- 分组 help:
runCli(["image"])→exitCode === 0,stdout+stderr 含子命令名 - --help:
runCli([..., "--help"])→ stderr 含主要 flags - 缺参:
--non-interactive且不传 required flag →exitCode === 2,stderr 匹配--flag|Missing required argument - --dry-run:仅当实现在联网/上传/写盘之前返回;断言 stdout JSON/文本,不入网
- 真实集成:保留既有用例名称与断言;放在 skip 块末尾
- 禁止真实破坏性操作:
auth logout只用--dry-run;config set只用--dry-run - 不加 dry-run:
dryRun在resolveFileUrl/resolveCredential/ 上传之后的命令(如image edit、speech recognize带--url) --list-voices等旁路:先于--text校验的 flag,缺参用例勿带该 flag- 新增 required option → 至少一条缺参用例;改 dry-run 输出 → 更新对应断言
-
commands/catalog.ts登记 +tests/e2e/<topic>.e2e.test.ts(新建或扩展) - 若改了
usage/options/examples,跑pnpm --filter bailian-cli run generate:reference更新tools/generated/reference/(本仓库 gitignore) - 顶层:分组 help + 子命令
--help(多子命令则各一条 help) - skip 块:每个 required flag 缺参;可 dry-run 则加一条
- 至少一条真实集成(或说明为何仅 smoke);不破坏已有集成用例顺序
-
pnpm test packages/cli/tests/e2e/<file>通过
test("foo bar 缺少 --prompt 时退出为用法错误 (2)", async () => {
const { stderr, exitCode } = await runCli(["foo", "bar", "--non-interactive"]);
expect(exitCode).toBe(2);
expect(stderr).toMatch(/--prompt|Missing required argument/i);
});
test("foo bar --dry-run 仅输出计划", async () => {
const { stdout, stderr, exitCode } = await runCli([
"foo",
"bar",
"--dry-run",
"--prompt",
"x",
"--non-interactive",
"--output",
"json",
]);
expect(exitCode, stderr).toBe(0);
const data = parseStdoutJson<{ request?: unknown }>(stdout);
expect(data.request).toBeDefined();
});- E2E:单条/少量调用、断言固定、可进
vp test(见上文 skip 条件) - 批量压测:
packages/cli/tests/stress/run.mjs+targets/*.mjs,并发 + 报告,仅手动pnpm run test:stress -- <target>
勿把压测并入 E2E 或默认 CI。详见 stress-batch-tests.md。