Skip to content

chore: Stryker mutation testing (opt-in, local only, never CI)#115

Merged
rodrigobnogueira merged 1 commit into
mainfrom
chore/mutation-testing
Jul 5, 2026
Merged

chore: Stryker mutation testing (opt-in, local only, never CI)#115
rodrigobnogueira merged 1 commit into
mainfrom
chore/mutation-testing

Conversation

@rodrigobnogueira

Copy link
Copy Markdown
Collaborator

An opt-in, local-only layer on top of the normal gate. CI is untouched by design; forks run npm test exactly as before, and no workflow file changes.

Mutation testing (Stryker 9.6, command runner): npm run test:mutation (incremental — the pre-PR ritual), test:mutation:full (--force), STRYKER_MUTATE to scope to the files a change touched (comma-separated globs). Two hard-won details from the drizzle repo are encoded in the config:

  • the per-mutant command is a dedicated test:mutant script = the normal mocha suite plus --exit — a mutant that breaks teardown would otherwise leave open handles and turn every kill into a slow timeout;
  • concurrency is capped at 4 — each command-runner mutant spawns a full ts-node/esm + mocha process, so Stryker's default worker count oversubscribes the CPU and turns every kill into a timeout.

ignorePatterns keeps the per-mutant sandbox copies small by excluding sample (128M, including the Angular fullstack showcase), website (473M), docs, coverage, complexity, .tmp, and dist.

Verification (local): scoped smoke run over packages/trpc/decorators/param-metadata.util.ts + packages/trpc/context/trpc-enhancer-runtime.factory.ts: 20 mutants — 14 killed, 4 timeout, 2 survived, 0 errors in 1m35s. The 4 timeouts are genuine detections: all four corrupt param metadata and hang E2E specs that raise mocha timeouts to 15–30s, blowing Stryker's per-mutant allowance. The 2 survivors point at an untested propertyKey == null guard in addTrpcParamMetadata — a candidate test addition for a future PR, exactly the signal this tool is for.

npm run ci ran green locally (note: the Angular showcase ng build gates on Node ≥22.22.3 — pre-existing on main's lockfile, unrelated to this change; that one step was verified green with the locally installed v22.23.1).

Docs: new "11. Mutation testing (Stryker — local only, never in CI)" section in GUIDELINES_NEST_TRPC.md (pre-PR ritual: run test:mutation, look at surviving mutants, mention the outcome in the PR body), README Workspace Commands pointer, CHANGELOG Unreleased entry. Repo tooling only — nothing ships in the package, no release.

Adds Stryker 9.6 with the command runner as an opt-in, local-only gate.
CI is untouched by design; forks run npm test exactly as before.

- npm run test:mutation (incremental - the pre-PR ritual),
  test:mutation:full (--force), STRYKER_MUTATE to scope to changed files.
- The per-mutant command is a dedicated test:mutant script = the normal
  mocha suite plus --exit: a mutant that breaks teardown would otherwise
  leave open handles and turn every kill into a slow timeout.
- concurrency is capped at 4: each command-runner mutant spawns a full
  ts-node/esm + mocha process, so default Stryker worker counts
  oversubscribe the CPU and turn every kill into a timeout.
- ignorePatterns excludes sample (128M, incl. the Angular showcase),
  website (473M), docs, coverage, complexity, .tmp and dist so the
  per-mutant sandbox copies stay small.
- Docs: new guidelines section 11 (mutation testing), README pointer,
  CHANGELOG Unreleased entry. Repo tooling only - nothing ships in the
  package, no release.

Verified locally: scoped smoke run over param-metadata.util.ts +
trpc-enhancer-runtime.factory.ts: 20 mutants, 14 killed, 4 timeout
(hanging-mutant detections in specs that raise mocha timeouts), 2
survived, 0 errors, in 1m35s. npm run ci green (the Angular showcase
ng build requires Node >=22.22.3 and was verified with the local
v22.23.1; everything else ran on the standard toolchain).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

📊 Coverage Coverage Report

Metric PR Base Diff
Statements ████████████████████ 664/664 (100%) 664/664 (100%) ⚪ 0%
Branches ████████████████████ 283/283 (100%) 283/283 (100%) ⚪ 0%
Functions ████████████████████ 122/122 (100%) 122/122 (100%) ⚪ 0%
Lines ████████████████████ 639/639 (100%) 639/639 (100%) ⚪ 0%

Updated for b51bf23 | Compared against base branch

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

⏱️ Performance Report

✅ Tests 199 passed, 0 failed, 0 skipped
🧪 Suites 39
⏱️ Total step time 11.00s (install + tests) ⚪ ~0
⚙️ Test execution 3.38s ⚪ ~0
🐢 Slowest test suites
# Suite Tests Duration vs Base
1 test/generators/schema-generator.spec.ts 19 2.35s 🟢 -96ms
2 test/adapter/trpc-client-adapter-e2e.spec.ts 16 236ms ⚪ ~0
3 test/adapter/trpc-http-adapter.spec.ts 19 95ms ⚪ ~0
4 test/router/trpc-router.spec.ts 29 42ms ⚪ ~0
5 test/context/trpc-context-creator.spec.ts 26 38ms ⚪ ~0
6 test/adapter/trpc-http-adapter-unit.spec.ts 22 22ms ⚪ ~0
7 test/generators/zod-serializer.spec.ts 37 11ms ⚪ ~0
8 test/router/trpc-router-lifecycle.spec.ts 11 11ms ⚪ ~0
9 test/module/trpc-module.spec.ts 4 5ms ⚪ ~0
10 test/context/trpc-enhancer-runtime.factory.spec.ts 1 1ms ⚪ ~0
🐌 Slowest individual tests
# Suite Test Duration vs Base
1 schema-generator generateSchemaContent (type-level AppRouter contract) should require a link transformer on typed clients when generated with hasTransformer 1.47s ⚪ ~0
2 schema-generator generateSchemaContent (type-level AppRouter contract) should typecheck generated AppRouter with a typed tRPC client 871ms 🟢 -118ms
3 trpc-client-adapter-e2e real @trpc/client adapter E2E express handles typed queries, mutations, and context extraction 74ms ⚪ ~0
4 trpc-client-adapter-e2e real @trpc/client adapter E2E express runs class-validator DTO validation through ValidationPipe 27ms ⚪ ~0
5 trpc-client-adapter-e2e real @trpc/client adapter E2E express streams subscriptions through the real client 26ms ⚪ ~0
6 trpc-client-adapter-e2e real @trpc/client adapter E2E fastify handles typed queries, mutations, and context extraction 16ms ⚪ ~0
7 trpc-client-adapter-e2e real @trpc/client adapter E2E fastify runs class-validator DTO validation through ValidationPipe 13ms ⚪ ~0
8 trpc-client-adapter-e2e real @trpc/client adapter E2E express reports Zod input errors through the real client 12ms ⚪ ~0
9 trpc-http-adapter TrpcHttpAdapter edge cases should handle Fastify GET with createContext 12ms ⚪ ~0
10 trpc-client-adapter-e2e real @trpc/client with superjson transformer E2E express exposes the flattened ZodError shape to the real client 10ms ⚪ ~0
11 trpc-client-adapter-e2e real @trpc/client adapter E2E fastify reports Zod input errors through the real client 9ms ⚪ ~0
12 trpc-client-adapter-e2e real @trpc/client adapter E2E fastify streams subscriptions through the real client 9ms ⚪ ~0
13 trpc-http-adapter TrpcHttpAdapter Fastify handler should handle GET query requests 8ms ⚪ ~0
14 trpc-client-adapter-e2e real @trpc/client with superjson transformer E2E express round-trips Date instances through queries 7ms ⚪ ~0
15 trpc-client-adapter-e2e real @trpc/client with superjson transformer E2E express round-trips Date instances through mutation inputs and outputs 7ms ⚪ ~0

Updated for b51bf23 | Compared against base branch

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

🧠 Cognitive Complexity Report

Metric PR Base Diff
Total complexity 159 159 ⚪ 0
Max function complexity 12 12 ⚪ 0
Functions measured 53 53 ⚪ 0
🧩 Most complex functions
Function Location Complexity Status
serializeZodSchema packages/trpc/generators/zod-serializer.ts:9 12 🟢 OK
generateSchemaContent packages/trpc/generators/schema-generator.ts:58 9 🟢 OK
TrpcContextCreator.extractHttpExceptionMessage packages/trpc/context/trpc-context-creator.ts:467 7 🟢 OK
TrpcHttpAdapter.resolveBody packages/trpc/trpc-http-adapter.ts:124 7 🟢 OK
TrpcRouter.validateSubscriptionOutput packages/trpc/trpc-router.ts:551 7 🟢 OK
(anonymous callback) packages/trpc/context/trpc-context-creator.ts:243 6 🟢 OK
TrpcRouter.assertUniqueAliasPath packages/trpc/trpc-router.ts:436 6 🟢 OK
TrpcRouter.resolveContextId packages/trpc/trpc-router.ts:504 6 🟢 OK
TrpcRouter.createRouterProviderContext packages/trpc/trpc-router.ts:148 5 🟢 OK
(anonymous callback) packages/trpc/trpc-router.ts:320 5 🟢 OK

🧭 Cognitive complexity is reported as a review signal, not a merge gate. Prefer small, intention-revealing refactors when complexity rises.


Updated for b51bf23 | Compared against base branch

@rodrigobnogueira rodrigobnogueira merged commit 6f56dcd into main Jul 5, 2026
10 checks passed
@rodrigobnogueira rodrigobnogueira deleted the chore/mutation-testing branch July 5, 2026 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant