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')