fix(test): serialize default e2e runner (#122203)

* fix(test): serialize default e2e runner

* docs(test): document serial e2e default
This commit is contained in:
Vincent Koc
2026-08-12 05:01:04 +08:00
committed by GitHub
parent ce466fccb0
commit aa52ebaef3
4 changed files with 52 additions and 39 deletions
+2 -2
View File
@@ -781,10 +781,10 @@ Native dependency policy:
- Files: `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts`, and bundled-plugin E2E tests under `extensions/`
- Runtime defaults:
- Uses Vitest `threads` with `isolate: false`, matching the rest of the repo.
- Uses adaptive workers (CI: up to 2, local: 1 by default).
- Uses one worker by default to keep non-isolated gateway state deterministic.
- Runs in silent mode by default to reduce console I/O overhead.
- Useful overrides:
- `OPENCLAW_E2E_WORKERS=<n>` to force worker count (capped at 16).
- `OPENCLAW_E2E_WORKERS=<n>` to opt into parallel workers (capped at 16).
- `OPENCLAW_E2E_VERBOSE=1` to re-enable verbose console output.
- Scope:
- Multi-instance gateway end-to-end behavior
+1 -1
View File
@@ -113,7 +113,7 @@ Test wrapper runs end with a short `[test] passed|failed|skipped ... in ...` sum
- Gateway tests are included in the untargeted `pnpm test` full suite; run them alone with `pnpm test:gateway`.
- `pnpm test:e2e`: repo E2E aggregate = `pnpm test:e2e:gateway && pnpm test:ui:e2e`.
- `pnpm test:e2e:gateway`: gateway end-to-end smoke tests (multi-instance WS/HTTP/node pairing). Defaults to `threads` + `isolate: false` with adaptive workers in `vitest.e2e.config.ts`; tune with `OPENCLAW_E2E_WORKERS=<n>`, verbose logs with `OPENCLAW_E2E_VERBOSE=1`.
- `pnpm test:e2e:gateway`: gateway end-to-end smoke tests (multi-instance WS/HTTP/node pairing). Defaults to `threads` + `isolate: false` with one worker in `vitest.e2e.config.ts`; opt into parallelism with `OPENCLAW_E2E_WORKERS=<n>` (capped at 16), and enable verbose logs with `OPENCLAW_E2E_VERBOSE=1`.
- `pnpm test:live`: provider live tests (Claude/Minimax/DeepSeek/z.ai/etc, gated by `*.live.test.ts`). Requires API keys and `LIVE=1` (or `OPENCLAW_LIVE_TEST=1`) to unskip; verbose output with `OPENCLAW_LIVE_TEST_QUIET=0`.
## Full Docker suite (`pnpm test:docker:all`)
+9 -1
View File
@@ -5,7 +5,7 @@ import {
normalizeConfigPaths,
} from "../../test/helpers/vitest-config-paths.js";
import { BUNDLED_PLUGIN_E2E_TEST_GLOB } from "../../test/vitest/vitest.bundled-plugin-paths.ts";
import e2eConfig from "../../test/vitest/vitest.e2e.config.ts";
import e2eConfig, { createE2EVitestConfig } from "../../test/vitest/vitest.e2e.config.ts";
describe("e2e vitest config", () => {
it("runs as a standalone config instead of inheriting unit projects", () => {
@@ -32,4 +32,12 @@ describe("e2e vitest config", () => {
"test/setup-openclaw-runtime.ts",
]);
});
it("serializes default e2e runs while preserving explicit worker overrides", () => {
expect(createE2EVitestConfig({}).test?.maxWorkers).toBe(1);
expect(createE2EVitestConfig({ OPENCLAW_E2E_WORKERS: "4" }).test?.maxWorkers).toBe(4);
expect(createE2EVitestConfig({ OPENCLAW_E2E_WORKERS: "99" }).test?.maxWorkers).toBe(16);
expect(createE2EVitestConfig({ OPENCLAW_E2E_WORKERS: "0" }).test?.maxWorkers).toBe(1);
expect(createE2EVitestConfig({ OPENCLAW_E2E_WORKERS: "invalid" }).test?.maxWorkers).toBe(1);
});
});
+40 -35
View File
@@ -1,22 +1,17 @@
// Vitest e2e config wires the e2e test shard.
import os from "node:os";
import { defineConfig } from "vitest/config";
import { BUNDLED_PLUGIN_E2E_TEST_GLOB } from "./vitest.bundled-plugin-paths.ts";
import baseConfig from "./vitest.config.ts";
import { resolveRepoRootPath } from "./vitest.shared.config.ts";
const base = baseConfig as unknown as Record<string, unknown>;
const isCI = process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true";
const cpuCount = os.cpus().length;
// Keep e2e runs cheap by default; callers can still override via OPENCLAW_E2E_WORKERS.
const defaultWorkers = isCI ? Math.min(2, Math.max(1, Math.floor(cpuCount * 0.25))) : 1;
const requestedWorkers = Number.parseInt(process.env.OPENCLAW_E2E_WORKERS ?? "", 10);
const e2eWorkers =
Number.isFinite(requestedWorkers) && requestedWorkers > 0
function resolveE2EWorkerCount(env: Record<string, string | undefined>): number {
const requestedWorkers = Number.parseInt(env.OPENCLAW_E2E_WORKERS ?? "", 10);
return Number.isFinite(requestedWorkers) && requestedWorkers > 0
? Math.min(16, requestedWorkers)
: defaultWorkers;
const verboseE2E = process.env.OPENCLAW_E2E_VERBOSE === "1";
: 1;
}
const base = baseConfig as unknown as Record<string, unknown>;
const baseTestWithProjects =
(baseConfig as { test?: { exclude?: string[]; projects?: string[]; setupFiles?: string[] } })
.test ?? {};
@@ -33,27 +28,37 @@ const exclude = [
...tuiPtyExcludes,
];
export default defineConfig({
...base,
test: {
...baseTest,
maxWorkers: e2eWorkers,
silent: !verboseE2E,
globalSetup: [resolveRepoRootPath("test/vitest/vitest.e2e.global-setup.ts")],
setupFiles: [
...new Set(
[...(baseTest.setupFiles ?? []), "test/setup-openclaw-runtime.ts"].map(resolveRepoRootPath),
),
],
include: [
"test/**/*.e2e.test.ts",
"src/**/*.e2e.test.ts",
"packages/**/*.e2e.test.ts",
"src/gateway/gateway.test.ts",
"src/gateway/server.startup-matrix-migration.integration.test.ts",
"src/gateway/sessions-history-http.test.ts",
BUNDLED_PLUGIN_E2E_TEST_GLOB,
],
exclude,
},
});
export function createE2EVitestConfig(env: Record<string, string | undefined> = process.env) {
// Keep e2e runs deterministic by default; callers can still opt into parallelism.
const e2eWorkers = resolveE2EWorkerCount(env);
const verboseE2E = env.OPENCLAW_E2E_VERBOSE === "1";
return defineConfig({
...base,
test: {
...baseTest,
maxWorkers: e2eWorkers,
silent: !verboseE2E,
globalSetup: [resolveRepoRootPath("test/vitest/vitest.e2e.global-setup.ts")],
setupFiles: [
...new Set(
[...(baseTest.setupFiles ?? []), "test/setup-openclaw-runtime.ts"].map(
resolveRepoRootPath,
),
),
],
include: [
"test/**/*.e2e.test.ts",
"src/**/*.e2e.test.ts",
"packages/**/*.e2e.test.ts",
"src/gateway/gateway.test.ts",
"src/gateway/server.startup-matrix-migration.integration.test.ts",
"src/gateway/sessions-history-http.test.ts",
BUNDLED_PLUGIN_E2E_TEST_GLOB,
],
exclude,
},
});
}
export default createE2EVitestConfig();