Java 物流接口 E2E 测试指南
测试目标
使用 Chrome DevTools Protocol (CDP) 自动化测试 LoopAgent VSCode 扩展在 Java 项目中的表现:
- 启动 VSCode 并加载 LoopAgent 扩展
- 打开项目
D:\zz\yguc\yguc-biz - 定位文件
LogisticsController.java - 提问 "请在 LogisticsController 中新增一个新增物流信息的接口"
- 捕获 模型的推理过程、工具调用、最终回答
- 生成报告 包含截图和详细记录
快速开始
方式 1:使用启动脚本(推荐)
# 在项目根目录执行
.\scripts\run-java-logistics-test.ps1
脚本会自动:
- 启动 VSCode 测试实例(CDP 端口 9333)
- 等待扩展加载
- 执行测试脚本
- 生成报告到
.artifacts/目录 - 提示是否关闭 VSCode
方式 2:手动分步执行
步骤 1:启动 VSCode(启用 CDP)
# 启动 VSCode 并启用远程调试
$VSCODE_PATH = "C:\Users\msi\AppData\Local\Programs\Microsoft VS Code\Code.exe"
$EXTENSION_PATH = "E:\zz\loopagent-vscode"
& $VSCODE_PATH `
--remote-debugging-port=9333 `
--disable-extensions `
--extensionDevelopmentPath=$EXTENSION_PATH `
--new-window
等待 10-15 秒让 VSCode 完全启动并加载扩展。
步骤 2:运行测试脚本
# 在新的 PowerShell 窗口执行
node .\scripts\run-java-logistics-e2e.mjs
测试脚本工作流程
测试脚本 run-java-logistics-e2e.mjs 执行以下步骤:
阶段 1:连接和准备
- 连接 CDP - 连接到 VSCode 的 CDP 端口(9333)
- 查找 Workbench - 定位 VSCode 主窗口的调试目标
- 打开文件夹 - 使用
vscode.openFolderAPI 打开项目 - 打开文件 - 使用
vscode.workspace.openTextDocument打开目标文件
阶段 2:对话交互
- 打开 LoopAgent - 点击活动栏中的 LoopAgent 图标
- 查找 Webview - 定位 LoopAgent 的 Webview 调试目标
- 新建会话 - 点击 "New chat" 按钮
- 提交问题 - 填充 textarea 并点击提交按钮
阶段 3:捕获和报告
- 监听推理 - 轮询 DOM,捕获:
- 推理过程(
.reasoning-content) - 工具调用(
.tool-call-entry) - 最终回答(
.assistant-answer) - 状态变化(
.status-pill)
- 推理过程(
- 截图 - 使用
Page.captureScreenshot保存 PNG - 生成报告 - 写入 Markdown 报告到
.artifacts/
输出文件
测试完成后会生成两个文件:
1. 截图 .artifacts/java-logistics-e2e.png
完整的 VSCode 窗口截图,包含:
- 编辑器中的 LogisticsController.java
- LoopAgent 侧边栏和对话界面
- 模型的最终回答
2. 报告 .artifacts/java-logistics-e2e.md
Markdown 格式的详细报告,包含:
# Java 物流接口 E2E 测试报告
## 执行摘要
- 状态: ✅ 成功完成 / ❌ 失败
- 总耗时: XX 秒
- 推理过程长度: XX 字符
- 工具调用次数: XX 次
- 最终回答长度: XX 字符
## 推理过程
(模型的 thinking 内容)
## 工具调用详情
#### 工具调用 1: Read
**输入**: { "file_path": "..." }
**输出**: (文件内容)
#### 工具调用 2: Write
...
## 最终回答
(模型生成的回答内容)
监控和调试
实时进度输出
脚本每 5 秒输出一次进度到 stderr:
[进度] 推理: 1234字 | 工具调用: 3次 | 回答: 567字 | 状态: Thinking | 耗时: 15s
JSON 结果输出
脚本最后会输出 JSON 到 stdout,供自动化工具解析:
{
"success": true,
"elapsedMs": 45000,
"reasoningLength": 1234,
"toolCallCount": 5,
"answerLength": 890,
"error": null,
"screenshotPath": "E:\\zz\\loopagent-vscode\\.artifacts\\java-logistics-e2e.png",
"transcriptPath": "E:\\zz\\loopagent-vscode\\.artifacts\\java-logistics-e2e.md"
}
超时设置
- 连接超时: 10 秒(CDP WebSocket 连接)
- 请求超时: 20 秒(单个 CDP 命令)
- 回答超时: 300 秒(5 分钟,等待模型完成回答)
可以在脚本中修改 TURN_TIMEOUT_MS 常量来调整回答超时。
常见问题
Q1: 脚本报错 "未找到 VS Code workbench 的 CDP 目标"
原因: VSCode 未完全启动或 CDP 端口未开启
解决方案:
- 确认 VSCode 启动参数包含
--remote-debugging-port=9333 - 等待更长时间(15-20 秒)再运行测试脚本
- 手动访问
http://127.0.0.1:9333/json/list检查 CDP 是否可用
Q2: 脚本报错 "未在 XXms 内找到 LoopAgent Webview 的 CDP 目标"
原因: LoopAgent 扩展未加载或 Webview 未打开
解决方案:
- 确认启动参数包含
--extensionDevelopmentPath=E:\zz\loopagent-vscode - 手动打开 LoopAgent 视图,确认扩展正常运行
- 检查 VSCode 开发者工具(Help > Toggle Developer Tools)的控制台错误
Q3: 脚本报错 "打开文件夹失败" 或 "打开文件失败"
原因: 项目路径不存在或文件路径错误
解决方案:
- 确认项目路径存在:
Test-Path "D:\zz\yguc\yguc-biz" - 确认文件路径存在:
Test-Path "D:\zz\yguc\yguc-biz\src\main\java\com\sunshine\procurement\controller\LogisticsController.java" - 修改脚本中的
PROJECT_PATH和TARGET_FILE常量
Q4: 脚本报错 "等待响应超时 300000ms"
原因: 模型响应时间过长或卡住
解决方案:
- 增加
TURN_TIMEOUT_MS到更大的值(如 600000 = 10 分钟) - 检查最后状态输出,确认模型是否在正常工作
- 手动检查 VSCode 中的 LoopAgent 界面,查看是否有错误提示
Q5: 工具调用或推理内容为空
原因: DOM 选择器不匹配或 Webview 结构变化
解决方案:
- 手动打开 LoopAgent Webview 的开发者工具
- 检查 DOM 结构,确认选择器是否正确:
.reasoning-content- 推理内容.tool-call-entry- 工具调用条目.assistant-answer- 最终回答
- 更新脚本中的选择器
自定义测试
修改测试项目和文件
编辑 scripts/run-java-logistics-e2e.mjs:
// 目标项目和文件路径
const PROJECT_PATH = "D:\\your\\project\\path";
const TARGET_FILE = "D:\\your\\project\\path\\src\\YourFile.java";
修改测试提示词
编辑 scripts/run-java-logistics-e2e.mjs:
// 测试提示词
const TEST_PROMPT = "你的自定义问题";
修改超时时间
编辑 scripts/run-java-logistics-e2e.mjs:
const TURN_TIMEOUT_MS = 600_000; // 10 分钟
技术细节
CDP 架构
Node.js 测试脚本
↓ WebSocket
VSCode CDP 服务器 (端口 9333)
↓
┌─────────────────┐
│ Workbench │ ← 主窗口(打开文件、执行命令)
│ Target │
└─────────────────┘
↓
┌─────────────────┐
│ Webview │ ← LoopAgent UI(提交问题、捕获回答)
│ Target │
└─────────────────┘
同步求值模式
CDP 的 Runtime.evaluate 在 Webview 上下文变化后会回收挂起的 Promise,因此脚本使用同步求值模式:
- 所有注入的 JavaScript 代码保持同步(不使用
awaitPromise: true) - 需要等待的地方回到 Node.js 侧使用
delay() - 通过
syncEval()辅助函数访问 Webview 的document和window
const WEBVIEW_DOCUMENT = `const webviewDocument =
document.getElementById("active-frame")?.contentDocument ?? document;
const webviewWindow = webviewDocument.defaultView;`;
function syncEval(body) {
return `(() => {
${WEBVIEW_DOCUMENT}
if (!webviewWindow) return { ok: false, reason: "webview window missing" };
${body}
})()`;
}
工具调用捕获
脚本通过轮询 DOM 结构捕获工具调用:
const toolCalls = [...(turn?.querySelectorAll(".tool-call-entry") ?? [])].map((entry) => {
return {
name: entry.querySelector(".tool-call-name")?.textContent?.trim() ?? "",
input: entry.querySelector(".tool-call-input")?.textContent?.trim() ?? "",
output: entry.querySelector(".tool-call-output")?.textContent?.trim() ?? "",
status: [...entry.classList].find((name) => name.startsWith("tool-call-"))
};
});
相关文件
- CDP 客户端: scripts/cdpClient.mjs
- 测试脚本: scripts/run-java-logistics-e2e.mjs
- 启动脚本: scripts/run-java-logistics-test.ps1
- 其他 E2E 测试: scripts/run-multi-file-edit-e2e.mjs