资讯动态

Positron Agent Sessions 端到端测试:用 `02-chat-with-changes.scenario.md` 验证聊天消息在 Changes 视图产生真实文件差异

发布时间:2026/10/17 2:57:06 来源:尧图企业网站定制
开发工具代码编辑器数据科学【免费下载链接】positronPositron, a next-generation data science IDE项目地址https://gitcode.com/gh_mirrors/po/positron点击查看免费下载导读本文围绕 Positron 仓库中 Agent Sessions智能体会话窗口的 E2E 测试场景02-chat-with-changes.scenario.md展开深入讲解聊天消息如何在 Changes 视图产生真实文件 diff这一测试链路从自然语言场景编写、playwright-cli命令编译到 mock Agent 发出textEdit进度、真实ChatEditingService计算前后差异并驱动 diff 编辑器打开。读完本文你将掌握该 E2E 框架的编译-回放compile-and-replay架构、语义断言写法以及如何为聊天编辑类功能编写可复现、确定性的 UI 测试。场景文件定位与整体测试架构场景文件在仓库中的位置本场景是 Agent Sessions E2E 测试的第 2 个用例完整目录结构如下见 e2e 测试 READMEsrc/vs/sessions/test/e2e/ ├── common.cjs # 共享工具服务、playwright-cli、快照、场景解析 ├── generate.cjs # 编译 .scenario.md → .commands.json依赖 Copilot CLI ├── test.cjs # 确定性回放 .commands.json不依赖 LLM ├── package.json # npm scripts: generate / test / serve ├── extensions/ │ └── sessions-e2e-mock/ # Mock 扩展GitHub 认证 PR/Code Review 命令桩 └── scenarios/ ├── 01-chat-response.scenario.md ├── 02-chat-with-changes.scenario.md ← 本文核心 └── generated/ ├── 01-chat-response.commands.json └── 02-chat-with-changes.commands.json ← 编译产物提交到 git编译-回放compile-and-replay双阶段架构该框架采用编译-回放架构README 原文为 compile-and-replayPhase 1 生成npm run generate对每个.scenario.md启动 Sessions Web 服务器用playwright-cli打开页面并抓取可访问性树快照然后把自然语言步骤 快照发送给Copilot CLI由它输出精确的playwright-cli命令如click e43、type hello执行命令推进 UI 状态后把编译结果写入scenarios/generated/*.commands.json。此阶段慢且需要 LLM但只跑一次。Phase 2 回放npm test读取已提交的.commands.json逐条机械回放命令。无 LLM 调用、无正则匹配、无图标剥离只做顺序命令与断言因此快速且确定性见 generate.cjs 与 test.cjs。什么时候需要重新生成npm run generate新增.scenario.md、UI 变化导致引用ref过期、或修改了既有场景步骤时。场景原文七步验证聊天产生真实文件差异本场景的原始文件内容非常精炼核心是验证Chat 消息 → Changes 视图真实文件 diff的完整闭环02-chat-with-changes.scenario.md# Scenario: Chat message produces real file diffs in the changes view ## Steps 1. Type build the project in the chat input 2. Press Enter to submit 3. Verify there is a response in the chat 4. Verify the changes view shows modified files 5. Click on index.ts in the changes list 6. Verify a diff editor opens with the modified content 7. Press Escape to close the diff editor这 7 步覆盖了从用户输入到diff 编辑器打开与关闭的完整用户旅程输入触发编辑的指令 → 提交 → 等待 Agent 文本回复 → 检查 Changes 视图出现修改文件 → 点击文件 → 确认 diff 编辑器展示修改内容 → 关闭编辑器。每一步都刻意保持原子化一个动作一步便于失败时定位问题。编译产物.commands.json如何固化这 7 步场景被编译为确定性的命令文件 02-chat-with-changes.commands.json。对照原文每一步被翻译为具体的playwright-cli语义命令与断言注释场景步骤编译后的命令/断言说明1. Type build the projectclick textbox Chat inputtype build the project语义选择器角色 标签2. Press Enterclick textbox Chat inputpress Enter先聚焦再提交3. 验证有回复# ASSERT_VISIBLE: Ill help you build the project. Here are the changes:断言 mock Agent 的固定回复文本4. 验证 Changes 视图# ASSERT_VISIBLE: index.ts/build.ts/package.json断言三个修改文件都出现在树中5. 点击 index.tsclick treeitem index.ts在 changes 树中点击文件6. 验证 diff 编辑器# ASSERT_VISIBLE: import { build } from断言修改后的内容片段7. 关闭 diff 编辑器press Escape返回初始状态注意第 4 步的断言方式只断言文件名而不是硬编码行数如23。README 特别强调真实 diff 引擎计算的linesAdded/linesRemoved会随 mock 文件内容演化而变化因此应断言文件名与内容片段而非具体行数见 README 的 Testing File Diffs 一节。断言注释的三种语义回放器 test.cjs 支持三类注释式断言均通过轮询可访问性树快照实现10 秒超时、500ms 间隔# ASSERT_VISIBLE: text— 快照中必须包含该文本# ASSERT_DISABLED: label— 指定按钮必须带[disabled]# ASSERT_ENABLED: label— 指定按钮必须不带[disabled]语义命令如click treeitem index.ts不会直接执行而是先在实时快照里按角色 标签解析成 ref 命令如click e170再执行这样即使元素 ref 因页面变化而漂移也能稳定命中目标。Mock 最小化原则只有外部后端被替换这套测试跑的是真实的 Sessions workbench只有依赖外部后端的最小服务集被 mock详见 README 的 Mocking Architecture服务Mock 方式原因IChatEntitlementService返回ChatEntitlement.FreeCI 无真实 Copilot 账号IDefaultAccountService返回假登录账号隐藏 Sign In 按钮IGitService立即 resolveWeb 测试中无真实 git 扩展Chat agentscopilotcli等关键字匹配的 canned 响应 textEdit进度无真实 LLM 后端mock-fs://文件系统InMemoryFileSystemProvider直接注册到 workbench必须在任何服务解析工作区文件前可用GitHub 认证始终登录的 mock provider扩展无真实 OAuth 流程PR 命令Create/Open/Mergeno-op 处理器扩展无真实 GitHub API而一切下游链路全部走真实实现ChatEditingService处理 mock Agent 的textEdit进度创建带真实前后差异的IModifiedFileEntry并从内容变化计算真实的linesAdded/linesRemovedChatModel通过acceptResponseProgress()路由 Agent 进度ChangesViewPane从IChatEditingService的 observable 读取文件修改状态并渲染带真实 diff 统计的树Diff 编辑器点击 changes 列表中的文件时打开真实 diff 视图Context keyshasUndecidedChatEditingResourceContextKey、hasAppliedChatEditsContextKey由真实ModifiedFileEntryState观察设置Create PR、Accept、Reject 等菜单动作依据真实 context key 状态出现完整数据流User types message → Chat Widget → ChatService → Mock Agent invoke() → progress([{ kind: textEdit, uri, edits }]) → ChatModel.acceptResponseProgress() → ChatEditingService observes textEditGroup parts → Creates IModifiedFileEntry per file → Reads original content from mock-fs:// FileSystemProvider → Computes real diff (linesAdded, linesRemoved) → ChangesViewPane renders via observable chain → Click file → Opens real diff editormock Agent 是唯一注入 canned 数据的地方其下游全部使用真实服务实现——这正是本场景能验证真实文件差异的根本原因。场景背后的 Mock 实现web.test.ts与 mock 扩展关键字驱动的 canned 响应与文件编辑场景第 1 步输入的build the project会命中 web.test.ts 中getMockResponseWithEdits()的/build|compile|create/i分支返回固定回复文本与 3 个文件编辑/mock-repo/src/index.ts已有文件新内容加入import { build } from ./build;及build()调用——产生修改 diff/mock-repo/src/build.ts新文件全新的构建脚本——产生文件创建条目/mock-repo/package.json已有文件加入scripts.build——产生修改 diff这正是编译产物中第 3、4 步断言文本与文件名的来源回复文本Ill help you build the project. Here are the changes:与三个文件index.ts、build.ts、package.json一一对应。此外该函数还支持fix|bug修改utils.ts增加输入校验与explain|describe纯文本回复等关键字。文件编辑策略真实 diff 的触发机制emitFileEdits()通过真实ChatModel管线发出textEdit进度关键在于 range 的选择web.test.ts已有文件路径命中EXISTING_MOCK_FILES即/mock-repo/src/index.ts、/mock-repo/src/utils.ts、/mock-repo/package.json、/mock-repo/README.md使用整文件替换 rangeline 1 → line 99999让ChatEditingService对比旧内容与新内容算出真实 diff新文件如build.ts使用开头插入 range1:1 → 1:1在 changes 视图产生file created条目。mock-fs:// 为何必须注册在 workbench 层registerMockFileSystemProvider()把mock-fs的InMemoryFileSystemProvider直接注册到IFileService并预置 4 个 mock 文件MOCK_FS_FILES。这很关键多个 workbench 服务SnippetsService、AgenticPromptFilesLocator、MCP 等会在扩展宿主激活之前尝试解析工作区文件。如果只在扩展中通过vscode.workspace.registerFileSystemProvider()注册这些服务会碰到ENOPRO: No file system provider并静默失败。因此 workbench 层注册才是事实来源source of truth扩展层虽然也注册扩展宿主操作需要但不能作为唯一入口mock 扩展 注释明确不要在扩展中注册否则会重复 provider 报错。Mock 工作区文件夹工作区文件夹 URI 为mock-fs://mock-repo/mock-repo路径刻意用/mock-repo而非根/这样basename(folderUri)返回mock-repo文件夹选择器就能显示该名称。所有 mock 文件存放在此路径下的内存文件存储中。测试入口 TestSessionsBrowserMain 还会预置sessions.recentlyPickedWorkspaces让resolveWorkspace()能水合出文件夹选择。Mock Agent 与会话提供者MockChatAgentContribution注册为sessions.test.mockChatAgentWorkbenchPhase.BlockStartup完成三件事registerMockAgents()注册copilotcli默认与copilot-cloud-agent两个动态 Agentinvoke()时取关键字响应、流式输出 markdown、通过emitFileEdits()发出文本编辑并调用addSessionItem()记录会话历史与文件变更元数据insertions/deletionsregisterMockSessionProvider()为两个 scheme 注册内容提供者重开会话时可回放历史与 item controller让会话出现在侧边栏列表仅copilotcli返回真实 itemregisterMockTerminalBackend()提供空实现的后端避免终端服务报错。Mock 扩展与 PR 按钮流sessions-e2e-mock 扩展 提供假 GitHub 认证githubprovider恒返回 mock session以及一组 PR/Code Review 命令桩Create PR、Open PR、Merge、Apply Changes 等全部只打印日志并showInformationMessage。PR 按钮通过 mock 扩展package.json的菜单贡献由chatSessionType copilotcli门控——该 context key 源自会话 URI schemegetChatSessionType()mock 会话返回copilotcli。从源码看真实差异背后的服务实现场景验证的 diff 能力由真实的聊天编辑服务支撑。在 chatEditingService.ts 中IModifiedFileEntry接口定义了state: IObservableModifiedFileEntryState— 条目状态待决定/已接受等changesCount: IObservablenumber— 该文件的变更数diffInfo?: IObservableIDocumentDiff— 差异信息linesAdded?: IObservablenumber/linesRemoved?: IObservablenumber— 真实计算出的增删行数accept()/reject()— 接受/拒绝修改相关的 context key 也在该文件定义chatEditingWidgetFileStateContextKey、chatEditingResourceContextKey、inChatEditingSessionContextKey、hasUndecidedChatEditingResourceContextKey、hasAppliedChatEditsContextKey、applyingChatEditsFailedContextKeychatEditingService.ts。这些 context key 在 chatWidget.ts 中通过bindContextKey绑定在 chatEditingActions.ts 中作为菜单/命令的when条件——例如 Accept、Reject、Create PR 按钮只有在hasUndecidedChatEditingResource为真时才可用。这正是 README 所述菜单动作基于真实 context key 状态出现的源码依据。从源码结构看IModifiedFileEntry的具体实现如 chatEditingModifiedDocumentEntry.ts、chatEditingDeletedFileEntry.ts在条目创建时读取原始文件内容、在内容变化时计算 diff——即linesAdded/linesRemoved是真实计算而非 mock 传入mock 的insertions/deletions仅用于会话列表展示。这也解释了场景断言策略不硬编码行数只断言文件名与内容片段。运行与编写同类场景环境准备与运行前置条件见 README 的 Prerequisites# 仓库根目录编译 VS Code 产物 npm install npm run compile # 安装 e2e 测试依赖 cd src/vs/sessions/test/e2e npm install # 仅 generate 阶段需要 copilot --version运行cd src/vs/sessions/test/e2e # 首次或 UI 变化后编译场景慢含 LLM npm run generate # 运行测试快、确定性 npm testnpm test输出形如Found 2 compiled scenario(s) Starting sessions web server on port 9542… Server ready. ▶ Scenario: Chat message produces real file diffs in the changes view ✅ step 1: Type build the project in the chat input ✅ step 2: Press Enter to submit ... Results: 6 passed, 0 failed测试运行器会在每个场景间press Escapegoto重置状态失败时自动截图到out/failure-scenario-stepN.png。npm run generate -- 02-chat-with-changes可只重编译单个场景。编写新场景的规范在scenarios/下新建NN-description.scenario.md文件名数字前缀决定执行顺序步骤用纯英文自然语言描述常用模式Click button X、Type hello in the chat input、Press Enter、Verify the repository picker dropdown is visible、Verify the Send button is disablednpm run generate编译出.commands.jsonnpm test验证两个文件一起提交.commands.json是所有人运行的确定性测试计划。小贴士使用 UI 中精确的按钮标签一步一个动作场景顺序执行标签含 Unicode PUA 图标字符时只用可读文本部分匹配选择器中永远不要包含日期时间每次运行都会变化。为场景添加新的 mock 文件编辑要新增关键字匹配的带编辑响应修改 web.test.ts 的getMockResponseWithEdits()已有文件URI 路径必须命中EXISTING_MOCK_FILESemitFileEdits()会用整文件替换 range 让ChatEditingService计算真实 diff新文件任意其他路径助手函数改用插入 range产生 file created 条目Mock 文件存储增删预置文件需同步更新extensions/sessions-e2e-mock/extension.js与web.test.ts的EXISTING_MOCK_FILES所有路径必须在/mock-repo/下如/mock-repo/src/newfile.ts。结语02-chat-with-changes.scenario.md虽只有 7 步却是 Positron Agent Sessions E2E 体系中聊天→编辑→diff链路的关键验证点它通过最小化 mock仅替换 auth、LLM、git 三类外部依赖让textEdit进度流经真实的ChatEditingService与 Changes 视图从而在 CI 中确定性、快速地断言聊天消息产生真实文件差异这一核心产品能力。理解它的编译-回放机制、语义断言与 mock 边界你就能为 Agent 会话的各类交互编写同样可靠的可复现测试。赞分享开发工具代码编辑器数据科学【免费下载链接】positronPositron, a next-generation data science IDE项目地址https://gitcode.com/gh_mirrors/po/positron点击查看免费下载相关推荐VS Code Agent Sessions E2E 场景解析验证 Chat 消息在 Changes 视图中生成真实文件 DiffVS Code Agent Sessions E2E 场景解析验证 Chat 消息在 Changes 视图中生成真实文件 Diff 本文围绕 02 chat开发工具代码编辑器Chat-LangChain聊天评估evaluate_chat_langchain.py端到端测试Chat LangChain聊天评估evaluate_chat_langchain.py端到端测试 概述 Chat LangChain是一个基于LangCha人工智能AI 应用AI AgentRAG后端前端用 chat-recovery-probe 在真实 Cloudflare 生产运行时验证 Think 持久化聊天恢复假设用 chat recovery probe 在真实 Cloudflare 生产运行时验证 Think 持久化聊天恢复假设 chat recovery probeAI AgentAgent 框架后端云原生MCP 服务实时通信上一篇vim-airline文件编码批量检测找出编码不一致文件下一篇让应用触手可及Android-Sunflower中的无障碍测试实践指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑