chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env node
|
||||
// Measure testcontainers boot/teardown vs test time for a single test file.
|
||||
//
|
||||
// Usage (from any package dir, or pass --cwd):
|
||||
// node <path>/measure-test-timing.mjs <testFile> [--cwd <packageDir>] [--runs N]
|
||||
//
|
||||
// Relies on the TESTCONTAINERS_TIMING log gate in src/logs.ts and runs vitest with
|
||||
// --disableConsoleIntercept so the JSON timing lines reach stdout.
|
||||
|
||||
import { spawn } from "node:child_process";
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const testFile = args.find((a) => !a.startsWith("--"));
|
||||
const cwd = valueOf("--cwd") ?? process.cwd();
|
||||
const runs = Number(valueOf("--runs") ?? "1");
|
||||
|
||||
function valueOf(flag) {
|
||||
const i = args.indexOf(flag);
|
||||
return i >= 0 ? args[i + 1] : undefined;
|
||||
}
|
||||
|
||||
if (!testFile) {
|
||||
console.error("usage: measure-test-timing.mjs <testFile> [--cwd dir] [--runs N]");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function runOnce() {
|
||||
return new Promise((resolve) => {
|
||||
const child = spawn("pnpm", ["exec", "vitest", "run", testFile, "--disableConsoleIntercept"], {
|
||||
cwd,
|
||||
env: { ...process.env, TESTCONTAINERS_TIMING: "1" },
|
||||
});
|
||||
|
||||
let out = "";
|
||||
const collect = (buf) => (out += buf.toString());
|
||||
child.stdout.on("data", collect);
|
||||
child.stderr.on("data", collect);
|
||||
|
||||
child.on("close", () => {
|
||||
const cleanups = [];
|
||||
let duration = null;
|
||||
for (const line of out.split("\n")) {
|
||||
const trimmed = line.trim();
|
||||
if (trimmed.startsWith("{")) {
|
||||
try {
|
||||
const ev = JSON.parse(trimmed);
|
||||
if (ev.type === "cleanup") cleanups.push(ev);
|
||||
} catch {}
|
||||
}
|
||||
const m = trimmed.match(/Duration\s+([\d.]+)s/);
|
||||
if (m) duration = Number(m[1]);
|
||||
}
|
||||
resolve({ cleanups, duration, passed: /Tests\s+\d+ passed/.test(out) });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
for (let i = 0; i < runs; i++) {
|
||||
const { cleanups, duration, passed } = await runOnce();
|
||||
const byResource = {};
|
||||
for (const c of cleanups) {
|
||||
const key = c.resource.split(":")[0];
|
||||
byResource[key] ??= { totalMs: 0, count: 0 };
|
||||
byResource[key].totalMs += c.durationMs ?? 0;
|
||||
byResource[key].count += 1;
|
||||
}
|
||||
const teardownMs = Object.values(byResource).reduce((a, r) => a + r.totalMs, 0);
|
||||
console.log(
|
||||
`\nrun ${i + 1}/${runs} passed=${passed} wall=${duration}s teardown=${(
|
||||
teardownMs / 1000
|
||||
).toFixed(2)}s`
|
||||
);
|
||||
for (const [res, r] of Object.entries(byResource)) {
|
||||
console.log(` teardown ${res}: ${(r.totalMs / 1000).toFixed(2)}s over ${r.count}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user