From 9dad1c9ec06cbbdb048cd725a6b91c5efff4a1ce Mon Sep 17 00:00:00 2001 From: hy Date: Wed, 19 Aug 2026 15:15:32 +0800 Subject: [PATCH] fix(test): always run vector warmup for package E2E when running multiple cases The only warmup case lives under the settings domain, so filtering with --domain/--suite/--case excluded it and left every selected case to index the workspace fixture from scratch. Package E2E now appends the warmup case whenever more than one case is selected, and the warmup task bypasses --testNamePattern so targeted --case runs still seed the shared cache. --- doc/release.md | 2 +- doc/test.md | 1 + scripts/test/workflow.mjs | 17 ++++++++++++++++- .../release/app-update-publish-config.test.ts | 3 +++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/doc/release.md b/doc/release.md index 098ae6bc..5c677d26 100644 --- a/doc/release.md +++ b/doc/release.md @@ -96,7 +96,7 @@ macOS arm64 候选包必须通过选定的回归范围。macOS x64 仍正常构 pnpm release:mac -- --tag mac-vX.Y.Z --test-only --include-x64-e2e ``` -所有发布阶段最多运行 60 分钟;测试 runner 在 55 分钟停止领取新用例并保存部分结果。正式并发开始前,每个实际参加 E2E 的候选包先串行通过唯一的 `warmup` 向量索引用例,让模型和磁盘缓存完成冷启动;warm-up 产生的 split/vector 缓存会作为种子复制到后续 case 的隔离缓存目录,warm-up 失败时不会启动后续并发。随后 E2E 总并发和 live 并发上限均为 3,原生对话框、鼠标和桌面焦点用例独占执行。显式启用 macOS x64 E2E 时,x64 仍固定为单并发。 +所有发布阶段最多运行 60 分钟;测试 runner 在 55 分钟停止领取新用例并保存部分结果。正式并发开始前,每个实际参加 E2E 的候选包先串行通过唯一的 `warmup` 向量索引用例,让模型和磁盘缓存完成冷启动;warm-up 产生的 split/vector 缓存会作为种子复制到后续 case 的隔离缓存目录,warm-up 失败时不会启动后续并发。使用 `--domain`/`--suite`/`--case` 收窄回归范围时,只要本次执行的 case 数超过 1,runner 也会自动纳入全仓唯一的 `warmup` 用例并先预热,不会因过滤漏掉它。随后 E2E 总并发和 live 并发上限均为 3,原生对话框、鼠标和桌面焦点用例独占执行。显式启用 macOS x64 E2E 时,x64 仍固定为单并发。 选中的正式包 E2E 全部执行,其中使用真实 AI 或真实服务的 E2E 也不排除。源码 E2E、backend、unit 和独立的 `test:ai*` 测试集只用于开发验证或问题排查,不替代正式包 E2E,也不属于标准发布门。 diff --git a/doc/test.md b/doc/test.md index 7c627653..7a18cba5 100644 --- a/doc/test.md +++ b/doc/test.md @@ -189,6 +189,7 @@ runner 支持的过滤参数: 补充规则: - runner 强制执行固定 domain/type 边界。backend 普通测试并发为 6;Source E2E 的所有 case 直接共享按构建指纹保存的 split/vector 内容缓存,各 case 只隔离统计文件,`warmup` 用例按普通并发用例执行。正式包 E2E 才先串行执行全仓唯一的 `warmup` 用例,并把缓存种子复制到后续 case 的隔离缓存目录。随后开放总并发 3、live 并发 2,`exclusive` 用例串行独占;普通失败继续收集剩余 case,正式包 warm-up 失败则不启动后续并发。 +- 正式包 E2E 即使通过 `--domain`/`--suite`/`--case` 过滤范围,只要本次实际执行的 case 数超过 1,runner 也会自动把全仓唯一的 `warmup` 用例纳入执行并先串行预热,避免过滤后漏掉 warmup 导致全部 case 冷启动重复索引;`--case` 过滤时 `warmup` 用例不受 `--testNamePattern` 影响。 - 真实模型 backend live 用例失败后最多重试 1 次,避免模型异常时重复等待过久。 - E2E 默认执行类型为 `normal`;真实 AI/服务调用声明 `execution: 'live'`,原生对话框、鼠标和桌面焦点用例声明 `execution: 'exclusive'`,唯一的向量冷启动用例声明 `execution: 'warmup'`。 - `source` 是日常目标,直接复用内容缓存,不额外预热;`package` 只接受既有 release bundle,安装后通过 warm-up 验证冷启动并运行同一批 E2E,不负责构建。 diff --git a/scripts/test/workflow.mjs b/scripts/test/workflow.mjs index e62f9129..92e1ed24 100644 --- a/scripts/test/workflow.mjs +++ b/scripts/test/workflow.mjs @@ -39,6 +39,13 @@ const CROSS_ARCH_WARMUP_SOURCE_TARGET = new Map([['macos-x64', 'macos-arm64']]) const USE_WINDOWS_SHELL = process.platform === 'win32' const activeAsyncChildren = new Set() let stoppingActiveChildren = false +const VECTOR_WARMUP_TEST_FILE = path.join( + TEST_CASES_ROOT, + 'settings', + 'workspace', + 'files', + 'workspace-prepare-refresh.e2e.test.ts' +) const KNOWLEDGE_CACHE_ROOT = path.join(TESTS_ROOT, '.cache', 'workspace-knowledge') const EMPTY_KNOWLEDGE_CACHE_STATS = { splitCacheHits: 0, @@ -636,6 +643,14 @@ const formatScope = (input) => .join(' ') const runE2ETestFilesConcurrently = async (testFiles, targets, testNamePattern, deadlineAt) => { + const warmupTargets = targets.filter((target) => target.cacheMode === 'warmup') + if ( + warmupTargets.length > 0 && + !testFiles.includes(VECTOR_WARMUP_TEST_FILE) && + testFiles.length > 1 + ) { + testFiles = [...testFiles, VECTOR_WARMUP_TEST_FILE] + } const fileTasks = await Promise.all( testFiles.map(async (testFile) => ({ testFile, @@ -708,7 +723,7 @@ const runE2ETestFilesConcurrently = async (testFiles, targets, testNamePattern, configPath: 'vitest.e2e.config.mts', testFiles: [task.testFile], env: caseEnv, - testNamePattern, + testNamePattern: task.execution === 'warmup' ? '' : testNamePattern, workers: 1, deadlineAt }) diff --git a/tests/case/unit/release/app-update-publish-config.test.ts b/tests/case/unit/release/app-update-publish-config.test.ts index 9a7898f3..1c9b7aad 100644 --- a/tests/case/unit/release/app-update-publish-config.test.ts +++ b/tests/case/unit/release/app-update-publish-config.test.ts @@ -115,6 +115,9 @@ describe('app update publish config', () => { expect(testWorkflow).toContain("cacheMode: 'direct'") expect(testWorkflow).toContain("cacheMode: 'warmup'") expect(testWorkflow).toContain("task.cacheMode === 'warmup' && task.execution === 'warmup'") + expect(testWorkflow).toContain('VECTOR_WARMUP_TEST_FILE') + expect(testWorkflow).toContain("testFiles = [...testFiles, VECTOR_WARMUP_TEST_FILE]") + expect(testWorkflow).toContain("task.execution === 'warmup' ? '' : testNamePattern") expect(testWorkflow).toContain('buildDirectKnowledgeCacheEnv') expect(testWorkflow).toContain('NCURATOR_WORKSPACE_KNOWLEDGE_CACHE_STATS_PATH') expect(testWorkflow).toContain('vector warm-up failed; parallel E2E will not start')