ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

LibreChat E2E 测试体系实战:Mock 假模型、Redis 流传输分片与 Bombadil 属性化浏览器探索

2026/9/6 16:57:23 拓冰建站 浏览量
LibreChat E2E 测试体系实战:Mock 假模型、Redis 流传输分片与 Bombadil 属性化浏览器探索 LibreChat E2E 测试体系实战Mock 假模型、Redis 流传输分片与 Bombadil 属性化浏览器探索【免费下载链接】LibreChatEnhanced ChatGPT Clone: Features Agents, MCP, Skills, DeepSeek, Anthropic, AWS, OpenAI, Responses API, Azure, Groq, o1, GPT-5, Mistral, OpenRouter, Vertex AI, Gemini, Artifacts, AI model switching, message search, Code Interpreter, langchain, DALL-E-3, OpenAPI Actions, Functions, Secure Multi-User Auth, Presets, open-source for self-hosting. Active项目地址: https://gitcode.com/GitHub_Trending/li/LibreChat本文以 LibreChat 仓库的 e2e/README.md 为核心系统讲解其 Playwright 端到端测试体系的三层能力免真实凭据的 Mock 测试画像Profile、内存/Redis 双流存储模式与 CI 分片策略、基于 Bombadil 的属性化浏览器探索测试以及用 Playwright codegen 录制并落地为可维护规格spec的完整工作流。读完本文你可以直接在本仓库运行完整的 mock e2e 套件、切换 Redis 传输验证流式保真度、复现并归档 Bombadil 发现的缺陷并掌握从浏览器录制到提交级测试的转化方法。一、Mock E2E 画像免真实 LLM 凭据的安全默认Mock e2e 画像是生成式测试最安全的默认选择它使用 e2e/config/librechat.e2e.yaml 启动 LibreChat通过LIBRECHAT_TEST_RUN_HOOK环境变量注入一个进程内假 LLM自动创建一个已认证的 e2e 用户全程不触碰任何真实 Provider 凭据。1.1 从 npm 脚本到测试服务器的启动链根目录 package.json 中定义的入口脚本为npm run e2e:mock该脚本实际展开为两步npm run e2e:prepare # 等价于 npm run frontend构建>npm run e2e:mock:redis从 package.json 可见该命令等价于cross-env E2E_STREAM_STOREredis playwright test --confige2e/playwright.config.mock.ts。2.2 环境变量如何决定存储模式e2e/setup/env.ts 中的getStreamStoreEnv()是模式分发的核心支持三种取值E2E_STREAM_STORE行为memory默认USE_REDISfalse、USE_REDIS_STREAMSfalse、E2E_REQUIRE_REDIS_STREAMSfalse显式禁用 RedisredisUSE_REDIStrue、USE_REDIS_STREAMStrue、E2E_REQUIRE_REDIS_STREAMStrueREDIS_URI默认redis://127.0.0.1:6379/15数据库 15REDIS_KEY_PREFIX默认取自E2E_REDIS_KEY_PREFIX缺省为LibreChatE2Eredis-cluster同上但USE_REDIS_CLUSTERtrueREDIS_URI默认为 7001/7002/7003 三节点E2E_REQUIRE_REDIS_STREAMStrue就是文档所说的fail closed机制e2e/setup/start-server.js 启动时会 ping Redis超时 10 秒并验证生成 job 管理器没有静默回退到内存否则测试直接失败而不是带病运行。2.3 CI 分片与 Redis 传输专项套件Pull Request CI 的策略是完整 mock 套件跑内存模式、分 3 片外加一条聚焦的 Redis 传输套件npx playwright test --confige2e/playwright.config.mock.ts --shard1/3 npm run e2e:mock:redis:transport分片安全性的依据来自 playwright.config.mock.tsworkers: 1保证每个 shard 只有一个 worker从而不与同一 shard 内的其他测试争抢同一个认证用户和数据库CI 下retries: 2且forbidOnly生效。e2e:mock:redis:transport使用派生配置 e2e/playwright.config.redis.ts它展开 mock 配置后只保留 10 个跨越流存储边界的场景与 README 所列覆盖范围一一对应testMatch: [ /completion\.spec\.ts/, // 完成 /deferred-tools-hitl\.spec\.ts/, // HITL 审批 /model-spec-icons\.spec\.ts/, // 模型图标 /steering\.spec\.ts/, // steering运行中转向 /steering-escalation\.spec\.ts/, // steering 升级 /streaming\.spec\.ts/, // 流式保真 /subagent-activity\.spec\.ts/, /thread-fold\.spec\.ts/, // 线程折叠 /tool-approvals\.spec\.ts/, // 工具审批 /usage\.spec\.ts/, // 用量 ]Redis 泳道还放宽了断言预算expect.timeout从 10 秒提到 20 秒、CI 重试 3 次——因为每个流事件都要走真实 Redis 往返暂停/恢复与重新水合整 job 重放路径最接近超时预算。夜间调度和手动 workflow 则会在两种流模式下各跑完整套件、每种模式 2 片。三、Bombadil 属性化浏览器测试让随机探索替你找 bugBombadil 是 e2e/bombadil/ 目录实现的属性化property-based浏览器测试框架它对核心聊天回路、消息分支、并行多会话响应、模型切换、页面重载和侧边栏会话生命周期操作进行随机序列探索而不是沿着固定脚本点击。3.1 基础探索命令npm run e2e:bombadil底层由 e2e/playwright.config.bombadil.tstestDir: bombadil、testMatch: harness.spec.ts驱动 e2e/bombadil/harness.spec.ts该 harness 会把 e2e/bombadil/specification.ts 复制为运行时副本并把登录占位符__BOMBADIL_E2E_USER_EMAIL__/__BOMBADIL_E2E_USER_PASSWORD__替换为实际 e2e 用户凭据spawnnode_modules/.bin/bombadil二进制执行browser test --headless --output-path e2e/.generated/bombadil-output --instrument-javascript inline --exit-on-violation --time-limit 90s对新运行前若e2e/.generated/bombadil-output已存在先归档到e2e/.generated/bombadil-history/带时间戳。调长探索时间设置BOMBADIL_TIME_LIMITharness 支持90s、5m、2h这类数字 s/m/h/d格式本地或定时任务可放心用更长的值。3.2 失败复现与归档闭环失败会留下可复现 traceBOMBADIL_REPRODUCEe2e/.generated/bombadil-output npm run e2e:bombadil:run复现时 harness 会向 bombadil 传入--reproduce path而不是--time-limit并把 Playwright 超时放宽到 30 分钟。按设计复现出一个真实违反invariant violation时测试应当失败但如果流式时序变化导致行为发散复现结果可能偏离Bombadil 会明确报告这一点。3.3 CI 集成非阻塞探索 工件CI 在Bombadil Property Explorationworkflow 中做 5 分钟宽泛探索非阻塞。属性失败时下载bombadil-reproduction-*工件到e2e/.generated/bombadil-output/本地执行上面的复现命令配套的bombadil-diagnostics-*工件包含 CI 日志、Playwright HTML 报告与测试结果Bombadil 失败只产生 workflow 警告不阻塞合并。3.4 JavaScript 插桩范围默认只对inlineJS 做插桩因为对 LibreChat 完整 Vite bundle 插桩会在有状态长运行中超过 Bombadil 的 driver 超时harness.spec.ts 中的注释明确说明了这一点。需要做更短周期的覆盖率引导实验时可以设置BOMBADIL_INSTRUMENT_JAVASCRIPTfiles,inline npm run e2e:bombadil3.5 五个可独立运行的生命周期属性分支重载、fork 提交、模型/会话、HITL 暂停/恢复、运行中 steering 的生命周期属性可以单独跑npm run e2e:bombadil:branch-reload npm run e2e:bombadil:fork-lifecycle npm run e2e:bombadil:model-lifecycle npm run e2e:bombadil:hitl npm run e2e:bombadil:steeringpackage.json 中每条命令都通过BOMBADIL_SPECIFICATION指定对应的 specification 文件如hitl-lifecycle.specification.ts并内置时间上限30s/30s/30s/45s/75s 分别对应 branch-reload/fork/model/hitl/steering。这些聚焦命令是诊断性属性复现出产品不变量违反时以非零码退出。对应的 trace 输出目录按 specification 区分如e2e/.generated/bombadil-output-hitl复现命令也要匹配目录与:run脚本BOMBADIL_REPRODUCEe2e/.generated/bombadil-output-hitl npm run e2e:bombadil:hitl:run各属性的语义摘自 e2e/README.mdHITL驱动一次真实的ask_user_question检查点走 answer/resume 控制器——问题暂停时重载页面、只回答一次、再重载已完成会话Steering在一次慢速 MCP 支撑的运行中提交 in-flight steering断言它恰好从 composer 锚点移动到响应中的工具边界一次并重载已应用状态Model lifecycle作为应通过的对照passing controlBranch reload 与 fork保留其最小失败 trace 作为回归锚点。由于 harness 使用的是免凭据 mock-LLM 画像探索过程永远不会发出计费的 Provider 请求。四、录制测试把探索性浏览器会话变成草稿 spec4.1 一键录制Mock 画像npm run e2e:record对照 e2e/setup/record.js 的源码这条命令的实际行为是npm run e2e:prepare构建应用若E2E_BASE_URLnpm 脚本固定为http://localhost:3333避免与 3080 上的常规开发服务器冲突未就绪spawn e2e/setup/start-server.js 启动带进程内假 LLM 的测试服务器writeStorageState()驱动 headless Chromium 完成注册失败则回退登录把认证态写入e2e/storageState.json以--targetplaywright-test --test-id-attributedata-testid --load-storage e2e/storageState.json打开 Playwright codegen起始页/c/new。原始录制写入e2e/recordings/该目录被 git 忽略。4.2 本地真实配置画像要对真实的本地 LibreChat 配置而非 mock 画像录制npm run e2e:record:local4.3 record.js 的完整参数node e2e/setup/record.js --urlhttp://localhost:3080/c/new node e2e/setup/record.js --profilelocal --no-output node e2e/setup/record.js --auth-only node e2e/setup/record.js --outpute2e/recordings/settings-draft.spec.ts结合源码中的parseArgs()与printHelp()完整参数语义为参数默认值说明--profile mock\|localmockmock 画像会生成运行时配置、清洗凭据并注入假模型钩子local 直接使用本地环境--url urlbaseURL/c/newcodegen 打开的起始 URL--output pathe2e/recordings/recording-时间戳.spec.ts原始录制输出路径--storage pathe2e/storageState.json认证存储态路径--no-output—只在 codegen 面板展示生成代码不落盘--auth-only—启动服务器、写入存储态后直接退出不打开 codegen五、LLM 辅助循环从录制草稿到可提交的测试仓库给让 LLM 用 Computer Use 操作 headed Playwright 浏览器来录制的完整工作流定了 7 步标准启动npm run e2e:record让 LLM 用 Computer Use 操作该 headed 浏览器捕获完工作流后停止 codegen把e2e/recordings/中有价值的部分搬进e2e/specs/mock/下的已提交 spec用 role、label、文本或data-testid定位器替换脆弱的生成选择器codegen 本身就以--test-id-attributedata-testid启动优先产出 testid 定位器添加证明行为成立的断言而不仅是断言被点击的路径用npm run e2e:mock -- spec name运行完成的 spec 验证。关键原则生成的录制是草稿不是最终测试。提交版本应尽可能复用 e2e/specs/mock/helpers.ts 中的共享辅助函数等待网络或可见 UI 状态而不是固定 sleep并保持测试数据确定性——这与 mock 画像每个 spec 使用全新注册用户 单 worker的隔离设计是一致的确定性数据配合e2e/recordings/之外的受控输入fake-model 的标记协议才能被 CI 稳定复现。六、关键文件地图与延伸阅读关注点文件本文主体文档e2e/README.mdMock 画像主配置e2e/playwright.config.mock.tsRedis 传输专项配置e2e/playwright.config.redis.ts零凭据配置模板e2e/config/librechat.e2e.yaml流存储环境变量分发e2e/setup/env.ts进程内假 LLM标记协议e2e/setup/fake-model.js测试服务器启动fail-closed Redis 检查e2e/setup/start-server.js录制脚本e2e/setup/record.jsBombadil harnesse2e/bombadil/harness.spec.tsMock spec 目录约 60 个场景e2e/specs/mock/npm 脚本入口package.json适用前提与限制小结本地运行需先构建前端e2e:prepareMongoDB 默认连mongodb://127.0.0.1:27017/LibreChat-e2e可用MONGO_URI覆盖或依赖E2E_USE_MEMORY_MONGO自动内存模式Redis 泳道要求 6379 端口有可用 Redis模型 fixture 录制模式E2E_MODEL_FIXTURESrecord是唯一会接触真实 Provider 的路径且被 playwright.config.mock.ts 中的多重防护严格限制在指定 spec 与命名白名单内普通开发者日常只需面对零凭据的 mock 泳道即可。【免费下载链接】LibreChatEnhanced ChatGPT Clone: Features Agents, MCP, Skills, DeepSeek, Anthropic, AWS, OpenAI, Responses API, Azure, Groq, o1, GPT-5, Mistral, OpenRouter, Vertex AI, Gemini, Artifacts, AI model switching, message search, Code Interpreter, langchain, DALL-E-3, OpenAPI Actions, Functions, Secure Multi-User Auth, Presets, open-source for self-hosting. Active项目地址: https://gitcode.com/GitHub_Trending/li/LibreChat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考