---
read_when:
  - 在本地或 CI 中运行测试
  - 为模型/提供商问题添加回归测试
  - 调试 Gateway 网关 + 智能体行为
summary: 测试套件：单元/端到端/实时测试套件、Docker 运行器，以及每个测试的覆盖范围
title: 测试
x-i18n:
  generated_at: "2026-02-03T09:23:12Z"
  model: claude-opus-4-5
  provider: pi
  source_hash: 8c236673838731c49464622ac54bf0336acf787b857677c8c2d2aa52949c8ad5
  source_path: help/testing.md
  workflow: 15
---

# 测试

Fased 包含三个 Vitest 测试套件（单元/集成、端到端、实时）以及一小组 Docker 运行器。

本文档是一份"我们如何测试"的指南：

- 每个套件覆盖什么（以及它刻意*不*覆盖什么）
- 常见工作流程应运行哪些命令（本地、推送前、调试）
- 实时测试如何发现凭证并选择模型/提供商
- 如何为现实中的模型/提供商问题添加回归测试

## 快速开始

日常使用：

- 完整检查（推送前的预期流程）：`pnpm build && pnpm check && pnpm test`

当你修改测试或需要额外的信心时：

- 覆盖率检查：`pnpm test:coverage`
- 端到端套件：`pnpm test:e2e`

调试真实提供商/模型时（需要真实凭证）：

- 实时套件（模型 + Gateway 网关工具/图像探测）：`pnpm test:live`

提示：当你只需要一个失败用例时，建议使用下文描述的允许列表环境变量来缩小实时测试范围。

## 测试套件（在哪里运行什么）

可以将这些套件理解为"逐渐增强的真实性"（以及逐渐增加的不稳定性/成本）：

### 单元/集成测试（默认）

- 命令：`pnpm test`
- 配置：`vitest.config.ts`
- 文件：`src/**/*.test.ts`
- 范围：
  - 纯单元测试
  - 进程内集成测试（Gateway 网关认证、路由、工具、解析、配置）
  - 已知问题的确定性回归测试
- 预期：
  - 在 CI 中运行
  - 不需要真实密钥
  - 应该快速且稳定

### 端到端测试（Gateway 网关冒烟测试）

- 命令：`pnpm test:e2e`
- 配置：`vitest.e2e.config.ts`
- 文件：`src/**/*.e2e.test.ts`
- 范围：
  - 多实例 Gateway 网关端到端行为
  - WebSocket/HTTP 接口、节点配对和较重的网络操作
- 预期：
  - 在 CI 中运行（当在流水线中启用时）
  - 不需要真实密钥
  - 比单元测试有更多活动部件（可能较慢）

### 实时测试（真实提供商 + 真实模型）

- 命令：`pnpm test:live`
- 配置：`vitest.live.config.ts`
- 文件：`src/**/*.live.test.ts`
- 默认：通过 `pnpm test:live` **启用**（设置 `FASED_LIVE_TEST=1`）
- 范围：
  - "这个提供商/模型用真实凭证*今天*实际能工作吗？"
  - 捕获提供商格式变更、工具调用怪癖、认证问题和速率限制行为
- 预期：
  - 设计上不适合 CI 稳定运行（真实网络、真实提供商策略、配额、故障）
  - 花费金钱/使用速率限制
  - 建议运行缩小范围的子集而非"全部"
  - 实时运行会加载 `~/.profile` 以获取缺失的 API 密钥
  - Anthropic 密钥轮换：设置 `FASED_LIVE_ANTHROPIC_KEYS="sk-...,sk-..."`（或 `FASED_LIVE_ANTHROPIC_KEY=sk-...`）或多个 `ANTHROPIC_API_KEY*` 变量；测试会在遇到速率限制时重试

## 我应该运行哪个套件？

使用这个决策表：

- 编辑逻辑/测试：运行 `pnpm test`（如果改动较大，加上 `pnpm test:coverage`）
- 涉及 Gateway 网关网络/WS 协议/配对：加上 `pnpm test:e2e`
- 调试"我的机器人挂了"/提供商特定故障/工具调用：运行缩小范围的 `pnpm test:live`

## 实时测试：模型冒烟测试（配置文件密钥）

实时测试分为两层，以便隔离故障：

- "直接模型"告诉我们提供商/模型是否能用给定的密钥正常响应。
- "Gateway 网关冒烟测试"告诉我们完整的 Gateway 网关 + 智能体管道是否对该模型正常工作（会话、历史记录、工具、沙箱策略等）。

### 第一层：直接模型补全（无 Gateway 网关）

- 测试：`src/agents/models.profiles.live.test.ts`
- 目标：
  - 枚举发现的模型
  - 使用 `getApiKeyForModel` 选择你有凭证的模型
  - 每个模型运行一个小型补全（以及需要时的针对性回归测试）
- 如何启用：
  - `pnpm test:live`（或直接调用 Vitest 时使用 `FASED_LIVE_TEST=1`）
- 设置 `FASED_LIVE_MODELS=modern`（或 `all`，modern 的别名）以实际运行此套件；否则会跳过以保持 `pnpm test:live` 专注于 Gateway 网关冒烟测试
- 如何选择模型：
  - `FASED_LIVE_MODELS=modern` 运行现代允许列表（Opus/Sonnet/Haiku 4.5、GPT-5.x + Codex、Gemini 3、GLM 4.7、MiniMax M2.7、Grok 4）
  - `FASED_LIVE_MODELS=all` 是现代允许列表的别名
  - 或 `FASED_LIVE_MODELS="openai/gpt-5.5,anthropic/claude-opus-4-6,..."`（逗号分隔的允许列表）
- 如何选择提供商：
  - `FASED_LIVE_PROVIDERS="google,google-gemini-cli"`（逗号分隔的允许列表）
- 密钥来源：
  - 默认：配置文件存储和环境变量回退
  - 设置 `FASED_LIVE_REQUIRE_PROFILE_KEYS=1` 以强制**仅使用配置文件存储**
- 为什么存在这个测试：
  - 将"提供商 API 损坏/密钥无效"与"Gateway 网关智能体管道损坏"分离
  - 包含小型、隔离的回归测试（例如：OpenAI Responses/Codex Responses 推理重放 + 工具调用流程）

### 第二层：Gateway 网关 + 开发智能体冒烟测试（"@fased"实际做的事）

- 测试：`src/gateway/gateway-models.profiles.live.test.ts`
- 目标：
  - 启动一个进程内 Gateway 网关
  - 创建/修补一个 `agent:dev:*` 会话（每次运行覆盖模型）
  - 遍历有密钥的模型并断言：
    - "有意义的"响应（无工具）
    - 真实的工具调用工作正常（读取探测）
    - 可选的额外工具探测（执行+读取探测）
    - OpenAI 回归路径（仅工具调用 → 后续）保持工作
- 探测详情（以便你能快速解释故障）：
  - `read` 探测：测试在工作区写入一个随机数文件，要求智能体 `read` 它并回显随机数。
  - `exec+read` 探测：测试要求智能体 `exec` 将随机数写入临时文件，然后 `read` 回来。
  - 图像探测：测试附加一个生成的 PNG（猫 + 随机代码），期望模型返回 `cat <CODE>`。
  - 实现参考：`src/gateway/gateway-models.profiles.live.test.ts` 和 `src/gateway/live-image-probe.ts`。
- 如何启用：
  - `pnpm test:live`（或直接调用 Vitest 时使用 `FASED_LIVE_TEST=1`）
- 如何选择模型：
  - 默认：现代允许列表（Opus/Sonnet/Haiku 4.5、GPT-5.x + Codex、Gemini 3、GLM 4.7、MiniMax M2.7、Grok 4）
  - `FASED_LIVE_GATEWAY_MODELS=all` 是现代允许列表的别名
  - 或设置 `FASED_LIVE_GATEWAY_MODELS="provider/model"`（或逗号分隔列表）来缩小范围
- 如何选择提供商（避免"OpenRouter 全部"）：
  - `FASED_LIVE_GATEWAY_PROVIDERS="google,google-gemini-cli,openai,anthropic,zai,minimax"`（逗号分隔的允许列表）
- 工具 + 图像探测在此实时测试中始终开启：
  - `read` 探测 + `exec+read` 探测（工具压力测试）
  - 当模型声明支持图像输入时运行图像探测
  - 流程（高层次）：
    - 测试生成一个带有"CAT"+ 随机代码的小型 PNG（`src/gateway/live-image-probe.ts`）
    - 通过 `agent` `attachments: [{ mimeType: "image/png", content: "<base64>" }]` 发送
    - Gateway 网关将附件解析为 `images[]`（`src/gateway/server-methods/agent.ts` + `src/gateway/chat-attachments.ts`）
    - 嵌入式智能体将多模态用户消息转发给模型
    - 断言：回复包含 `cat` + 代码（OCR 容差：允许轻微错误）

提示：要查看你的机器上可以测试什么（以及确切的 `provider/model` ID），运行：

```bash
fased models list
fased models list --json
```

## 实时测试：Anthropic 设置令牌冒烟测试

- 测试：`src/agents/anthropic.setup-token.live.test.ts`
- 目标：验证 Claude Code CLI 设置令牌（或粘贴的设置令牌配置文件）能完成 Anthropic 提示。
- 启用：
  - `pnpm test:live`（或直接调用 Vitest 时使用 `FASED_LIVE_TEST=1`）
  - `FASED_LIVE_SETUP_TOKEN=1`
- 令牌来源（选择一个）：
  - 配置文件：`FASED_LIVE_SETUP_TOKEN_PROFILE=anthropic:setup-token-test`
  - 原始令牌：`FASED_LIVE_SETUP_TOKEN_VALUE=sk-ant-oat01-...`
- 模型覆盖（可选）：
  - `FASED_LIVE_SETUP_TOKEN_MODEL=anthropic/claude-opus-4-6`

设置示例：

```bash
fased models auth paste-token --provider anthropic --profile-id anthropic:setup-token-test
FASED_LIVE_SETUP_TOKEN=1 FASED_LIVE_SETUP_TOKEN_PROFILE=anthropic:setup-token-test pnpm test:live src/agents/anthropic.setup-token.live.test.ts
```

## 实时测试：CLI 后端冒烟测试（Claude Code CLI 或其他本地 CLI）

- 测试：`src/gateway/gateway-cli-backend.live.test.ts`
- 目标：使用本地 CLI 后端验证 Gateway 网关 + 智能体管道，而不影响你的默认配置。
- 启用：
  - `pnpm test:live`（或直接调用 Vitest 时使用 `FASED_LIVE_TEST=1`）
  - `FASED_LIVE_CLI_BACKEND=1`
- 默认值：
  - 模型：`claude-cli/claude-sonnet-4-6`
  - 命令：`claude`
  - 参数：`["-p","--output-format","json","--dangerously-skip-permissions"]`
- 覆盖（可选）：
  - `FASED_LIVE_CLI_BACKEND_MODEL="claude-cli/claude-opus-4-6"`
  - `FASED_LIVE_CLI_BACKEND_MODEL="codex-cli/gpt-5.3-codex"`
  - `FASED_LIVE_CLI_BACKEND_COMMAND="/full/path/to/claude"`
  - `FASED_LIVE_CLI_BACKEND_ARGS='["-p","--output-format","json","--permission-mode","bypassPermissions"]'`
  - `FASED_LIVE_CLI_BACKEND_CLEAR_ENV='["ANTHROPIC_API_KEY","ANTHROPIC_API_KEY_OLD"]'`
  - `FASED_LIVE_CLI_BACKEND_IMAGE_PROBE=1` 发送真实图像附件（路径注入到提示中）。
  - `FASED_LIVE_CLI_BACKEND_IMAGE_ARG="--image"` 将图像文件路径作为 CLI 参数传递而非提示注入。
  - `FASED_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"`（或 `"list"`）控制设置 `IMAGE_ARG` 时如何传递图像参数。
  - `FASED_LIVE_CLI_BACKEND_RESUME_PROBE=1` 发送第二轮并验证恢复流程。
- `FASED_LIVE_CLI_BACKEND_DISABLE_MCP_CONFIG=0` 保持 Claude Code CLI MCP 配置启用（默认使用临时空文件禁用 MCP 配置）。

示例：

```bash
FASED_LIVE_CLI_BACKEND=1 \
  FASED_LIVE_CLI_BACKEND_MODEL="claude-cli/claude-sonnet-4-6" \
  pnpm test:live src/gateway/gateway-cli-backend.live.test.ts
```

### 推荐的实时测试配方

缩小范围的显式允许列表最快且最不易出错：

- 单个模型，直接测试（无 Gateway 网关）：
  - `FASED_LIVE_MODELS="openai/gpt-5.5" pnpm test:live src/agents/models.profiles.live.test.ts`

- 单个模型，Gateway 网关冒烟测试：
  - `FASED_LIVE_GATEWAY_MODELS="openai/gpt-5.5" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`

- 跨多个提供商的工具调用：
  - `FASED_LIVE_GATEWAY_MODELS="openai/gpt-5.5,anthropic/claude-opus-4-6,google/gemini-3-flash-preview,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`

- Google 专项（Gemini API 密钥 + Gemini CLI）：
  - Gemini（API 密钥）：`FASED_LIVE_GATEWAY_MODELS="google/gemini-3-flash-preview" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`
  - Gemini CLI（OAuth）：`FASED_LIVE_GATEWAY_MODELS="google-gemini-cli/gemini-3-pro-preview" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`

注意：

- `google/...` 使用 Gemini API（API 密钥）。
- `google-gemini-cli/...` 使用你机器上的本地 Gemini CLI（独立的认证 + 工具怪癖）。
- Gemini API 与 Gemini CLI：
  - API：Fased 通过 HTTP 调用 Google 托管的 Gemini API（API 密钥/配置文件认证）；这是大多数用户说的"Gemini"。
  - CLI：Fased 调用本地 `gemini` 二进制文件；它有自己的认证，行为可能不同（流式传输/工具支持/版本差异）。

## 实时测试：模型矩阵（我们覆盖什么）

没有固定的"CI 模型列表"（实时测试是可选的），但这些是建议在有密钥的开发机器上定期覆盖的**推荐**模型。

### 现代冒烟测试集（工具调用 + 图像）

这是我们期望保持工作的"常用模型"运行：

- OpenAI（非 Codex）：`openai/gpt-5.5`（可选：`openai/gpt-5.5-pro`）
- OpenAI Codex：`openai-codex/gpt-5.3-codex`（可选：`openai-codex/gpt-5.4-mini`）
- Anthropic：`anthropic/claude-opus-4-6`（或 `anthropic/claude-sonnet-4-5`）
- Google（Gemini API）：`google/gemini-3-pro-preview` 和 `google/gemini-3-flash-preview`（避免较旧的 Gemini 2.x 模型）
- Google（Gemini CLI）：`google-gemini-cli/gemini-3-pro-preview`
- Z.AI（GLM）：`zai/glm-4.7`
- MiniMax：`minimax/MiniMax-M2.7`

运行带工具 + 图像的 Gateway 网关冒烟测试：
`FASED_LIVE_GATEWAY_MODELS="openai/gpt-5.5,openai-codex/gpt-5.3-codex,anthropic/claude-opus-4-6,google/gemini-3-pro-preview,google/gemini-3-flash-preview,google-gemini-cli/gemini-3-pro-preview,zai/glm-4.7,minimax/MiniMax-M2.7" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts`

### 基线：工具调用（Read + 可选 Exec）

每个提供商系列至少选择一个：

- OpenAI：`openai/gpt-5.5`（或 `openai/gpt-5.4-mini`）
- Anthropic：`anthropic/claude-opus-4-6`（或 `anthropic/claude-sonnet-4-5`）
- Google：`google/gemini-3-flash-preview`（或 `google/gemini-3-pro-preview`）
- Z.AI（GLM）：`zai/glm-4.7`
- MiniMax：`minimax/MiniMax-M2.7`

可选的额外覆盖（锦上添花）：

- xAI：`xai/grok-4`（或最新可用版本）
- Mistral：`mistral/`…（选择一个你已启用的"工具"能力模型）
- 自定义/OpenAI-compatible 端点：如果你使用 vLLM、LiteLLM、LM Studio 或本地 Ollama-compatible server，可以包含一个已配置的端点。

### 视觉：图像发送（附件 → 多模态消息）

在 `FASED_LIVE_GATEWAY_MODELS` 中至少包含一个支持图像的模型（Claude/Gemini/OpenAI 视觉能力变体等）以测试图像探测。

### 聚合器/替代 Gateway 网关

如果你启用了密钥，我们也支持通过以下方式测试：

- OpenRouter：`openrouter/...`（数百个模型；使用 `fased models scan` 查找支持工具+图像的候选模型）
- OpenCode Zen：`opencode/...`（通过 `OPENCODE_API_KEY` / `OPENCODE_ZEN_API_KEY` 认证）

如果你有凭证/配置，可以在实时矩阵中包含更多提供商：

- 内置公开设置路径包括 `openai`、`openai-codex`、`anthropic`、`google`、`google-gemini-cli`、`zai`、`openrouter`、`opencode`、`xai`、`mistral`、`github-copilot` 和 `minimax`。
- 高级/自定义端点位于 `models.providers` 下，包括任何 OpenAI-compatible 代理，例如 LM Studio、vLLM、LiteLLM 或 Ollama-compatible server。

提示：不要试图在文档中硬编码"所有模型"。权威列表是你机器上 `discoverModels(...)` 返回的内容 + 可用的密钥。

## 凭证（绝不提交）

实时测试以与 CLI 相同的方式发现凭证。实际含义：

- 如果 CLI 能工作，实时测试应该能找到相同的密钥。
- 如果实时测试说"无凭证"，用调试 `fased models list`/模型选择相同的方式调试。

- 配置文件存储：`~/.fased/credentials/`（首选；测试中"配置文件密钥"的含义）
- 配置：`~/.fased/fased.json`（或 `FASED_CONFIG_PATH`）

如果你想依赖环境变量密钥（例如在 `~/.profile` 中导出的），在 `source ~/.profile` 后运行本地测试，或使用下面的 Docker 运行器（它们可以将 `~/.profile` 挂载到容器中）。

## Deepgram 实时测试（音频转录）

- 测试：`src/media-understanding/providers/deepgram/audio.live.test.ts`
- 启用：`DEEPGRAM_API_KEY=... DEEPGRAM_LIVE_TEST=1 pnpm test:live src/media-understanding/providers/deepgram/audio.live.test.ts`

## Docker 运行器（可选的"在 Linux 中工作"检查）

这些在仓库 Docker 镜像内运行 `pnpm test:live`，挂载你的本地配置目录和工作区（如果挂载了 `~/.profile` 则会加载它）：

- 直接模型：`pnpm test:docker:live-models`（脚本：`scripts/test-live-models-docker.sh`）
- Gateway 网关 + 开发智能体：`pnpm test:docker:live-gateway`（脚本：`scripts/test-live-gateway-models-docker.sh`）
- 新手引导向导（TTY，完整脚手架）：`pnpm test:docker:onboard`（脚本：`scripts/e2e/onboard-docker.sh`）
- Gateway 网关网络（两个容器，WS 认证 + 健康检查）：`pnpm test:docker:gateway-network`（脚本：`scripts/e2e/gateway-network-docker.sh`）
- 插件（自定义扩展加载 + 注册表冒烟测试）：`pnpm test:docker:plugins`（脚本：`scripts/e2e/plugins-docker.sh`）

有用的环境变量：

- `FASED_CONFIG_DIR=...`（默认：`~/.fased`）挂载到 `/home/node/.fased`
- `FASED_WORKSPACE_DIR=...`（默认：`~/.fased/workspace`）挂载到 `/home/node/.fased/workspace`
- `FASED_PROFILE_FILE=...`（默认：`~/.profile`）挂载到 `/home/node/.profile` 并在运行测试前加载
- `FASED_LIVE_GATEWAY_MODELS=...` / `FASED_LIVE_MODELS=...` 用于缩小运行范围
- `FASED_LIVE_REQUIRE_PROFILE_KEYS=1` 确保凭证来自配置文件存储（而非环境变量）

## 文档完整性检查

文档编辑后运行文档检查：`pnpm docs:list`。

## 离线回归测试（CI 安全）

这些是没有真实提供商的"真实管道"回归测试：

- Gateway 网关工具调用（模拟 OpenAI，真实 Gateway 网关 + 智能体循环）：`src/gateway/gateway.tool-calling.mock-openai.test.ts`
- Gateway 网关向导（WS `wizard.start`/`wizard.next`，写入配置 + 强制认证）：`src/gateway/gateway.wizard.e2e.test.ts`

## 智能体可靠性评估（Skills）

我们已经有一些 CI 安全的测试，它们的行为类似于"智能体可靠性评估"：

- 通过真实 Gateway 网关 + 智能体循环的模拟工具调用（`src/gateway/gateway.tool-calling.mock-openai.test.ts`）。
- 验证会话连接和配置效果的端到端向导流程（`src/gateway/gateway.wizard.e2e.test.ts`）。

对于 Skills 仍然缺少的内容（参见 [Skills](/tools/skills)）：

- **决策：** 当 Skills 在提示中列出时，智能体是否选择正确的 skill（或避免不相关的）？
- **合规性：** 智能体是否在使用前读取 `SKILL.md` 并遵循所需的步骤/参数？
- **工作流契约：** 断言工具顺序、会话历史延续和沙箱边界的多轮场景。

未来的评估应该首先保持确定性：

- 使用模拟提供商来断言工具调用 + 顺序、skill 文件读取和会话连接的场景运行器。
- 一小套专注于 skill 的场景（使用 vs 避免、门控、提示注入）。
- 可选的实时评估（可选的，环境变量门控），仅在 CI 安全套件就位后。

## 添加回归测试（指导）

当你修复在实时测试中发现的提供商/模型问题时：

- 如果可能，添加 CI 安全的回归测试（模拟/存根提供商，或捕获确切的请求形状转换）
- 如果它本质上是仅限实时的（速率限制、认证策略），保持实时测试范围小且通过环境变量可选
- 优先针对能捕获问题的最小层：
  - 提供商请求转换/重放问题 → 直接模型测试
  - Gateway 网关会话/历史/工具管道问题 → Gateway 网关实时冒烟测试或 CI 安全的 Gateway 网关模拟测试
