Skip to content

命令行驱动的测试体系

核心问题

传统 Web 项目的测试方式依赖大量手动操作:

写代码
  → 启动 Spring Boot / ASP.NET 应用
    → 打开浏览器 / Swagger UI
      → 手动构造请求参数
        → 点"发送"查看返回
          → 切到数据库确认结果
            → 发现问题?重复以上步骤

这个过程每次都要重复:启动服务器、打开 UI、手动操作、肉眼检查。不仅慢,而且不可重复、不可验证、对 AI 不友好——AI 无法"点击 Swagger 按钮"。

CLI 命令 vs Swagger 手动测试


思路:一切皆 CLI 命令

把测试、验证、调试、打包、发布全链路脚本化。每条命令可独立执行、可持续集成、可被 AI 直接调用。

传统做法:                    CLI 做法:
启动 Web 服务器                http POST /api/bill body=@data.json
打开 Swagger UI               npx playwright test
手动构造请求                   ./scripts/build.ps1
肉眼检查结果                   ./scripts/package.ps1

CLI 命令的输入是参数,输出是结构化结果,中间是确定性的执行逻辑——这正是 AI 最擅长的处理模式。


分层分治:独立工程 × 独立测试

测试不应该混在业务代码里。我们的实践是:每层对应一个独立的测试工程,每个工程只测自己那一层的逻辑。

Java 项目(wukong)

wukong-server/
├── wukong-web/                  ← Controller 层
├── wukong-business/             ← Service 层
├── wukong-domain/               ← Mapper 层
├── wukong-test/                 ← Service 层测试(独立工程)
├── wukong-integration-test/     ← 集成测试(独立工程)
└── wukong-component/            ← 组件服务
  • wukong-test:Service 层单元测试。Service 的方法参数是扁平的(前面第 02 章提到的扁平化改造),构造测试用例非常简单——几行代码就能组装参数调用,不需要 Mock 复杂的对象链。
  • wukong-integration-test:跨层的集成测试。验证 Controller → Service → Mapper 的全链路是否正常。
  • 未来:wukong-domain 层测试,纯粹的 SQL 验证,因为 domain 层就是 Mapper 接口 + XML,测试起来最简单。

C# 项目(Components)

Components/
├── Components.Test/              ← 通用组件测试
├── Workflow.Integration.Test/    ← 工作流集成测试
├── AiAgent.Integration.Test/     ← Agent 集成测试
└── AiAgent.Embedded.Test/        ← 嵌入式 Agent 测试

每层独立工程带来的好处是:测试可以独立运行,不需要启动整个应用。 启动一个测试工程就是执行一条 CLI 命令,不依赖 Web 服务器、不依赖数据库(Mock 或嵌入式数据库即可)。

分层测试架构


实践一:命令式接口测试

传统做法需要启动完整的 Web 服务器,通过 Swagger UI 手动测试。

CLI 做法是用命令行直接模拟客户端请求,不需要启动 Web 服务器也能测试:

bash
# 模拟 HTTP 请求(httpie)
http POST localhost:8080/api/bill/create \
  title="测试账单" \
  amount:=100.00 \
  userId:=1

# 模拟 FTP 上传
ftp-put localhost:21 test-file.txt /remote/path/

# 模拟外部 API(Prism Mock)
prism mock api-spec/openapi.yaml --port 4010

# 模拟数据库查询
./scripts/query-db.ps1 "SELECT * FROM bill WHERE status = 'PENDING'"

每条命令都可以独立运行,不需要等待服务器启动、不需要手动构造请求体。AI 可以直接调用这些命令来验证接口行为。


实践二:Playwright E2E 测试与前端调试

前端测试依赖浏览器环境,传统做法是手动打开页面、操作、检查。Playwright 将这一切脚本化:

bash
# 运行全部 E2E 测试
npx playwright test

# 运行单个测试文件
npx playwright test tests/bill-flow.spec.ts

# 前端 JS 排错——追踪 JS 运行时错误
npx playwright test --debug

# 录制用户操作生成测试代码
npx playwright codegen http://localhost:5173

Playwright 的 --debug 模式可以在测试执行时实时查看 DOM 状态、网络请求、Console 错误,替代了传统的手动打开 DevTools 排查的方式。

typescript
// 一个典型的 E2E 测试用例
test('创建账单流程', async ({ page }) => {
    await page.goto('/bill/create');

    // 监听 JS 错误
    const errors: string[] = [];
    page.on('pageerror', err => errors.push(err.message));

    await page.fill('#title', '测试账单');
    await page.fill('#amount', '100.00');
    await page.click('button[type="submit"]');

    // 验证成功提示
    await expect(page.locator('.success-message')).toBeVisible();
    expect(errors.length).toBe(0);  // 无 JS 错误
});

Skill 驱动的测试生成与执行

CLI 测试体系遇上 Qoder 的 Skill 机制,产生了更高层次的效率:测试类可以自动生成,测试可以自动执行,整个过程由 Skill 标准化。

测试生成 Skill

思路是定义两个 Skill:

  • 生成服务测试类:根据 Service 类签名,自动生成对应的测试类框架——包括 Mock 注入、测试数据结构、断言模板。
  • 生成接口测试:根据 Controller 接口定义,自动生成集成测试用例——包括请求构造、参数填充、结果验证。
// Skill: generate-service-test
// 输入:Service 类路径
// 输出:完整的测试类文件
// 规则:
//   1. 参数扁平化——利用扁平化改造后的 Service 签名
//   2. Mock 最小化——只 Mock 外部依赖,不 Mock 内部 Mapper
//   3. 断言标准化——统一使用 Assert 或 Shouldly
//
// Skill: generate-integration-test
// 输入:Controller 类路径 + OpenAPI 定义
// 输出:集成测试用例
// 规则:
//   1. 自动解析请求参数结构
//   2. 生成 Httpie/curl 等价命令
//   3. 包含状态码和响应体断言

测试执行 Skill

有了测试类之后,执行测试同样通过 Skill 标准化:

// Skill: run-service-tests
// 行为:执行指定 Service 的测试类,输出通过/失败
//
// Skill: run-integration-tests
// 行为:启动测试容器(数据库/模拟服务)→ 执行集成测试 → 报告结果

wukong 项目目前还没有实现这套 Skill 的自动化生成,但完全可以这样做。CLI 测试体系提供了基础(每条测试命令都是可执行的),Skill 在此基础上提供了一层自动编排。

为什么这比 IDE 的测试工具好

传统的 IDE 测试工具(如 IntelliJ 的测试运行器):

  • 需要手动点击运行
  • 测试结果只有人能看到
  • 无法在 CI 中复用同样的操作

Skill 驱动的测试:

  • AI 可以直接调用 Skill 生成并执行测试
  • 测试结果可以被 Skill 解析并反馈给 AI
  • 同样的 Skill 在开发环境和 CI 中行为一致

实践三:依赖与运行环境管理

测试和构建需要特定的运行时环境。传统做法是手动安装配置,CLI 做法是脚本自动完成:

powershell
# 下载并配置 Node.js
./scripts/setup-node.ps1

# 下载并配置 Python 虚拟环境
./scripts/setup-python.ps1

# 启动所有模拟服务(HTTP Mock / FTP Mock / Prism)
./scripts/start-mocks.ps1

# 启动开发环境
./scripts/start-dev.ps1

每个人(包括 CI 机器)执行同样的脚本,得到同样的环境。AI 也可以在沙箱中直接运行这些脚本来搭建测试环境。


实践四:打包与发布

发布流程同样可以脚本化:

powershell
# 构建
./scripts/build.ps1

# 运行全部检查(lint + test + build)
./scripts/verify.ps1

# 打包安装包
./scripts/package.ps1

# 发布到指定环境
./scripts/deploy.ps1 -Environment staging

每条命令可以独立运行,也可以在 CI 中串联执行。AI 可以执行 verify.ps1 来确认代码是否可以发布,而不需要手动走完整个流程。


为什么这对 AI 友好

维度Swagger/UI 手动测试CLI 命令测试
AI 可执行❌ AI 无法"点击按钮"✅ AI 直接调用 Bash 工具
可重复性❌ 手动操作因人而异✅ 相同输入 = 相同输出
可编排❌ 无法串联自动化✅ 管道/脚本串联
验证方式肉眼检查返回数据断言/退出码验证
上下文消耗手动操作不在代码中CLI 命令本身就是代码

核心原因:CLI 命令是"可执行的代码",Swagger 操作是"不可记录的意图"。 AI 能执行代码、理解代码、生成代码——但它无法操作 UI。


IDE 工具的未来

谈到 CLI 和 AI,一个自然的问题是:IDEA、VS Studio 这类传统 GUI 编程工具还有存在的必要吗?

以我最近的实践经验来看——自从全面使用 Qoder + CLI + LLM 的工作流之后,我已经大半年没有打开过 IDEA 或 VS Studio 了。

IDE 曾经的两个核心价值

价值一:快速启动应用

IDE 最擅长的是"一键启动"——点一个按钮就能启动 Spring Boot、ASP.NET 应用,自动配好调试端口、环境变量。但 CLI 脚本完全可以替代这一点:

powershell
# 一条命令启动应用,和 IDE 点按钮一样快
./scripts/start-dev.ps1

而且 CLI 方式更好——启动参数是显式的、可重复的、可以被 AI 直接调用。IDE 的启动配置藏在菜单里,AI 无法操作。

价值二:大规模重构

IDE 的"重命名"、"提取接口"、"移动方法"等重构功能确实强大。但这类需求在 AI 时代越来越少:

  • 如果代码是 AI 生成的,从一开始就应该是正确的,不需要事后重命名
  • 如果真的要批量修改,AI 直接改代码比 IDE 的 Refactor 更聪明——它理解语义,不只是改符号
  • 通过 CLI + ripgrep + sed 等工具,批量化操作一样可以做

IDE 解决不了的问题

IDE 的核心能力建立在"人能看懂代码"的前提上。它辅助的是人的阅读和操作——语法高亮、代码补全、调试器。但:

  • AI 不需要语法高亮,它直接理解 AST
  • AI 不需要代码补全,它直接生成完整代码
  • AI 不需要可视化调试器,它通过日志和测试验证行为

更关键的是:IDE 是 GUI 程序,AI 无法操作它。 在 AI 主导编码的时代,一个 AI 无法操作的工具,就是枷锁。

CLI + AI 已经足够

现在的项目开发流程已经完全脱离了 IDE:

# 写代码:Qoder + LLM,直接生成
# 测代码:CLI 命令 + Skill,自动执行
# 查代码:ripgrep + CLI 搜索,比 IDE 的查找更快
# 改代码:AI 理解语义后直接修改,比 IDE 重构更智能
# 跑应用:CLI 脚本启动,参数显式可重复
# 调 Bug:日志 + 测试 + AI 分析,比调试器更高效

未来趋势

可以预见,传统的 GUI 编程软件会逐渐消失——不是因为它们不好,而是因为"通过 GUI 操作代码"这个范式本身在 AI 时代变得低效。

取而代之的是 Qoder + LLM + CLI 这样的组合:

  • Qoder 提供 AI 上下文管理、Skill 编排、Agent 调度
  • LLM 提供代码生成、理解、推理能力
  • CLI 提供可执行、可编排、可验证的工程支撑

三者叠加,已经完全覆盖了传统 IDE 的所有核心功能,而且在 AI 友好性上有数量级的提升。


与第 08 章的关系

这一章是第 08 章"可执行优于可声明"原则的工程实践预演

  • 第 08 章将从原则层面讨论:为什么声明式的注解(@Transactional)对 AI 不友好,编程式代码更好
  • 这一章从工程实践层面讨论:为什么声明式的测试流程(手动操作 Swagger)对 AI 不友好,CLI 脚本更好

两者说的是同一件事:AI 时代,能用可执行代码表达的行为,就不要用不可执行的声明/手动操作来表达。


本章小结

分层测试架构

测试层覆盖范围独立工程CLI 命令
Service 层测试业务逻辑正确性wukong-testdotnet test wukong-test
集成测试跨层协作wukong-integration-testdotnet test wukong-integration-test
Domain 层测试SQL 正确性规划中dotnet test wukong-domain-test
E2E 测试UI 交互web-e2enpx playwright test

传统 vs CLI

场景传统做法CLI 做法
接口测试启动服务器 → Swagger 手动测试http POST /api
前端测试手动操作浏览器 → 看控制台npx playwright test --debug
环境搭建手动安装依赖配置./scripts/setup-*.ps1
模拟服务手动启动 Mock 服务./scripts/start-mocks.ps1
打包发布IDE 菜单操作./scripts/package.ps1
测试生成手动写测试类Skill 自动生成
测试执行IDE 点击运行Skill 自动化执行

关联:下一章将这套 CLI 驱动的工程实践,抽象为通用的"面向 AI 的架构原则"。