首页
/ Gemini CLI 集成测试体系全解:构建、运行、沙箱矩阵与内存/性能回归基线

Gemini CLI 集成测试体系全解:构建、运行、沙箱矩阵与内存/性能回归基线

2026-09-06 12:42:30作者:范靓好Udolf

Gemini CLI 的集成测试框架负责在受控环境中执行构建产物(bundle),验证 CLI 与文件系统、PTY 交互、遥测等端到端行为的正确性。本篇基于仓库文档 docs/integration-tests.md 及其背后的源码实现展开,读完后你将掌握:如何构建待测 bundle、如何按沙箱矩阵运行 e2e 测试、如何用 golden 文件机制回放模型响应、如何用 deflake 脚本与 CI 工作流保障测试稳定性,以及如何运行内存与性能回归测试并更新基线。

框架总览

集成测试的目标是验证 Gemini CLI 的端到端功能:测试进程拉起已构建的 CLI 产物,在隔离的文件系统目录中运行它,并断言其行为符合预期。测试位于 integration-tests/ 目录,使用自定义测试运行器驱动——从源码结构看,该运行器由 Vitest 与 TestRig 测试装备类组合而成:

  • Vitest 配置见 integration-tests/vitest.config.ts:单测试超时 5 分钟、自动重试 2 次、启用文件级并行(8~16 线程),并通过全局环境变量 GEMINI_TEST_TYPE: 'integration' 标记测试类型;
  • TestRig 位于 packages/test-utils/src/test-rig.ts,负责创建隔离的测试工作区与假 HOME 目录、生成 settings.json、以子进程或 PTY 方式启动 CLI、解析遥测日志并做断言辅助。

值得注意的实现细节:TestRig 通过环境变量选择被测对象——默认执行 bundle/gemini.js(见 BUNDLE_PATH 定义),设置 INTEGRATION_TEST_GEMINI_BINARY_PATH 可换为自定义二进制,设置 INTEGRATION_TEST_USE_INSTALLED_GEMINI=true 则改为验证已安装的 gemini 命令。启动前的 _getCleanEnv 会清除大部分 GEMINI_* 环境变量(保留 GEMINI_API_KEYGEMINI_MODELGEMINI_DEBUG 等白名单项),并把 GEMINI_CLI_HOME 指向测试专用 HOME,确保测试环境不受本机配置污染。

准备待测构建包

运行任何集成测试前,必须先构建一个真正可测的 release bundle:

npm run bundle

对应 package.json 中的 bundle 脚本,它会先生成 git commit 信息、构建 devtools 包与浏览器 MCP,再用 esbuild 产出 bundle/gemini.jsTestRig 拉起的正是这个文件,因此修改 CLI 源码后必须重新执行该命令,而修改测试代码则无需重新构建。

运行测试:命令与沙箱矩阵

集成测试不包含在默认的 npm run test 中,必须显式运行。最常用的快捷方式是:

npm run test:e2e

package.json 可以看到,它实际等价于 cross-env VERBOSE=true KEEP_OUTPUT=true npm run test:integration:sandbox:none,即默认以“无沙箱 + 保留输出 + 详细日志”的方式运行,方便本地调试。

沙箱矩阵

test:integration:all 会依次在三种沙箱环境下跑完整套测试:

npm run test:integration:all

也可以单独运行某一类:

npm run test:integration:sandbox:none
npm run test:integration:sandbox:docker
npm run test:integration:sandbox:podman

从脚本定义看,三者的差异完全由环境变量 GEMINI_SANDBOX 驱动:

  • sandbox:noneGEMINI_SANDBOX=false vitest run --root ./integration-tests
  • sandbox:dockerGEMINI_SANDBOX=docker,并且会先执行 npm run build:sandbox 构建沙箱容器镜像,再运行测试;
  • sandbox:podmanGEMINI_SANDBOX=podman 直接运行。

TestRig 生成的 settings.json 中会写入 sandbox: env['GEMINI_SANDBOX'](见 _createSettingsFile 实现),使被测 CLI 按指定沙箱启动。此外 TestRig.getDefaultTimeout() 会按环境调整轮询超时:CI 上 60 秒、容器内 30 秒、本地 15 秒。

运行子集测试与按名称定位

要运行部分测试文件,直接使用文件名(不含扩展名)作为参数,命令是 test:e2e 或任一 test:integration* 脚本:

npm run test:e2e list_directory write_file

要按测试名运行单个测试,使用 Vitest 的 --test-name-pattern 标志(注意双横线透传):

npm run test:e2e -- --test-name-pattern "reads a file"

模型响应 golden 文件回放机制

集成测试大多不依赖真实模型,而是使用伪造的模型响应(fake responses)做确定性回放。TestRig.setup() 会把指定的 .responses 文件拷贝到测试目录,并向 CLI 传递对应参数(见 _getCommandAndArgs):

  • 常规回放:--fake-responses <path>
  • 非严格模式:--fake-responses-non-strict <path>
  • 录制模式:当 REGENERATE_MODEL_GOLDENS=true 时改为 --record-responses <path>,让 CLI 把真实模型输出写入文件。

重新生成 golden 文件

随着实现变化,golden 文件需要不定期重新录制:

REGENERATE_MODEL_GOLDENS="true" npm run test:e2e

警告:本地录制时,请检查更新后的响应中是否包含模型可能带出的你本人或系统的敏感信息,提交前应审查这些内容。

警告:测试结尾必须执行 await rig.cleanup(),否则录制的新响应不会从测试目录拷回原 golden 文件——TestRig.cleanup() 中正是判断 REGENERATE_MODEL_GOLDENS === 'true' 后才执行 copyFileSync 回写源文件(见 test-rig.ts)。

Deflake:新测试入库前的稳定性验证

新增集成测试前,应先用 deflake 机制至少跑 5 遍,确认它不是不稳定测试(flaky)。

Deflake 脚本

npm run deflake -- --runs=5 --command="npm run test:e2e -- -- --test-name-pattern '<your-new-test-name>'"

scripts/deflake.js 的参数为 --command(必选,要重复执行的命令)与 --runs(次数,默认 5)。脚本的额外细节是:运行前会临时把 .dockerignore 替换为仅包含 .integration-tests 的内容(避免测试目录被打包进沙箱镜像),结束后恢复原文件;任一运行失败,最终退出码为 1。仓库还提供了针对整条集成命令的快捷脚本 deflake:test:integration:sandbox:none / :docker 等。

Deflake 工作流

在 CI 侧也可以用 GitHub Actions 工作流远程执行:

gh workflow run deflake.yml --ref <your-branch> -f test_name_pattern="<your-test-name-pattern>"

工作流定义位于 .github/workflows/deflake.yml

内存回归测试

内存回归测试用于检测关键 CLI 场景下的堆增长与泄漏,位于 memory-tests/ 目录。它与普通集成测试的区别在于:测量内存占用并与提交到仓库的基线比较。

运行

内存测试同样不在 npm run testnpm run test:e2e 中,CI 中夜间运行,本地手动执行:

npm run test:memory

更新基线

如果有意变更了影响内存的行为,可更新基线:

UPDATE_MEMORY_BASELINES=true npm run test:memory

这会运行测试、取中位数快照并覆盖 memory-tests/baselines.json。更新后应审查变更再提交。

工作原理

Harness 为 packages/test-utils 中的 MemoryTestHarness(见 memory-test-harness.ts):

  • 多次强制垃圾回收以降低噪声;
  • 取中位数快照过滤毛刺;
  • 与基线比较,容忍度为 10%;
  • 提供 analyzeSnapshots() 分析跨 3 个快照的持续性泄漏。

数据源是被测 CLI 输出的 gemini_cli.memory.usage 遥测指标——TestRigreadMemoryMetrics() 会从 telemetry.log 中解析该指标并按时间戳聚合为内存快照序列。

性能回归测试

性能回归测试检测墙钟时间、CPU 占用与事件循环延迟的退化,位于 perf-tests/ 目录,同样与标准集成测试分离,因为它的比较对象是提交的性能基线。

运行

npm run test:perf

更新基线

UPDATE_PERF_BASELINES=true npm run test:perf

该过程会多次运行测试(含预热),做 IQR 离群点过滤后覆盖 perf-tests/baselines.json,审查后提交。

工作原理

Harness 为 PerfTestHarness(见 perf-test-harness.ts):

  • 使用 performance.now() 测量墙钟时间;
  • 使用 process.cpuUsage() 测量 CPU 占用;
  • 使用 perf_hooks.monitorEventLoopDelay() 监控事件循环延迟;
  • 应用 IQR(四分位距)过滤剔除离群样本;
  • 与基线比较,容忍度为 15%。

诊断:KEEP_OUTPUT 与 VERBOSE

运行器提供两个环境变量用于排障:

保留测试输出

把测试运行期间创建的临时文件保留下来,便于检查文件系统相关问题:

KEEP_OUTPUT=true npm run test:integration:sandbox:none

保留输出时,运行器会打印本次运行唯一目录的路径。

详细日志

VERBOSE=true npm run test:integration:sandbox:none

两者同时设置时,输出既流式打印到控制台,也写入测试临时目录中的日志文件。详细日志的格式会明确标出日志来源:

--- TEST: <log dir>:<test-name> ---
... output from the gemini command ...
--- END TEST: <log dir>:<test-name> ---

从实现看,KEEP_OUTPUT/VERBOSE 的作用贯穿整个 TestRig:子进程 stdout/stderr 与 PTY 输出在两个变量任一为 true 时都会回显到控制台;而 integration-tests/globalSetup.ts 在 teardown 阶段会删除本次运行的 .integration-tests/<run-id>/ 目录,除非 KEEP_OUTPUT=true——这正是“保留输出”语义的落点。

测试产物目录结构

每次集成测试运行会在 .integration-tests 目录内创建唯一的运行目录,其中每个测试文件一个子目录、每个测试用例一个子目录:

.integration-tests/
└── <run-id>/
    └── <test-file-name>.test.js/
        └── <test-case-name>/
            ├── output.log
            └── ...other test artifacts...

globalSetup 会为运行目录写入 INTEGRATION_TEST_FILE_DIR,并自动清理历史运行目录(保留最近 5 次以便调试)。TestRig.setup() 在此目录下按 <testDir>(工作区)与 <testDir>-home(假 HOME)组织每个用例的产物,并预写两份 settings.json(项目级与用户级)及 state.json,其中将遥测目标强制指向本地收集器文件 telemetry.log、关闭自动更新、关闭 IDE 连接提示——这些都是保证测试可复现的关键配置。

Lint 与格式化

集成测试文件与主构建流程一样接受 lint 检查,也可手动运行:

npm run lint

加上自动修复:

npm run lint:fix

持续集成

为确保集成测试始终执行,仓库定义了 chained_e2e.yml 工作流(名为 “Testing: E2E (Chained)”)。从工作流定义看,它的触发条件包括:

  • pushmain 分支;
  • merge_group(PR 进入合并队列时);
  • 由 “Trigger E2E” 工作流完成事件链式触发,以及手动 workflow_dispatch(可指定 head_sha 与仓库名);

工作流带并发组控制(同分支取消进行中任务)与 pending 状态上报逻辑,并在 sandbox:nonesandbox:dockersandbox:podman 三类沙箱环境中分别运行集成测试,保证 Gemini CLI 在每种沙箱形态下都被覆盖验证。

关键命令与环境变量速查

命令 / 变量 作用
npm run bundle 构建待测 release bundle(CLI 源码变更后必须重跑)
npm run test:e2e 快捷运行:VERBOSE=true KEEP_OUTPUT=true + 无沙箱
npm run test:integration:all 依次跑 none / docker / podman 三套沙箱
npm run test:integration:sandbox:<none|docker|podman> 单跑某一沙箱形态
--test-name-pattern "<name>" 按测试名运行单个用例
REGENERATE_MODEL_GOLDENS=true 录制并回写模型响应 golden 文件
npm run deflake -- --runs=5 --command="..." 本地重复运行以验证稳定性
gh workflow run deflake.yml -f test_name_pattern="..." CI 侧 deflake
npm run test:memory / UPDATE_MEMORY_BASELINES=true 内存回归测试 / 更新基线
npm run test:perf / UPDATE_PERF_BASELINES=true 性能回归测试 / 更新基线
KEEP_OUTPUT=true 保留 .integration-tests/<run-id>/ 产物供排查
VERBOSE=true 流式回显子进程/PTY 输出并写入日志
RUN_FLAKY_INTEGRATION=1 启用被标记为 flaky 的测试(见 test-helper.tsskipFlaky 逻辑)

相关入口文件:integration-tests/(测试用例与 vitest 配置)、packages/test-utils/src/test-rig.ts(测试装备核心)、packages/test-utils/src/memory-test-harness.tspackages/test-utils/src/perf-test-harness.ts(回归 harness)、scripts/deflake.js(deflake 脚本)、.github/workflows/chained_e2e.yml(CI 定义)。注意运行集成测试要求 Node.js ≥ 20(见 package.jsonengines 声明),且 docker 沙箱形态依赖预先构建的沙箱镜像(npm run build:sandbox 会作为其前置步骤自动执行)。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.74 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.81 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
595
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
920
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.63 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
518
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
389