release: v0.92.0

This commit is contained in:
coso
2026-03-20 23:03:38 +08:00
parent 276c7eb9d5
commit 7242707293
188 changed files with 43591 additions and 13993 deletions
+68 -27
View File
@@ -1,14 +1,21 @@
# Lime 测试体系
> 基于 Anthropic AI Agent 评估指南与 Orchids Bridge 项目实践
> 面向 Lime 当前桌面端产品形态的测试入口与索引
## 概述
Lime 作为 AI API 代理和 Agent 集成平台,需要一套完整的测试体系来确保:
- API 代理的正确性和稳定性
- 凭证池管理的可靠性
- Aster Agent 集成的功能完整性
- 协议转换的准确性
Lime 当前是一个本地优先的 Tauri 桌面应用,而不是单一前端项目或单一 API 服务。
测试体系需要同时覆盖:
- 前端界面与工作台交互
- Tauri 命令边界
- Rust 服务层与业务逻辑
- 数据库、文件系统与工作区状态
- Provider、协议转换与本地 HTTP Server
- 浏览器运行时、终端、OpenClaw 等桌面能力
- Agent Runtime 与真实模型行为
- macOS / Windows 平台差异
## 测试分层
@@ -36,9 +43,10 @@ Lime 作为 AI API 代理和 Agent 集成平台,需要一套完整的测试体
```
docs/test/
├── README.md # 本文件 - 测试体系概览
├── testing-strategy-2026.md # 当前 Lime 主测试策略
├── unit-tests.md # 单元测试指南
├── integration-tests.md # 集成测试指南
├── e2e-tests.md # 端到端测试指南
├── e2e-tests.md # 浏览器续测与 E2E 总览
├── agent-evaluation.md # Agent 评估指南(核心文档)
└── test-cases/ # 测试用例模板
├── converter-tests.md # 协议转换器测试用例
@@ -48,15 +56,17 @@ docs/test/
## 文档索引
| 文档 | 说明 | 适用场景 |
|------|------|----------|
| [unit-tests.md](unit-tests.md) | 单元测试指南 | 独立模块测试 |
| [integration-tests.md](integration-tests.md) | 集成测试指南 | 模块间协作测试 |
| [e2e-tests.md](e2e-tests.md) | E2E 测试指南 | 完整用户流程测试 |
| [agent-evaluation.md](agent-evaluation.md) | Agent 评估指南 | AI Agent 行为评估 |
| [test-cases/converter-tests.md](test-cases/converter-tests.md) | 转换器测试用例 | OpenAI ↔ Claude 转换 |
| [test-cases/provider-tests.md](test-cases/provider-tests.md) | Provider 测试用例 | OAuth 和 API 调用 |
| [test-cases/agent-tests.md](test-cases/agent-tests.md) | Agent 测试用例 | Aster Agent 集成 |
| 文档 | 说明 | 适用场景 |
| ---------------------------------------------------------------- | -------------------------- | ------------------------------------- |
| [testing-strategy-2026.md](testing-strategy-2026.md) | 当前 Lime 测试体系建设建议 | 建立分层门禁、规划演进 |
| [unit-tests.md](unit-tests.md) | 单元测试指南 | 独立模块测试 |
| [integration-tests.md](integration-tests.md) | 集成测试指南 | 模块间协作测试 |
| [e2e-tests.md](e2e-tests.md) | 当前浏览器续测与 E2E 入口 | Playwright MCP / DevBridge 主路径验证 |
| [../aiprompts/playwright-e2e.md](../aiprompts/playwright-e2e.md) | 浏览器续测详细事实源 | 继续测试、复现、控制台与 Bridge 排障 |
| [agent-evaluation.md](agent-evaluation.md) | Agent 评估指南 | AI Agent 行为评估 |
| [test-cases/converter-tests.md](test-cases/converter-tests.md) | 转换器测试用例 | OpenAI ↔ Claude 转换 |
| [test-cases/provider-tests.md](test-cases/provider-tests.md) | Provider 测试用例 | OAuth 和 API 调用 |
| [test-cases/agent-tests.md](test-cases/agent-tests.md) | Agent 测试用例 | Aster Agent 集成 |
## 快速开始
@@ -72,6 +82,37 @@ cd src-tauri && cargo test
npm test
```
### 运行本地智能校验
```bash
npm run verify:local
```
### 运行本地全量校验
```bash
npm run verify:local:full
```
### 浏览器模式桥接检查
```bash
npm run bridge:health -- --timeout-ms 120000
```
### 运行首条自包含 smoke
```bash
npm run smoke:workspace-ready
```
### 当前浏览器续测入口
当前仓库的浏览器模式 E2E / 续测文档分两层:
- `docs/test/e2e-tests.md`:总览、命令矩阵、适用边界
- `docs/aiprompts/playwright-e2e.md`:详细操作流程与 Playwright MCP 续测事实源
### 运行代码检查
```bash
@@ -84,12 +125,12 @@ npm run lint
## 核心测试模块
| 模块 | 测试重点 | 文档 |
|------|----------|------|
| 协议转换 | OpenAI ↔ Claude 转换正确性 | [converter-tests.md](test-cases/converter-tests.md) |
| Provider 系统 | OAuth 刷新、API 调用 | [provider-tests.md](test-cases/provider-tests.md) |
| 凭证池 | 轮询、健康检查、负载均衡 | [integration-tests.md](integration-tests.md) |
| Aster Agent | 流式响应、工具调用 | [agent-tests.md](test-cases/agent-tests.md) |
| 模块 | 测试重点 | 文档 |
| ------------- | -------------------------- | --------------------------------------------------- |
| 协议转换 | OpenAI ↔ Claude 转换正确性 | [converter-tests.md](test-cases/converter-tests.md) |
| Provider 系统 | OAuth 刷新、API 调用 | [provider-tests.md](test-cases/provider-tests.md) |
| 凭证池 | 轮询、健康检查、负载均衡 | [integration-tests.md](integration-tests.md) |
| Aster Agent | 流式响应、工具调用 | [agent-tests.md](test-cases/agent-tests.md) |
## 测试原则
@@ -104,11 +145,11 @@ npm run lint
## 评分器类型
| 类型 | 适用场景 | 优点 | 缺点 |
|------|----------|------|------|
| **代码评分器** | 确定性验证 | 快速、可复现 | 对有效变体脆弱 |
| **模型评分器** | 语义评估 | 灵活、可扩展 | 非确定性、需校准 |
| **人工评分器** | 复杂判断 | 金标准质量 | 昂贵、慢 |
| 类型 | 适用场景 | 优点 | 缺点 |
| -------------- | ---------- | ------------ | ---------------- |
| **代码评分器** | 确定性验证 | 快速、可复现 | 对有效变体脆弱 |
| **模型评分器** | 语义评估 | 灵活、可扩展 | 非确定性、需校准 |
| **人工评分器** | 复杂判断 | 金标准质量 | 昂贵、慢 |
## 评估指标
+99 -249
View File
@@ -1,276 +1,126 @@
# Lime E2E 测试指南
# Lime 浏览器续测与 E2E 指南
> 端到端测试验证完整用户流程
> 本文只保留 Lime 当前仍有效的浏览器端 E2E 入口;详细操作与续测步骤以 `docs/aiprompts/playwright-e2e.md` 为准。
## 概述
## 1. 当前事实源
E2E 测试模拟真实用户操作,验证从前端到后端的完整流程。Lime 使用 Tauri 框架,E2E 测试需要覆盖:
### current
- 桌面应用启动和初始化
- 用户界面交互
- API 代理完整流程
- 凭证管理流程
- `docs/aiprompts/playwright-e2e.md`:浏览器续测、Playwright MCP 交互、DevBridge 排障的唯一详细事实源
- `npm run tauri:dev:headless`:当前浏览器模式启动入口
- `npm run bridge:health -- --timeout-ms 120000`:当前 DevBridge 就绪检查入口
- `npm run test:bridge`:当前浏览器桥接最小自动校验入口
- `npm run smoke:workspace-ready`:当前首条自包含 smoke,覆盖 DevBridge 就绪与默认 workspace 基础链路
## 测试框架
### supplement
### Tauri E2E 测试
- `npm run bridge:e2e`:偏排障性质的脚本,不是仓库统一 E2E 标准
- `npm run smoke:social-workbench`:现有专项 smoke,但仍依赖人工前置状态,暂不等于“自包含主链路冒烟”
使用 `tauri-driver` 进行自动化测试:
### deprecated
- `tauri-driver`:不再是当前仓库推荐的 E2E 方案
- `npm run test:e2e`:当前仓库已不存在,不应继续作为执行入口
## 2. 何时使用 E2E / 续测
以下场景优先走当前浏览器续测流程:
- 用户明确要求“继续测试”“继续复现”“继续用 Playwright MCP 验证”
- 需要复用已有页面状态或浏览器标签页
- 需要确认页面真实交互、控制台报错、DevBridge / mock fallback 行为
- 修改涉及前端页面主路径,而不是单一工具函数或纯后端逻辑
以下场景不要强行拉起整条 E2E:
- 只是模块级逻辑修改,可用单测或定向集成测试覆盖
- 只是 `safeInvoke`、mock、bridge 边界修改,且 `npm run test:bridge` 足以验证
- 只是命令注册 / 命令漂移问题,优先跑 `npm run test:contracts`
## 3. 当前标准流程
### 第 1 步:启动浏览器模式
```bash
# 安装依赖
cargo install tauri-driver
# 运行 E2E 测试
npm run test:e2e
npm run tauri:dev:headless
```
### 测试配置
用途:
```javascript
// playwright.config.ts
import { defineConfig } from "@playwright/test";
- 启动前端 dev server
- 启动 Tauri headless 环境
- 启动 DevBridge
- 让 Playwright MCP 可访问 `http://127.0.0.1:1420/`
export default defineConfig({
testDir: "./tests/e2e",
timeout: 30000,
use: {
baseURL: "tauri://localhost",
},
});
```
## 测试场景
### 1. 应用启动流程
```typescript
import { test, expect } from "@playwright/test";
test.describe("应用启动", () => {
test("应用正常启动并显示主界面", async ({ page }) => {
// 等待应用加载
await page.waitForSelector('[data-testid="main-layout"]');
// 验证核心组件存在
await expect(page.locator('[data-testid="sidebar"]')).toBeVisible();
await expect(page.locator('[data-testid="content-area"]')).toBeVisible();
});
test("首次启动显示欢迎引导", async ({ page }) => {
// 清除本地存储模拟首次启动
await page.evaluate(() => localStorage.clear());
await page.reload();
await expect(page.locator('[data-testid="welcome-modal"]')).toBeVisible();
});
});
```
### 2. 凭证管理流程
```typescript
test.describe("凭证管理", () => {
test("添加 Kiro 凭证", async ({ page }) => {
// 打开凭证管理
await page.click('[data-testid="credentials-tab"]');
await page.click('[data-testid="add-credential-btn"]');
// 选择 Provider
await page.click('[data-testid="provider-kiro"]');
// 上传凭证文件
const fileInput = page.locator('input[type="file"]');
await fileInput.setInputFiles("./tests/fixtures/test-credential.json");
// 验证凭证添加成功
await expect(page.locator('[data-testid="credential-item"]')).toBeVisible();
await expect(page.locator("text=test@example.com")).toBeVisible();
});
test("删除凭证", async ({ page }) => {
// 假设已有凭证
await page.click('[data-testid="credentials-tab"]');
// 删除凭证
await page.click('[data-testid="credential-menu"]');
await page.click('[data-testid="delete-credential"]');
await page.click('[data-testid="confirm-delete"]');
// 验证凭证已删除
await expect(
page.locator('[data-testid="credential-item"]'),
).not.toBeVisible();
});
});
```
### 3. API 代理流程
```typescript
test.describe("API 代理", () => {
test("启动代理服务器", async ({ page }) => {
await page.click('[data-testid="server-tab"]');
await page.click('[data-testid="start-server-btn"]');
// 等待服务器启动
await expect(page.locator("text=服务器运行中")).toBeVisible();
await expect(page.locator('[data-testid="server-port"]')).toContainText(
"8080",
);
});
test("代理请求成功", async ({ page, request }) => {
// 启动服务器
await page.click('[data-testid="start-server-btn"]');
await page.waitForSelector("text=服务器运行中");
// 发送测试请求
const response = await request.post(
"http://localhost:8080/v1/chat/completions",
{
headers: {
"Content-Type": "application/json",
Authorization: "Bearer test-key",
},
data: {
model: "gpt-4",
messages: [{ role: "user", content: "Hello" }],
},
},
);
expect(response.ok()).toBeTruthy();
});
});
```
### 4. Agent 对话流程
```typescript
test.describe("Agent 对话", () => {
test("发送消息并接收响应", async ({ page }) => {
await page.click('[data-testid="agent-tab"]');
// 输入消息
await page.fill('[data-testid="message-input"]', "你好,请介绍一下自己");
await page.click('[data-testid="send-btn"]');
// 等待响应
await expect(page.locator('[data-testid="assistant-message"]')).toBeVisible(
{
timeout: 30000,
},
);
});
test("流式响应正确显示", async ({ page }) => {
await page.click('[data-testid="agent-tab"]');
await page.fill('[data-testid="message-input"]', "写一首短诗");
await page.click('[data-testid="send-btn"]');
// 验证流式显示(内容逐渐增加)
const messageEl = page.locator('[data-testid="assistant-message"]');
let prevLength = 0;
for (let i = 0; i < 5; i++) {
await page.waitForTimeout(500);
const text = await messageEl.textContent();
expect(text?.length).toBeGreaterThan(prevLength);
prevLength = text?.length || 0;
}
});
});
```
## 测试数据管理
### Fixtures
```
tests/
├── fixtures/
│ ├── test-credential.json # 测试凭证
│ ├── mock-responses/ # Mock API 响应
│ │ ├── chat-completion.json
│ │ └── streaming-response.txt
│ └── test-config.json # 测试配置
└── e2e/
└── *.spec.ts
```
### Mock 服务
```typescript
// tests/mocks/api-server.ts
import { setupServer } from "msw/node";
import { rest } from "msw";
export const mockServer = setupServer(
rest.post("*/v1/chat/completions", (req, res, ctx) => {
return res(
ctx.json({
id: "test-id",
choices: [
{
message: { role: "assistant", content: "Mock response" },
},
],
}),
);
}),
);
```
## 运行 E2E 测试
### 第 2 步:等待桥接就绪
```bash
# 构建应用
npm run build
# 运行 E2E 测试
npm run test:e2e
# 运行特定测试
npm run test:e2e -- --grep "凭证管理"
# 生成测试报告
npm run test:e2e -- --reporter=html
npm run bridge:health -- --timeout-ms 120000
```
## CI/CD 集成
用途:
```yaml
# .github/workflows/e2e.yml
name: E2E Tests
- 等待 `http://127.0.0.1:3030/health` 可用
- 降低页面早于 DevBridge 就绪时的 `Failed to fetch` 噪音
on: [push, pull_request]
### 第 3 步:使用 Playwright MCP 进入页面
jobs:
e2e:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
标准入口:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "22"
- 打开 `http://127.0.0.1:1420/`
- 等待“正在加载...”消失
- 确认默认首页已出现
- 检查一次 `browser_console_messages(level=error)`
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
### 第 4 步:沿主路径做最小验证
- name: Install dependencies
run: npm ci
当前优先验证以下路径:
- name: Build app
run: npm run build
1. 首页可加载,主导航可见
2. 社媒内容工作流可进入
3. 页面交互后控制台不新增关键 error
- name: Run E2E tests
run: npm run test:e2e
```
详细点击路径、控制台检查要求、交接格式,以 `docs/aiprompts/playwright-e2e.md` 为准。
## 下一步
## 4. 当前命令矩阵
- [Agent 评估指南](agent-evaluation.md)
- [测试用例:Agent](test-cases/agent-tests.md)
| 目标 | 命令 / 入口 | 角色 | 说明 |
| ---------------------- | ---------------------------------------------- | ---------- | ----------------------------------------------- |
| 启动浏览器模式 | `npm run tauri:dev:headless` | current | 当前标准启动命令 |
| 等待 Bridge 就绪 | `npm run bridge:health -- --timeout-ms 120000` | current | 当前标准健康检查 |
| 校验桥接基础能力 | `npm run test:bridge` | current | `safeInvoke` / mock / tauri-mock 最小自动校验 |
| Workspace 自包含 smoke | `npm run smoke:workspace-ready` | current | 验证 DevBridge、默认 workspace、路径回查链路 |
| 校验跨层命令契约 | `npm run test:contracts` | current | 检查前端命令、Rust 注册、catalog、mock 集合漂移 |
| 浏览器续测细则 | `docs/aiprompts/playwright-e2e.md` | current | Playwright MCP 唯一详细事实源 |
| 专项 bridge 排障 | `npm run bridge:e2e` | supplement | 适合排障,不是统一门禁 |
| 社媒内容专项 smoke | `npm run smoke:social-workbench` | supplement | 仍非自包含,不应冒充标准 E2E |
| 旧 E2E 命令 | `npm run test:e2e` | deprecated | 当前仓库不存在 |
## 5. 当前验证标准
一次有效的浏览器续测 / E2E 至少满足以下之一:
1. 主路径走通且控制台 error 归零
2. 主路径走通,且剩余错误已明确归类为非阻塞项
3. 已定位新的 bridge / mock / 命令注册缺口,并给出下一步最小修复点
## 6. 当前不做的假设
本文不再把以下内容当成当前标准:
- 假设仓库已接入本地 Playwright 测试目录与统一 `test:e2e` 命令
- 假设 `tauri-driver` 仍是推荐路径
- 假设浏览器 E2E 已进入 CI 标准门禁
当前 PR 门禁以 `.github/workflows/pr-gate.yml` 为准;完整浏览器主链路 smoke 仍属于后续建设项,详见 `docs/test/testing-strategy-2026.md`。
## 7. 给后续 Agent 的交接要求
如果本轮没有完全收口,请至少留下:
- 当前页面 URL
- 已完成的业务步骤
- 控制台 error 数量
- 是否走到了真实 bridge 或 mock fallback
- 最新暴露的命令缺口
- 下一轮应先补 mock、bridge,还是命令注册
+89
View File
@@ -0,0 +1,89 @@
# Lime 测试体系待办(2026)
> 本文件只保留当前仍未解决的测试问题;已落地能力已从优先级清单移除。
## 1. 事实源与分类
### current
以下路径已经是当前测试体系的事实源,不再作为“待建设能力”重复列入:
- `docs/test/README.md`:当前测试入口与命令索引
- `docs/test/e2e-tests.md`:当前浏览器续测与 E2E 总览入口
- `docs/aiprompts/playwright-e2e.md`:当前浏览器续测 / Playwright MCP 事实源
- `package.json`:当前统一测试命令入口
- `scripts/local-ci.mjs`:当前本地智能校验入口
- `scripts/report-legacy-surfaces.mjs`:当前 legacy / compat 回流护栏
- `.github/workflows/pr-gate.yml`:当前 PR 自动门禁入口
### compat
- 当前无仍需保留的 E2E compat 文档
### deprecated
- `tauri-driver` 作为仓库推荐 E2E 方案的说法
- `npm run test:e2e` 作为现行测试入口的说法
### dead
- `npm run test:e2e` 作为现行仓库命令已不存在,不应继续作为测试标准引用
## 2. 已从待办移除的事项
以下能力已具备基础,不再保留在优先级清单中:
- 前端 `Vitest` 覆盖已经足够广,`src/components`、`src/hooks`、`src/lib/api`、`src/features/browser-runtime` 等已有大量测试
- Rust 单测 / 集成测试基础已经存在,`src-tauri/src` 与多个 workspace crate 都有可运行测试
- 本地统一校验入口已经存在:`test:frontend`、`test:bridge`、`test:rust`、`verify:local`、`verify:local:full`
- 桥接基础测试已经存在:`src/lib/dev-bridge/safeInvoke.test.ts`、`src/lib/tauri-mock/core.test.ts`
- legacy 治理护栏已经存在:`npm run governance:legacy-report`
- 旧权限表面治理护栏已经补齐:`src/lib/governance/legacyToolPermissionGuard.test.ts` + `npm run governance:legacy-report`
- 跨层命令契约检查基础版已经落地:`npm run test:contracts` 已进入 `scripts/local-ci.mjs` 与 `.github/workflows/pr-gate.yml`
- 命令契约延期例外已经收口:`agent_terminal_command_response`、`agent_term_scrollback_response` 已退出 `runtimeGatewayCommands`,改为 `dead-candidate` 治理监控
- 首条自包含 smoke 已落地:`npm run smoke:workspace-ready` 可自动校验 DevBridge 就绪、默认 workspace 获取、目录修复与路径回查
- 测试文档事实源已经收口:`docs/test/README.md`、`docs/test/e2e-tests.md`、`docs/aiprompts/playwright-e2e.md` 已按“索引 / 总览 / 详细事实源”分层
- PR 自动门禁已经补齐:`.github/workflows/pr-gate.yml` 已覆盖前端、bridge、Rust 三类基础检查
## 3. 当前仍未解决的问题优先级
| 优先级 | 事项 | 为什么重要 | 当前证据 | 完成定义 |
| ------ | --------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| P0 | 自包含 smoke 仍然不足 | 单测很多,但主链路仍缺少无需人工准备的自动回归 | 目前仅有 `smoke:workspace-ready` 属于自包含 smoke;`smoke:social-workbench` 仍依赖已有 session,`bridge:e2e` 更像排障脚本 | 至少补齐 3 条无需人工准备的 smoke;当前已完成 1 条,仍需补 server / terminal / browser runtime 等 2 条以上 |
| P1 | Agent eval 尚未工程化 | 价值高,但建立在前面基础门禁稳定之后 | 仓库已有理念和局部真实测试,但缺少任务集、grader、nightly 报表 | 形成固定任务集、采样归档、grader、nightly 输出与趋势指标 |
## 4. 建议执行顺序
### 第 1 步:把 smoke 升级为自包含场景
先只挑 3 条最高价值场景,不要贪多:
1. 应用启动 + workspace 可创建 / 打开
2. server 基础链路可自动打通
3. terminal 或 browser runtime 至少有一条基础链路可自动打通
验收标准是“本地和 CI 都能重复执行”,而不是“方便人工排障”。
### 第 2 步:把 Agent eval 工程化
这一步放在最后,不是因为不重要,而是它依赖前面的基础设施稳定:
- 有稳定门禁
- 有稳定契约检查
- 有可重复 smoke
完成后再上:
- 固定任务集
- transcript 存档
- grader
- nightly 报表
## 5. 当前建议
如果只看投入产出比,当前最值得先做的两刀是:
1. 把 smoke 升级为自包含场景
2. 把 Agent eval 工程化
这两步做完之后,再继续往 nightly 与趋势报表收口,收益会更高。