Skip to content

Commit b31e822

Browse files
committed
Fix mutation testing pipeline and tighten threshold to 70
Stryker's default plugins glob "@stryker-mutator/*" resolves a directory relative to core's own install path. Under pnpm's isolated layout that landed in .pnpm/@stryker-mutator+core.../node_modules/@stryker-mutator/, which only contains core/api/util/instrumenter (all on Stryker's IGNORED_PACKAGES list). Sibling plugins live in different .pnpm/* paths, so the glob found nothing and every run died at "Cannot find Checker plugin typescript". List the two plugins explicitly so they go through normal import() resolution and resolve via root node_modules symlinks. Point tsconfigFile at server/tsconfig.json instead of tsconfig.base.json: the base is an options-only file with no include, so tsc fell back to **/*.ts from cwd and hit genuine type errors in client/test/ (which typecheck under client/tsconfig.json's lib: ["DOM"]). Drop transpilers/*/src from mutate. The real transpiler tests are shell scripts (server/test/{td,tbaf}/test.sh) that invoke the built fgtp CLI and diff against expected files; they are not vitest tests and Stryker's vitest-runner cannot see them. The transpilers' in-vitest suite covers <15% of the surface (transpilers/vitest.config.ts floor), so mutating those files against the vitest suite would have produced a floor-near-0 score regardless of how the pipeline was tuned. Add server/vitest.mutation.config.ts as the Stryker test config. It extends server/vitest.config.ts but excludes tests that read from external/ (rename.test.ts, call-sites.test.ts, weidu-tp2/format.test.ts) because Stryker's sandbox does not have those fixtures: external/ is ignored via ignorePatterns since it contains cloned mod repos with broken symlinks that crash the sandbox copy walker. Coverage is disabled since Stryker has its own perTest coverage analysis. Whitelist the new vitest config in knip.ts: knip's Stryker plugin resolves runner and checker package names from stryker.conf.json but not the vitest configFile path. With the pipeline working, baseline mutation score on master is 70.09%: - normalized-uri.ts: 100% (5/5 mutants killed) - provider-registry.ts: 84.31% (43 killed, 4 survived, 4 no-coverage) - symbol-index.ts: 65.17% (116 killed, 40 survived, 22 no-coverage) Raise break and low from 60 to 70 to floor-and-ratchet at today's score.
1 parent 70550d8 commit b31e822

3 files changed

Lines changed: 45 additions & 6 deletions

File tree

knip.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ const config: KnipConfig = {
3232
server: {
3333
// Point knip at the TypeScript source entry directly.
3434
// The package.json "main" field targets the built JS output.
35-
entry: ["src/server.ts"],
35+
// vitest.mutation.config.ts is referenced from stryker.conf.json
36+
// (vitest.configFile); knip's Stryker plugin resolves runner/checker
37+
// package names but not vitest configFile paths, so list it explicitly.
38+
entry: ["src/server.ts", "vitest.mutation.config.ts"],
3639
// Created at runtime by enum-transform.test.ts, may exist during parallel Knip runs
3740
ignore: [
3841
"**/*.d.ts",

server/vitest.mutation.config.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Vitest configuration used by Stryker mutation testing.
3+
*
4+
* Extends `vitest.config.ts` (server unit suite) and excludes the few tests
5+
* that read fixtures from `external/`. Stryker's sandbox excludes `external/`
6+
* because it contains cloned mod repos with broken symlinks that crash the
7+
* sandbox copy; the affected tests cannot run inside the sandbox regardless.
8+
*
9+
* Coverage is disabled here - mutation testing has its own coverage analysis
10+
* (`coverageAnalysis: "perTest"` in `stryker.conf.json`).
11+
*/
12+
13+
import { defineConfig, mergeConfig } from "vitest/config";
14+
import baseConfig from "./vitest.config";
15+
16+
export default mergeConfig(
17+
baseConfig,
18+
defineConfig({
19+
test: {
20+
name: "server-mutation",
21+
exclude: [
22+
"test/smoke-stdio.test.ts",
23+
"test/integration/**",
24+
"test/perf/**",
25+
"test/fallout-ssl/rename.test.ts",
26+
"test/fallout-ssl/call-sites.test.ts",
27+
"test/weidu-tp2/format.test.ts",
28+
],
29+
coverage: { enabled: false },
30+
},
31+
}),
32+
);

stryker.conf.json

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,24 @@
22
"$schema": "./node_modules/@stryker-mutator/core/schema/stryker-schema.json",
33
"packageManager": "pnpm",
44
"testRunner": "vitest",
5+
"plugins": ["@stryker-mutator/typescript-checker", "@stryker-mutator/vitest-runner"],
6+
"vitest": {
7+
"configFile": "server/vitest.mutation.config.ts",
8+
"dir": "server"
9+
},
510
"mutate": [
6-
"transpilers/*/src/**/*.ts",
7-
"!transpilers/*/src/**/*.test.ts",
811
"server/src/core/normalized-uri.ts",
912
"server/src/core/symbol-index.ts",
1013
"server/src/provider-registry.ts"
1114
],
1215
"checkers": ["typescript"],
13-
"tsconfigFile": "tsconfig.base.json",
16+
"tsconfigFile": "server/tsconfig.json",
17+
"ignorePatterns": ["external", "tmp", ".vscode-test"],
1418
"coverageAnalysis": "perTest",
1519
"thresholds": {
1620
"high": 80,
17-
"low": 60,
18-
"break": 60
21+
"low": 70,
22+
"break": 70
1923
},
2024
"reporters": ["clear-text", "progress", "html"],
2125
"htmlReporter": {

0 commit comments

Comments
 (0)