perf(test): split ui and bundled full-suite shards

This commit is contained in:
Peter Steinberger
2026-04-07 00:39:05 +01:00
parent 1ce9ab36df
commit 191f867ef6
10 changed files with 60 additions and 22 deletions

View File

@@ -47,7 +47,7 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
### Unit / integration (default)
- Command: `pnpm test`
- Config: five sequential shard runs (`vitest.full-*.config.ts`) over the existing scoped Vitest projects
- Config: ten sequential shard runs (`vitest.full-*.config.ts`) over the existing scoped Vitest projects
- Files: core/unit inventories under `src/**/*.test.ts`, `packages/**/*.test.ts`, `test/**/*.test.ts`, and the whitelisted `ui` node tests covered by `vitest.unit.config.ts`
- Scope:
- Pure unit tests
@@ -58,7 +58,7 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
- No real keys required
- Should be fast and stable
- Projects note:
- Untargeted `pnpm test` now runs eight smaller shard configs (`core-unit-src`, `core-unit-security`, `core-unit-support`, `core-contracts`, `core-runtime`, `agentic`, `auto-reply`, `extensions`) instead of one giant native root-project process. This cuts peak RSS on loaded machines and avoids auto-reply/extension work starving unrelated suites.
- Untargeted `pnpm test` now runs ten smaller shard configs (`core-unit-src`, `core-unit-security`, `core-unit-ui`, `core-unit-support`, `core-contracts`, `core-bundled`, `core-runtime`, `agentic`, `auto-reply`, `extensions`) instead of one giant native root-project process. This cuts peak RSS on loaded machines and avoids auto-reply/extension work starving unrelated suites.
- `pnpm test --watch` still uses the native root `vitest.config.ts` project graph, because a multi-shard watch loop is not practical.
- `pnpm test`, `pnpm test:watch`, and `pnpm test:perf:imports` route explicit file/directory targets through scoped lanes first, so `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` avoids paying the full root project startup tax.
- `pnpm test:changed` expands changed git paths into the same scoped lanes when the diff only touches routable source/test files; config/setup edits still fall back to the broad root-project rerun.

View File

@@ -13,7 +13,7 @@ title: "Tests"
- `pnpm test:coverage`: Runs the unit suite with V8 coverage (via `vitest.unit.config.ts`). Global thresholds are 70% lines/branches/functions/statements. Coverage excludes integration-heavy entrypoints (CLI wiring, gateway/telegram bridges, webchat static server) to keep the target focused on unit-testable logic.
- `pnpm test:coverage:changed`: Runs unit coverage only for files changed since `origin/main`.
- `pnpm test:changed`: expands changed git paths into scoped Vitest lanes when the diff only touches routable source/test files. Config/setup changes still fall back to the native root projects run so wiring edits rerun broadly when needed.
- `pnpm test`: routes explicit file/directory targets through scoped Vitest lanes. Untargeted runs now execute eight sequential shard configs (`vitest.full-core-unit-src.config.ts`, `vitest.full-core-unit-security.config.ts`, `vitest.full-core-unit-support.config.ts`, `vitest.full-core-contracts.config.ts`, `vitest.full-core-runtime.config.ts`, `vitest.full-agentic.config.ts`, `vitest.full-auto-reply.config.ts`, `vitest.full-extensions.config.ts`) instead of one giant root-project process.
- `pnpm test`: routes explicit file/directory targets through scoped Vitest lanes. Untargeted runs now execute ten sequential shard configs (`vitest.full-core-unit-src.config.ts`, `vitest.full-core-unit-security.config.ts`, `vitest.full-core-unit-ui.config.ts`, `vitest.full-core-unit-support.config.ts`, `vitest.full-core-contracts.config.ts`, `vitest.full-core-bundled.config.ts`, `vitest.full-core-runtime.config.ts`, `vitest.full-agentic.config.ts`, `vitest.full-auto-reply.config.ts`, `vitest.full-extensions.config.ts`) instead of one giant root-project process.
- Selected `plugin-sdk` and `commands` test files now route through dedicated light lanes that keep only `test/setup.ts`, leaving runtime-heavy cases on their existing lanes.
- Selected `plugin-sdk` and `commands` helper source files also map `pnpm test:changed` to explicit sibling tests in those light lanes, so small helper edits avoid rerunning the heavy runtime-backed suites.
- `auto-reply` now also splits into three dedicated configs (`core`, `top-level`, `reply`) so the reply harness does not dominate the lighter top-level status/token/helper tests.

View File

@@ -1,5 +1,3 @@
import { isRecord } from "../../../utils.js";
type JsonRecord = Record<string, unknown>;
import { isRecord } from "../../../utils.js";

View File

@@ -175,6 +175,12 @@ describe("scripts/test-projects full-suite sharding", () => {
includePatterns: null,
watchMode: false,
},
{
config: "vitest.full-core-unit-ui.config.ts",
forwardedArgs: [],
includePatterns: null,
watchMode: false,
},
{
config: "vitest.full-core-unit-support.config.ts",
forwardedArgs: [],
@@ -187,6 +193,12 @@ describe("scripts/test-projects full-suite sharding", () => {
includePatterns: null,
watchMode: false,
},
{
config: "vitest.full-core-bundled.config.ts",
forwardedArgs: [],
includePatterns: null,
watchMode: false,
},
{
config: "vitest.full-core-runtime.config.ts",
forwardedArgs: [],

View File

@@ -30,11 +30,11 @@ describe("projects vitest config", () => {
expect(config.test.runner).toBe("./test/non-isolated-runner.ts");
});
it("keeps the root ui lane aligned with the shared non-isolated jsdom setup", () => {
it("keeps the root ui lane aligned with the isolated jsdom setup", () => {
const config = createUiVitestConfig();
expect(config.test.environment).toBe("jsdom");
expect(config.test.isolate).toBe(false);
expect(config.test.runner).toBe("./test/non-isolated-runner.ts");
expect(config.test.isolate).toBe(true);
expect(config.test.runner).toBeUndefined();
expect(config.test.setupFiles).not.toContain("test/setup-openclaw-runtime.ts");
expect(config.test.setupFiles).toContain("ui/src/test-helpers/lit-warnings.setup.ts");
expect(config.test.deps?.optimizer?.web?.enabled).toBe(true);

View File

@@ -0,0 +1,7 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find((shard) => shard.config === "vitest.full-core-bundled.config.ts")
?.projects ?? [],
);

View File

@@ -0,0 +1,7 @@
import { createProjectShardVitestConfig } from "./vitest.project-shard-config.ts";
import { fullSuiteVitestShards } from "./vitest.test-shards.mjs";
export default createProjectShardVitestConfig(
fullSuiteVitestShards.find((shard) => shard.config === "vitest.full-core-unit-ui.config.ts")
?.projects ?? [],
);

View File

@@ -17,6 +17,11 @@ export const fullSuiteVitestShards = [
name: "core-unit-security",
projects: ["vitest.unit-security.config.ts"],
},
{
config: "vitest.full-core-unit-ui.config.ts",
name: "core-unit-ui",
projects: ["vitest.unit-ui.config.ts"],
},
{
config: "vitest.full-core-unit-support.config.ts",
name: "core-unit-support",
@@ -29,7 +34,12 @@ export const fullSuiteVitestShards = [
{
config: "vitest.full-core-contracts.config.ts",
name: "core-contracts",
projects: ["vitest.contracts.config.ts", "vitest.bundled.config.ts"],
projects: ["vitest.contracts.config.ts"],
},
{
config: "vitest.full-core-bundled.config.ts",
name: "core-bundled",
projects: ["vitest.bundled.config.ts"],
},
{
config: "vitest.full-core-runtime.config.ts",

View File

@@ -2,17 +2,5 @@ import { createUnitVitestConfigWithOptions } from "./vitest.unit.config.ts";
export default createUnitVitestConfigWithOptions(process.env, {
name: "unit-support",
includePatterns: [
"packages/**/*.test.ts",
"test/**/*.test.ts",
"ui/src/ui/app-chat.test.ts",
"ui/src/ui/chat/**/*.test.ts",
"ui/src/ui/views/agents-utils.test.ts",
"ui/src/ui/views/channels.test.ts",
"ui/src/ui/views/chat.test.ts",
"ui/src/ui/views/dreams.test.ts",
"ui/src/ui/views/usage-render-details.test.ts",
"ui/src/ui/controllers/agents.test.ts",
"ui/src/ui/controllers/chat.test.ts",
],
includePatterns: ["packages/**/*.test.ts"],
});

16
vitest.unit-ui.config.ts Normal file
View File

@@ -0,0 +1,16 @@
import { createUnitVitestConfigWithOptions } from "./vitest.unit.config.ts";
export default createUnitVitestConfigWithOptions(process.env, {
name: "unit-ui",
includePatterns: [
"ui/src/ui/app-chat.test.ts",
"ui/src/ui/chat/**/*.test.ts",
"ui/src/ui/views/agents-utils.test.ts",
"ui/src/ui/views/channels.test.ts",
"ui/src/ui/views/chat.test.ts",
"ui/src/ui/views/dreams.test.ts",
"ui/src/ui/views/usage-render-details.test.ts",
"ui/src/ui/controllers/agents.test.ts",
"ui/src/ui/controllers/chat.test.ts",
],
});