Skip to content

Commit c3a356b

Browse files
--wip-- [skip ci]
1 parent a52a820 commit c3a356b

11 files changed

Lines changed: 472 additions & 140 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,5 @@ packages/app/.env
132132
# turbo
133133
.turbo/
134134
.rollup.cache/
135+
136+
.codspeed

CLAUDE.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,25 @@ Based on the codebase analysis, to add stats access features:
9494
- Build: `pnpm turbo run build --filter=<package-name>`
9595
- Typecheck: `pnpm turbo run typecheck --filter=<package-name>`
9696
- Lint: `pnpm turbo run lint --filter=<package-name>`
97-
- Run a task across all packages by omitting `--filter` (e.g. `pnpm turbo run build`).
97+
- Run a task across all packages by omitting `--filter` (e.g. `pnpm turbo run build`).
98+
99+
## Testing a plugin during development
100+
101+
A plugin behaves differently depending on whether CodSpeed is driving the run,
102+
so exercise all three of these when developing or reviewing a plugin change
103+
(build the plugin first — the benches import from `dist`):
104+
105+
1. **Fallback (not under CodSpeed).** No env vars. The plugin must stay out of
106+
the way and let the framework run its benchmarks normally (no instrumentation,
107+
no hijacked output). e.g. `pnpm turbo run bench --filter=<package-name>`.
108+
2. **Instrumentation / simulation.** `CODSPEED_ENV=true CODSPEED_RUNNER_MODE=simulation`
109+
(or `instrumentation`). The plugin hijacks the run to do a single instrumented
110+
pass per benchmark and prints `Measured/Checked <uri>` instead of the normal
111+
harness output.
112+
3. **Walltime.** `CODSPEED_ENV=true CODSPEED_RUNNER_MODE=walltime`. The plugin
113+
instruments the framework's real benchmark loop and collects walltime results.
114+
115+
Running these locally outside the CodSpeed runner is expected to log
116+
`instrument-hooks: failed to write environment.json` and skip actual measurement
117+
writes — the point is to verify the plugin's control flow and output per mode,
118+
not to produce real measurements.
Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { bench, describe } from "vitest";
1+
import { describe, test } from "vitest";
22
import parsePr from "./parsePr";
33

44
const LONG_BODY =
@@ -9,12 +9,16 @@ const LONG_BODY =
99
.join("\n") + "fixes #123";
1010

1111
describe("parsePr", () => {
12-
bench("short body", () => {
13-
parsePr({ body: "fixes #123", title: "test-1", number: 1 });
12+
test("short body", async ({ bench }) => {
13+
await bench("short body", () => {
14+
parsePr({ body: "fixes #123", title: "test-1", number: 1 });
15+
}).run();
1416
});
1517

16-
bench("long body", () => {
17-
parsePr({ body: LONG_BODY, title: "test-2", number: 2 });
18+
test("long body", async ({ bench }) => {
19+
await bench("long body", () => {
20+
parsePr({ body: LONG_BODY, title: "test-2", number: 2 });
21+
}).run();
1822
});
1923
});
2024

@@ -24,10 +28,14 @@ function fibo(n: number): number {
2428
}
2529

2630
describe("fibo", () => {
27-
bench("fibo 10", () => {
28-
fibo(10);
31+
test("fibo 10", async ({ bench }) => {
32+
await bench("fibo 10", () => {
33+
fibo(10);
34+
}).run();
2935
});
30-
bench("fibo 15", () => {
31-
fibo(15);
36+
test("fibo 15", async ({ bench }) => {
37+
await bench("fibo 15", () => {
38+
fibo(15);
39+
}).run();
3240
});
3341
});
Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,42 @@
1-
import {
2-
afterAll,
3-
afterEach,
4-
beforeAll,
5-
beforeEach,
6-
bench,
7-
describe,
8-
expect,
9-
} from "vitest";
1+
import { describe, expect, test } from "vitest";
102

3+
// Exercises tinybench's per-benchmark hooks, which Vitest 5 exposes through the
4+
// `bench(name, options, fn)` options object (`beforeAll`/`beforeEach`/...).
115
describe("hooks", () => {
126
let count = 0;
7+
138
describe("run", () => {
14-
beforeAll(() => {
15-
count += 10;
16-
});
17-
beforeEach(() => {
18-
count += 1;
19-
});
20-
afterEach(() => {
21-
count -= 1;
22-
});
23-
afterAll(() => {
24-
count -= 10;
25-
});
9+
const hooks = {
10+
beforeAll: () => {
11+
count += 10;
12+
},
13+
beforeEach: () => {
14+
count += 1;
15+
},
16+
afterEach: () => {
17+
count -= 1;
18+
},
19+
afterAll: () => {
20+
count -= 10;
21+
},
22+
};
2623

27-
bench("one", () => {
28-
expect(count).toBe(11);
24+
test("one", async ({ bench }) => {
25+
await bench("one", hooks, () => {
26+
expect(count).toBe(11);
27+
}).run();
2928
});
30-
bench("two", () => {
31-
expect(count).toBe(11);
29+
30+
test("two", async ({ bench }) => {
31+
await bench("two", hooks, () => {
32+
expect(count).toBe(11);
33+
}).run();
3234
});
3335
});
34-
bench("end", () => {
35-
expect(count).toBe(0);
36+
37+
test("end", async ({ bench }) => {
38+
await bench("end", () => {
39+
expect(count).toBe(0);
40+
}).run();
3641
});
3742
});

packages/vitest-plugin/benches/macos.bench.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { bench, describe } from "vitest";
1+
import { describe, test } from "vitest";
22

33
const isMacOS = process.platform === "darwin";
44

@@ -10,7 +10,9 @@ function fibo(n: number): number {
1010
// macOS-only benchmark: skipped on every other platform, so it only runs on
1111
// the `codspeed-walltime-macos` CI job (see .github/workflows/codspeed.yml).
1212
describe.skipIf(!isMacOS)("macos only", () => {
13-
bench("fibo darwin", () => {
14-
fibo(30);
13+
test("fibo darwin", async ({ bench }) => {
14+
await bench("fibo darwin", () => {
15+
fibo(30);
16+
}).run();
1517
});
1618
});
Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { bench, describe } from "vitest";
1+
import { describe, test } from "vitest";
22
import parsePr from "./parsePr";
33

44
const LONG_BODY =
@@ -8,44 +8,52 @@ const LONG_BODY =
88
)
99
.join("\n") + "fixes #123";
1010

11+
function benchShortBody() {
12+
parsePr({ body: "fixes #123", title: "test", number: 124 });
13+
}
14+
15+
function benchLongBody() {
16+
parsePr({ body: LONG_BODY, title: "test", number: 124 });
17+
}
18+
1119
describe("parsePr", () => {
12-
bench("short body", () => {
13-
parsePr({ body: "fixes #123", title: "test", number: 124 });
20+
test("short body", async ({ bench }) => {
21+
await bench("short body", benchShortBody).run();
1422
});
1523

16-
bench("long body", () => {
17-
parsePr({ body: LONG_BODY, title: "test", number: 124 });
24+
test("long body", async ({ bench }) => {
25+
await bench("long body", benchLongBody).run();
1826
});
1927

2028
describe("nested suite", () => {
21-
bench("short body", () => {
22-
parsePr({ body: "fixes #123", title: "test", number: 124 });
29+
test("short body", async ({ bench }) => {
30+
await bench("short body", benchShortBody).run();
2331
});
2432

25-
bench("long body", () => {
26-
parsePr({ body: LONG_BODY, title: "test", number: 124 });
33+
test("long body", async ({ bench }) => {
34+
await bench("long body", benchLongBody).run();
2735
});
2836

2937
describe("deeply nested suite", () => {
30-
bench("short body", () => {
31-
parsePr({ body: "fixes #123", title: "test", number: 124 });
38+
test("short body", async ({ bench }) => {
39+
await bench("short body", benchShortBody).run();
3240
});
3341
});
3442
});
3543
});
3644

3745
describe("another parsePr", () => {
38-
bench("short body", () => {
39-
parsePr({ body: "fixes #123", title: "test", number: 124 });
46+
test("short body", async ({ bench }) => {
47+
await bench("short body", benchShortBody).run();
4048
});
4149

42-
bench("long body", () => {
43-
parsePr({ body: LONG_BODY, title: "test", number: 124 });
50+
test("long body", async ({ bench }) => {
51+
await bench("long body", benchLongBody).run();
4452
});
4553

4654
describe("nested suite", () => {
47-
bench("short body", () => {
48-
parsePr({ body: "fixes #123", title: "test", number: 124 });
55+
test("short body", async ({ bench }) => {
56+
await bench("short body", benchShortBody).run();
4957
});
5058
});
5159
});
Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { bench, describe, type BenchOptions } from "vitest";
1+
import { describe, test, type BenchOptions } from "vitest";
22

33
const busySleep = (ms: number): void => {
44
const end = performance.now() + ms;
@@ -13,27 +13,21 @@ const timingBenchOptions: BenchOptions = {
1313
};
1414

1515
describe("timing tests", () => {
16-
bench(
17-
"wait 1ms",
18-
async () => {
16+
test("wait 1ms", async ({ bench }) => {
17+
await bench("wait 1ms", async () => {
1918
busySleep(1);
20-
},
21-
timingBenchOptions,
22-
);
19+
}).run(timingBenchOptions);
20+
});
2321

24-
bench(
25-
"wait 500ms",
26-
async () => {
22+
test("wait 500ms", async ({ bench }) => {
23+
await bench("wait 500ms", async () => {
2724
busySleep(500);
28-
},
29-
timingBenchOptions,
30-
);
25+
}).run(timingBenchOptions);
26+
});
3127

32-
bench(
33-
"wait 1sec",
34-
async () => {
28+
test("wait 1sec", async ({ bench }) => {
29+
await bench("wait 1sec", async () => {
3530
busySleep(1_000);
36-
},
37-
timingBenchOptions,
38-
);
31+
}).run(timingBenchOptions);
32+
});
3933
});

packages/vitest-plugin/src/globalSetup.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,22 @@ function logCodSpeed(message: string) {
99
console.log(`[CodSpeed] ${message}`);
1010
}
1111

12+
let setupHappened = false;
1213
let teardownHappened = false;
1314

15+
// TODO: Check if this can be avoided
16+
// Vitest 5 forks a dedicated `(bench)` project from the base one and runs
17+
// globalSetup for both it and the root project, so setup/teardown fire more than
18+
// once against this shared module. Log only the first pass and make the rest
19+
// no-ops rather than treating the repeat as an error.
1420
export default function () {
15-
logCodSpeed(`@codspeed/vitest-plugin v${__VERSION__} - setup`);
21+
if (!setupHappened) {
22+
setupHappened = true;
23+
logCodSpeed(`@codspeed/vitest-plugin v${__VERSION__} - setup`);
24+
}
1625

1726
return () => {
18-
if (teardownHappened) throw new Error("teardown called twice");
27+
if (teardownHappened) return;
1928
teardownHappened = true;
2029

2130
logCodSpeed(`@codspeed/vitest-plugin v${__VERSION__} - teardown`);

0 commit comments

Comments
 (0)