Skip to content

feat(tests): add Stryker mutation testing to VS Code extension#602

Merged
rajbos merged 5 commits intomainfrom
rajbos/add-mutation-testing
Apr 12, 2026
Merged

feat(tests): add Stryker mutation testing to VS Code extension#602
rajbos merged 5 commits intomainfrom
rajbos/add-mutation-testing

Conversation

@rajbos
Copy link
Copy Markdown
Owner

@rajbos rajbos commented Apr 12, 2026

Summary

Adds Stryker Mutator mutation testing to the VS Code extension to measure test suite quality beyond code coverage.

What changed

vscode-extension/stryker.config.mjs (new)

  • Uses the command test runner (compatible with Node.js built-in node:test)
  • Mutates compiled JS in out/src/ — avoids a TypeScript recompile step per mutant
  • Targets 7 core logic files: tokenEstimation, sessionParser, maturityScoring, usageAnalysis, and utils/*
  • Explicit test file list (no shell globs) for cross-platform safety
  • coverageAnalysis: off, concurrency: 2, timeoutMS: 15000
  • break: 0 — informational during initial rollout, won't block merging
  • HTML report → reports/mutation/report.html

vscode-extension/package.json

  • Added @stryker-mutator/core ^9.6.1 devDependency
  • Added test:mutation script: npm run compile-tests && npx stryker run

.github/workflows/ci.yml

  • New mutation-testing job:
    • Runs only on PRs (not on pushes to main)
    • Depends on build job (tests must pass first)
    • continue-on-error: true — non-blocking during rollout
    • Hard cap: timeout-minutes: 20
    • Uploads HTML report as artifact (14-day retention)

.gitignore

  • Added .stryker-tmp and reports/mutation/

How to run locally

cd vscode-extension
npm run test:mutation
# Opens reports/mutation/report.html for a visual breakdown

Notes

  • Scope is intentionally focused on pure-logic files. extension.ts, webview/, and backend/ (Azure SDK) are excluded from this initial rollout.
  • The break: 0 threshold means the job reports scores but never fails. Once baseline scores are known, raise the threshold.

@rajbos rajbos force-pushed the rajbos/add-mutation-testing branch from 984e419 to ea1ec78 Compare April 12, 2026 10:38
rajbos and others added 5 commits April 12, 2026 18:41
- Install @stryker-mutator/core v9.6.1 as a devDependency
- Add stryker.config.mjs targeting compiled JS in out/src/ to avoid
  a TypeScript recompile step per mutant:
  - Mutates 7 core logic files (tokenEstimation, sessionParser,
    maturityScoring, usageAnalysis, utils/*)
  - Runs 9 explicit unit test files (no shell globs for cross-platform safety)
  - coverageAnalysis: off with command runner (node:test built-in)
  - concurrency: 2, timeoutMS: 15000
  - Threshold break: 0 (informational during rollout)
  - HTML report written to reports/mutation/report.html
- Add test:mutation npm script: compile-tests then npx stryker run
- Add mutation-testing CI job in ci.yml:
  - Only runs on pull_request events (not push to main)
  - Depends on build job (tests must pass first)
  - continue-on-error: true to keep it non-blocking
  - Hard cap at 20 minutes
  - Uploads HTML report artifact (14-day retention)
- Add .stryker-tmp and reports/mutation/ to .gitignore

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ssue

Stryker by default copies only git-tracked files to its sandbox.
Since \out/\ is gitignored, the compiled test files and vscode-shim
were missing from the sandbox, causing every test command to hang
until Stryker's per-mutant timeout was reached.

Setting inPlace:true makes Stryker mutate the compiled JS files
directly in the working directory (no sandbox), which works correctly
since npm run compile-tests already runs before npx stryker run.
Stryker still backs up the originals in .stryker-tmp before each
mutation and restores them afterwards.

Verified locally: html.js run completed in 5s with 0 timeouts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…on-error

Job-level continue-on-error keeps the CI workflow green but still marks
the mutation-testing job check as FAILURE. Adding continue-on-error at
the step level ensures the job itself succeeds even when Stryker times
out, so the check shows SUCCESS and doesn't block PR merges.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove usageAnalysis.js (1905 lines) and maturityScoring.js (1212 lines)
from the mutate list — together they generate ~5000+ mutations and push
total run time well past the 20-minute CI timeout.

Keep the focused utility files (tokenEstimation, sessionParser, dayKeys,
errors, html) which produce a manageable ~800 mutations.

Also increase concurrency 2→4 to cut run time roughly in half.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace coactions/setup-xvfb (abandoned, Node.js 20 only) with manual
  xvfb install+start to eliminate the Node.js deprecation warning
- Add 'json' reporter to stryker.config.mjs so step summary has data
- Add 'Publish mutation summary' step that writes a markdown table to
  GITHUB_STEP_SUMMARY from mutation.json (with fallback when missing)
- Add if-no-files-found: ignore to mutation report upload so the step
  does not error when Stryker times out before writing the report

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rajbos rajbos force-pushed the rajbos/add-mutation-testing branch from 486a8b8 to bbe70fa Compare April 12, 2026 16:45
@rajbos rajbos merged commit 7e370cc into main Apr 12, 2026
21 of 23 checks passed
@rajbos rajbos deleted the rajbos/add-mutation-testing branch April 12, 2026 17:12
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