Skip to content

improve test coverage after mutant testing with stryker - #27

Open
pknowles wants to merge 28 commits into
mainfrom
pknowles/mutant_testing
Open

pknowles wants to merge 28 commits into
mainfrom
pknowles/mutant_testing

Conversation

@pknowles

@pknowles pknowles commented Jun 7, 2026

Copy link
Copy Markdown
Owner

No description provided.

pknowles added 28 commits June 6, 2026 22:34
- Move webview Jest tests out of src and into test/webview

- Add testing_makeover_plan.md and refresh the mutation audit baseline

- Route Jest, Stryker, Playwright, and benchmark outputs under test-output

- Add a guarded Stryker runner that rejects unmerged or dirtied tracked state

- Guard test Git helpers so mutating commands only run in temp fixtures

- Exclude test-output from VS Code package contents
…verage

Extracts the private parser to a testable module-level function and adds
deduplication. Tests cover valid blocks, malformed indentation, missing
headers, duplicate paths, and termination lines. Parametrized VS Code
host tests add cherry-pick, revert, rebase-merge, and rebase-apply
conflict-state detection.
…n targets

Tests cover payload shape (file order, labels, commit metadata), merge
behavior (auto-merge, conflict markers, both-added empty base), working
content override, and exact opcode coordinates for clean 3-way merges.
Stubs readConflictState to avoid real filesystem I/O.
Myers getOpcodes tests cover the full fixture matrix (insert/delete/replace
at start/middle/end, empty sides, repeated equal blocks) with exact chunk
coordinates. Differ tests assert merge cache tag classification, conflict
detection, ignoreBlanks blank-line trimming, and locateChunk boundaries —
targeting the 345 surviving mutants in diffutil.ts and myers.ts.
…apping

highlightUtil: exact startLine 1-based offset assertions, exact
startColumn/endColumn for single-char, multi-char, and multi-line
replacements, and negative cases for delete/insert (no sub-highlights).

scrollMapping: exact boundary values at line 0, chunk srcMid→dstMid,
pre/post-chunk gap midpoints, insert/delete/starts-at-zero cases, and
two-chunk gap interpolation — targeting the 35 surviving arithmetic mutants.
Exports compareChunkOrder, assertDiffChunksWellFormed, findTargetChunk
from appHooks.ts. Tests cover chunk ordering, well-formedness validation
(negative length, zero-size, non-monotonic), and navigation wrap-around.

mergedPaneEdits tests cover contentChangeForFullReplacementFromLines
(range shape, endColumn, empty-array throw) and applyMeldStyleContentChanges
(mid-line replace, insert, delete, cross-line merge, newline split,
descending-order multi-edit, out-of-bounds errors).
Adds targeted cases for leading/trailing blank trimming (lo/hi loop
boundaries), replace→insert (A-side trims to empty), replace→delete
(B-side trims to empty), and both-sides-empty chunk elimination.
These target the 90+ surviving mutants in diffutil.ts consumeBlankLines.
Tests drive the four _getAutoMergeTag branches (replace, delete, insert,
conflict) via observable chunk tags, targeting the surviving mutants in
the L733-739 conditional chain that weren't reachable from merge-cache
tag tests alone.
ErrorBoundary: verifies fallback renders on throw, children render on
success, and error message appears in fallback. Uses a helper component
in test/helpers/ to satisfy linter rules.

useClipboardOverrides: covers VS Code path (postMessage with unique
incrementing IDs, resolveClipboardRead resolves promise, unknown ID
no-ops, writeClipboard command shape) and browser fallback path
(navigator.clipboard read/write, rejected read resolves to empty string).

Also marks completed plan items in testing_makeover_plan.md.
…ceLineDecimal

Exports the two pure functions and adds 14 tests covering: syncpoint
clamping to [0,1], syncpoint at top/half-page/bottom boundaries,
monotonicity, binary-search line lookup at exact tops and midpoints,
single-line and variable-height edge cases — targeting the 112
surviving mutants in useSynchronizedScrolling.ts.
Adds range-level assertions for applyChunkEdit (mid-file, EOF, append)
and deleteChunk (mid-file, through-EOF) — targeting off-by-one mutants
in the eL >= mMax branch that content-only tests miss when adjacent
lines produce the same final value.
… invariants

diffPayload opcode tests previously asserted startA/endA values derived
from reading the current merge algorithm output. Replaced with content-
level invariants: every non-equal diff chunk must point to lines that
actually differ between merged and local/remote, which holds for any
valid implementation.

Also adds a clarifying rule to testing-guidelines.md distinguishing
spec-defined exact values (safe to assert) from algorithm-output values
(should be verified via content/semantic invariants).
differ: changeSequence tests verify conflict resolution, line insertion/
deletion creating new diffs, sequential edits, and locateChunk finding
the changed position — targeting the _isChunkChanged and _offsetChunkA/B
boundary mutants (L352-386).

test_matchers: SyncPointMyersSequenceMatcher.getOpcodes tested with
explicit sync points (required to populate splitMatchingBlocks) covering
identical, replace, delete, insert, and reconstruction invariant —
targeting the _addOpcode mutants (L673-677). InlineMyersSequenceMatcher
tested at lengths 2 and 3 to exercise the L507 short-sequence branch.
Exports parseGitDirPointer and adds 14 tests covering getUnresolvedReasons
(clean content, git markers, (??) markers, both types, deduplication,
mid-line non-detection, === and ||||||| markers) and parseGitDirPointer
(absolute path, relative path, multi-segment, whitespace trimming, empty
throws, scheme preservation).

Also adds Uri.with() to the mock vscode Uri class, which was missing and
needed for the absolute-path branch in parseGitDirPointer.
…crollMapping

Adds exact assertions for line exactly at srcMid, just below, and just
above — targeting the <= boundary mutant in _upperBoundMid (L65). Also
adds a reversed-diff (sourceIsA=false) test. Split into a separate
describe to stay within the 100-line function limit.
Exports normalizeWebviewError and adds 8 tests covering: passthrough of
valid strings, fallback title/message substitution when fields are absent
or non-string, details omitted when undefined or non-string, and all-
fallback empty object — targeting the surviving conditional mutants in
the field-type guards (L180-196).
Exports parseCommitBlob, parseCommitLogOutput, parseShaLines and adds
24 unit tests covering: parseShaLines (empty, whitespace, single/multi,
trim), parseCommitBlob (field extraction, subject/message splitting,
multi-parent, root-commit, refs, null files, wrong field count throws),
parseCommitLogOutput (empty, single, multiple records, blank record
skipping), and submoduleConflictUri/parseSubmoduleConflictUri round-trip
and error cases.
Exports statusFromStages and adds 17 tests covering: getGitStatusName
(known codes, fallback for unknown, round-trip consistency),
statusFromStages (all four null/non-null combinations including empty-
string-as-present edge case), and isSupportedScheme (file/vscode-remote
accepted, untitled/internal/unknown rejected).
Tests cover all three classification outcomes: externalEdit (undefined
versionBeforeEdit regardless of new version), suppress (version +1
exactly, including the zero boundary), and fullSync (version +2 or
greater, or no increment). Targets the boundary mutants in the version
arithmetic that controls echo suppression vs resync.
getGitStatusName returns gitStatusNames[i] - testing that a lookup table
returns what you put in has no failure mode. Remove the 7-test suite.

parseShaLines: 5 tests for 4 lines of code; the single-SHA and
whitespace-only cases were fully covered by empty+multi+trim. Keep 2.

isSupportedScheme: collapse 5 tests to 2 (one accept, one reject).
Documents that Stryker only measures the Jest half of the codebase.
The VS Code integration tests (~4000 lines) exercise meldWebviewPanel,
repoContext, treeView etc. but produce no coverage metrics.

Adds a concrete setup for NODE_V8_COVERAGE + c8 to get verifiable VS
Code host coverage, notes the exit-before-flush timing issue to solve,
and records the actual high-risk gaps (completeMerge path, contentChanged
queue ordering) rather than chasing mutation scores in VS Code-coupled code.

Strengthens the Definition of Done with the "what breaks for the user?"
gate to prevent padding tests for trivial lookup functions.
NODE_V8_COVERAGE + c8 gives real line coverage for src/ files loaded
directly by the VS Code test process (treeView 91%, repoContext 48%,
gitUtils 61%, submoduleConflict 28%). meldWebviewPanel.ts and the
webview/ files are not reachable this way because the extension
activation path runs in a sandboxed Electron sub-process that does
not inherit NODE_V8_COVERAGE.

Documents what was actually found from the spike, and lists three
options for closing the meldWebviewPanel coverage gap (Istanbul
instrumentation, manual gap analysis, or @vscode/test-cli --coverage).
Replaces the previous Jest-only coverage ratchet with a single entry
point (npm run coverage / scripts/collect_coverage.ts) that:
- Runs Jest and VS Code integration tests in order
- Uses a fresh mkdtempSync raw dir under test-output/coverage/ for V8
  JSON so stale data from prior runs is never mixed in
- Deletes stale output LCOVs before each generation step
- Merges the two exact LCOV files via mergeCoverageReportFiles API
- Ratchets Jest thresholds from coverage-summary.json (Jest-only)
- Enforces and ratchets combined thresholds via coverage.config.json

Splits ratchet_coverage.ts into three exported functions with void
return (throw on failure): ratchetJestCoverage, ratchetCombinedCoverage,
ratchetStrykerScore. Stryker ratcheting is now only triggered by
npm run test:mutate via ratchet_mutation.ts, never by a coverage run.
- Extract Jest coverage thresholds into jest.coverage.config.json so
  ratchetJestCoverage() can do a clean JSON round-trip instead of regex
  surgery on jest.config.js
- Simplify LCOV parser: replace [key, offset] tuple table with a direct
  prefix→key lookup; use indexOf(":") instead of hardcoded offsets
- Skip config writes in ratchetJestCoverage and ratchetCombinedCoverage
  when thresholds are unchanged, avoiding spurious git diffs
- Replace execFileSync("env", ["-u", ...]) with Node env option to unset
  ELECTRON_RUN_AS_NODE, making collect_coverage.ts platform-neutral
- include restored-tabs and browser webview integration LCOV in combined coverage

- rename Playwright e2e tests to webview-integration

- instrument browser webview bundle with Istanbul and document coverage flow
Share the browser coverage env var between the runner and Playwright fixture.

Fail loudly when browser coverage is missing or malformed, and ignore non-file raw coverage entries during LCOV generation.

Document the multiple-build coverage flow and why the custom Istanbul path is used for browser webview coverage.
Add focused Jest tests for tree provider error isolation, mismatch warnings, MERGE_MSG resolved rows, row metadata, and event behavior.

Document the coverage backlog and ratchet Jest/combined coverage thresholds after the successful pre-checkin run.
Cover extension command behavior through activate() and captured mocked VS Code commands.

Upgrade the VS Code test mock with resettable command, UI, document, editor, progress, and configuration helpers.

Include extension.ts in Jest coverage, ratchet coverage thresholds, and fix a webview integration timing wait.
@github-actions

Copy link
Copy Markdown

Coverage report

St.
Category Percentage Covered / Total
🟢 Statements
81.69% (+7.72% 🔼)
3560/4358
🟡 Branches
70.88% (+7.64% 🔼)
1638/2311
🟢 Functions
82.6% (+9.42% 🔼)
655/793
🟢 Lines
81.59% (+7.85% 🔼)
3480/4265
Show new covered files 🐣
St.
File Statements Branches Functions Lines
🟢 extension.ts 85.32% 71.67% 94.57% 85.23%

Test suite run success

507 tests passing in 46 suites.

Report generated by 🧪jest coverage report action from 89dba11

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