Tests: align unit sharding with unit config
This commit is contained in:
parent
e6911f0448
commit
e9903c9133
@ -3,6 +3,7 @@ import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { channelTestPrefixes } from "../vitest.channel-paths.mjs";
|
||||
import { isUnitConfigTestFile } from "../vitest.unit-paths.mjs";
|
||||
import {
|
||||
loadTestRunnerBehavior,
|
||||
loadUnitTimingManifest,
|
||||
@ -16,10 +17,11 @@ const pnpm = "pnpm";
|
||||
const behaviorManifest = loadTestRunnerBehavior();
|
||||
const existingFiles = (entries) =>
|
||||
entries.map((entry) => entry.file).filter((file) => fs.existsSync(file));
|
||||
const unitBehaviorIsolatedFiles = existingFiles(behaviorManifest.unit.isolated);
|
||||
const unitSingletonIsolatedFiles = existingFiles(behaviorManifest.unit.singletonIsolated);
|
||||
const unitThreadSingletonFiles = existingFiles(behaviorManifest.unit.threadSingleton);
|
||||
const unitVmForkSingletonFiles = existingFiles(behaviorManifest.unit.vmForkSingleton);
|
||||
const existingUnitConfigFiles = (entries) => existingFiles(entries).filter(isUnitConfigTestFile);
|
||||
const unitBehaviorIsolatedFiles = existingUnitConfigFiles(behaviorManifest.unit.isolated);
|
||||
const unitSingletonIsolatedFiles = existingUnitConfigFiles(behaviorManifest.unit.singletonIsolated);
|
||||
const unitThreadSingletonFiles = existingUnitConfigFiles(behaviorManifest.unit.threadSingleton);
|
||||
const unitVmForkSingletonFiles = existingUnitConfigFiles(behaviorManifest.unit.vmForkSingleton);
|
||||
const unitBehaviorOverrideSet = new Set([
|
||||
...unitBehaviorIsolatedFiles,
|
||||
...unitSingletonIsolatedFiles,
|
||||
@ -237,10 +239,7 @@ const parseEnvNumber = (name, fallback) => {
|
||||
return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
|
||||
};
|
||||
const allKnownUnitFiles = allKnownTestFiles.filter((file) => {
|
||||
if (file.endsWith(".live.test.ts") || file.endsWith(".e2e.test.ts")) {
|
||||
return false;
|
||||
}
|
||||
return inferTarget(file).owner !== "gateway";
|
||||
return isUnitConfigTestFile(file);
|
||||
});
|
||||
const defaultHeavyUnitFileLimit =
|
||||
testProfile === "serial" ? 0 : testProfile === "low" ? 20 : highMemLocalHost ? 80 : 60;
|
||||
@ -730,10 +729,12 @@ const runOnce = (entry, extraArgs = []) =>
|
||||
|
||||
const run = async (entry, extraArgs = []) => {
|
||||
const explicitFilterCount = countExplicitEntryFilters(entry.args);
|
||||
// Wrapper-generated singleton/small-file lanes should not ask Vitest to shard
|
||||
// into more buckets than there are explicit test filters.
|
||||
// Vitest requires the shard count to stay strictly below the number of
|
||||
// resolved test files, so explicit-filter lanes need a `< fileCount` cap.
|
||||
const effectiveShardCount =
|
||||
explicitFilterCount === null ? shardCount : Math.min(shardCount, explicitFilterCount);
|
||||
explicitFilterCount === null
|
||||
? shardCount
|
||||
: Math.min(shardCount, Math.max(1, explicitFilterCount - 1));
|
||||
|
||||
if (effectiveShardCount <= 1) {
|
||||
if (shardIndexOverride !== null && shardIndexOverride > effectiveShardCount) {
|
||||
|
||||
21
test/vitest-unit-paths.test.ts
Normal file
21
test/vitest-unit-paths.test.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isUnitConfigTestFile } from "../vitest.unit-paths.mjs";
|
||||
|
||||
describe("isUnitConfigTestFile", () => {
|
||||
it("accepts unit-config src, test, and whitelisted ui tests", () => {
|
||||
expect(isUnitConfigTestFile("src/infra/git-commit.test.ts")).toBe(true);
|
||||
expect(isUnitConfigTestFile("test/format-error.test.ts")).toBe(true);
|
||||
expect(isUnitConfigTestFile("ui/src/ui/views/chat.test.ts")).toBe(true);
|
||||
});
|
||||
|
||||
it("rejects files excluded from the unit config", () => {
|
||||
expect(
|
||||
isUnitConfigTestFile("extensions/imessage/src/monitor.shutdown.unhandled-rejection.test.ts"),
|
||||
).toBe(false);
|
||||
expect(isUnitConfigTestFile("src/agents/pi-embedded-runner.test.ts")).toBe(false);
|
||||
expect(isUnitConfigTestFile("src/commands/onboard.test.ts")).toBe(false);
|
||||
expect(isUnitConfigTestFile("ui/src/ui/views/other.test.ts")).toBe(false);
|
||||
expect(isUnitConfigTestFile("src/infra/git-commit.live.test.ts")).toBe(false);
|
||||
expect(isUnitConfigTestFile("src/infra/git-commit.e2e.test.ts")).toBe(false);
|
||||
});
|
||||
});
|
||||
46
vitest.unit-paths.mjs
Normal file
46
vitest.unit-paths.mjs
Normal file
@ -0,0 +1,46 @@
|
||||
import path from "node:path";
|
||||
|
||||
export const unitTestIncludePatterns = [
|
||||
"src/**/*.test.ts",
|
||||
"test/**/*.test.ts",
|
||||
"ui/src/ui/app-chat.test.ts",
|
||||
"ui/src/ui/views/agents-utils.test.ts",
|
||||
"ui/src/ui/views/chat.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",
|
||||
];
|
||||
|
||||
export const unitTestAdditionalExcludePatterns = [
|
||||
"src/gateway/**",
|
||||
"extensions/**",
|
||||
"src/browser/**",
|
||||
"src/line/**",
|
||||
"src/agents/**",
|
||||
"src/auto-reply/**",
|
||||
"src/commands/**",
|
||||
];
|
||||
|
||||
const sharedBaseExcludePatterns = [
|
||||
"dist/**",
|
||||
"apps/macos/**",
|
||||
"apps/macos/.build/**",
|
||||
"**/node_modules/**",
|
||||
"**/vendor/**",
|
||||
"dist/OpenClaw.app/**",
|
||||
"**/*.live.test.ts",
|
||||
"**/*.e2e.test.ts",
|
||||
];
|
||||
|
||||
const normalizeRepoPath = (value) => value.split(path.sep).join("/");
|
||||
|
||||
const matchesAny = (file, patterns) => patterns.some((pattern) => path.matchesGlob(file, pattern));
|
||||
|
||||
export function isUnitConfigTestFile(file) {
|
||||
const normalizedFile = normalizeRepoPath(file);
|
||||
return (
|
||||
matchesAny(normalizedFile, unitTestIncludePatterns) &&
|
||||
!matchesAny(normalizedFile, sharedBaseExcludePatterns) &&
|
||||
!matchesAny(normalizedFile, unitTestAdditionalExcludePatterns)
|
||||
);
|
||||
}
|
||||
@ -1,27 +1,19 @@
|
||||
import { defineConfig } from "vitest/config";
|
||||
import baseConfig from "./vitest.config.ts";
|
||||
import {
|
||||
unitTestAdditionalExcludePatterns,
|
||||
unitTestIncludePatterns,
|
||||
} from "./vitest.unit-paths.mjs";
|
||||
|
||||
const base = baseConfig as unknown as Record<string, unknown>;
|
||||
const baseTest = (baseConfig as { test?: { include?: string[]; exclude?: string[] } }).test ?? {};
|
||||
const include = (
|
||||
baseTest.include ?? ["src/**/*.test.ts", "extensions/**/*.test.ts", "test/format-error.test.ts"]
|
||||
).filter((pattern) => !pattern.includes("extensions/"));
|
||||
const exclude = baseTest.exclude ?? [];
|
||||
|
||||
export default defineConfig({
|
||||
...base,
|
||||
test: {
|
||||
...baseTest,
|
||||
include,
|
||||
exclude: [
|
||||
...exclude,
|
||||
"src/gateway/**",
|
||||
"extensions/**",
|
||||
"src/browser/**",
|
||||
"src/line/**",
|
||||
"src/agents/**",
|
||||
"src/auto-reply/**",
|
||||
"src/commands/**",
|
||||
],
|
||||
include: unitTestIncludePatterns,
|
||||
exclude: [...exclude, ...unitTestAdditionalExcludePatterns],
|
||||
},
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user