Skip to content

Close the dotnet-test skill-coverage gaps from the PR 945 report#949

Open
Evangelink wants to merge 1 commit into
dev/amauryleve/dotnet-test-eval-followupsfrom
dev/amauryleve/close-dotnet-test-coverage-gaps
Open

Close the dotnet-test skill-coverage gaps from the PR 945 report#949
Evangelink wants to merge 1 commit into
dev/amauryleve/dotnet-test-eval-followupsfrom
dev/amauryleve/close-dotnet-test-coverage-gaps

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

The skill coverage report on #945 flagged roughly 190 uncovered teaching points across 9 dotnet-test skills, 7 of them at 0%. Reproducing it locally showed those skills all report Evidence items: 0, so most of that number was a measurement artifact rather than a real gap.

eng/skill-coverage/Measure-SkillCoverage.ps1 parses an eval schema this repo does not use. It looks for assertions: blocks with sibling pattern:/value: keys, but all 97 tests/**/eval.yaml files use graders: with a nested config: map. It also only captured rubric entries written as single-line quoted scalars, while nearly every rubric item here is an unquoted plain scalar wrapped across lines. The tool therefore found no evidence at all and reported every teaching point as uncovered. Writing ~190 assertions to satisfy that would have produced exactly the overfitting eng/skill-validator/src/docs/OverfittingDetection.md warns about.

1. Fix the measurement. Get-EvalEvidence is rewritten as an indentation-driven parser that reads the real spec shape: graders with nested config (pattern, substring, value, command, stdout_contains, stdout_matches, and path for file-exists graders), plus block and folded scalars for both grader values and rubric items. Literal values are regex-escaped before code-pattern matching so a substring is not mistakenly treated as a regex. This alone moved the 9 skills from 0-33% to 82-100%.

2. Close the 24 points that were genuinely uncovered. All 9 skills now sit at 100%:

  • detect-static-dependencies: new accounting-discipline stimulus for file:line locations, one authoritative total, and pure helpers such as Path.Combine excluded from the needs-wrapping total.
  • migrate-static-to-wrapper: new with-tests fixture (a custom IClock seam plus an MSTest project) and a stimulus covering the required using directive, test doubles in the updated tests, and scope discipline.
  • test-smell-detection: wires up the orphaned skip-and-magic fixture, which was committed but had no stimulus referencing it and was missing its production class. Covers reasoned vs bare skips, contextually obvious numbers, justified severities, and concrete fix examples.
  • test-tagging: wires up the orphaned go-report-only fixture for the report-only "no source files modified" rule, plus a grader for the NUnit [Category] attribute.
  • assertion-quality, test-anti-patterns, test-gap-analysis: rubric items for metric arithmetic, per-finding locations, severity prioritisation, empirical survivor confirmation, mutation category labels, and settled verdicts.

3. Repair a broken fixture found on the way. Three crap-score stimuli reference fixtures/refactor-required/coverage.cobertura.xml, which never landed because .gitignore's coverage*.xml rule silently swallowed it. The file is added, fixture coverage reports are un-ignored, and two rubric numbers are aligned with what the file actually records.

Worth a careful look

Related issue

Follows up the coverage report on #945.

Validation

  • Measure-SkillCoverage.ps1 -All -Format Json cross-checked against a real YAML parser (PyYAML) computing expected evidence counts from the same grader/rubric rules: 0 mismatches across all 73 skills that have an eval spec.
  • All 97 tests/**/eval.yaml files parse.
  • All 614 fixture src: references resolve. Before this change 3 were missing (the crap-score Cobertura file).
  • dotnet test Billing.Tests on the new with-tests fixture: 3 passed, 0 failed.
  • dotnet build Inventory.Tests on the repaired skip-and-magic fixture: build succeeded, 0 warnings, 0 errors. Build artifacts and the temporary global.json used to bypass the repo-root MTP runner setting were removed afterwards.
  • Extract-MethodCoverage.ps1 against the new Cobertura fixture returns the intended values (ApplySurcharges 60% / complexity 14, ClassifyAccount 63.2% / complexity 17, RoundToCurrency 100% / complexity 3).
  • Final coverage for the 9 reported skills: all 100%.
  • skill-validator check could not run: building it downloads @github/copilot-win32-x64 from npmjs and the sandbox blocks that TLS handshake. No plugins/** content changed in this PR, so its checks are unaffected.

Checklist

  • I searched existing issues and pull requests to avoid duplicates.
  • I kept this pull request focused and avoided unrelated refactors.
  • I added or updated tests, evals, or documentation when changing skill or agent behavior.
  • I updated CODEOWNERS when adding or moving owned content. (N/A - no owned content moved)
  • I updated all marketplace manifests when plugin metadata changed. (N/A - no plugin metadata changed)
  • I updated eng/known-domains.txt for any new external domains referenced by skill content. (N/A - no new external domains)

The coverage comment reported 0% for seven dotnet-test skills. Most of
that was a measurement artifact: Measure-SkillCoverage.ps1 parses an
eval schema that does not exist in this repo. It looks for `assertions:`
blocks with sibling `pattern:`/`value:` keys, but all 97 tests/**/eval.yaml
files use `graders:` with a nested `config:` map, and it only captured
rubric entries that were single-line quoted scalars while nearly every
rubric item here is an unquoted plain scalar wrapped across lines. The
result was `Evidence items: 0` and every teaching point reported as
uncovered.

Rewrite Get-EvalEvidence as an indentation-driven parser that reads the
real shape: graders with nested config (pattern, substring, value,
command, stdout_contains, stdout_matches, and path for file-exists
graders), plus block and folded scalars for both grader values and
rubric items. Literal values are regex-escaped before code-pattern
matching so a substring is not treated as a regex. Cross-checked against
a real YAML parser: evidence counts now agree exactly for all 73 skills
that have an eval spec.

With the measurement fixed the true gaps were 24 teaching points, all of
which are now covered:

- detect-static-dependencies: new accounting-discipline stimulus for
  file:line locations, one authoritative total, and pure helpers such as
  Path.Combine excluded from the needs-wrapping total.
- migrate-static-to-wrapper: new with-tests fixture (custom IClock seam
  plus an MSTest project) and a stimulus covering the required using
  directive, test doubles in the updated tests, and scope discipline.
- test-smell-detection: wired up the orphaned skip-and-magic fixture
  (added its missing production class) to cover reasoned vs bare skips,
  contextually obvious numbers, justified severities, and concrete fixes.
- test-tagging: wired up the orphaned go-report-only fixture for the
  report-only no-source-edits rule, plus a grader for the NUnit
  [Category] attribute.
- assertion-quality, test-anti-patterns, test-gap-analysis: rubric items
  for metric arithmetic, per-finding locations, severity prioritisation,
  empirical survivor confirmation, mutation category labels, and settled
  verdicts.

Also fix crap-score, whose refactor-required stimuli referenced a
coverage.cobertura.xml that .gitignore silently swallowed via
`coverage*.xml`. Add the fixture, un-ignore fixture coverage reports, and
align the two rubric numbers with what the file records (60% line
coverage, complexity 14, CRAP ~26).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c217f3c4-fd5a-4ede-bbc6-5d916c1182e6
Copilot AI review requested due to automatic review settings July 27, 2026 08:24
@Evangelink
Evangelink changed the base branch from main to dev/amauryleve/dotnet-test-eval-followups July 27, 2026 08:24
@github-actions

Copy link
Copy Markdown
Contributor

Skill Coverage Report

Plugin Skill Covered Coverage
dotnet-test code-testing-agent 3/3 100%
dotnet-test crap-score 6/6 100%
dotnet-test detect-static-dependencies 22/22 100%
dotnet-test migrate-static-to-wrapper 26/26 100%
dotnet-test test-anti-patterns 25/25 100%
dotnet-test test-gap-analysis 30/30 100%
dotnet-test test-smell-detection 26/26 100%
dotnet-test assertion-quality 22/22 100%
dotnet-test test-tagging 28/28 100%

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes eng/skill-coverage/Measure-SkillCoverage.ps1 so it can correctly extract evidence from this repo’s tests/**/eval.yaml format (graders + nested config + wrapped rubric scalars), then uses that corrected measurement to close remaining genuine coverage gaps across several dotnet-test skills. It also repairs a missing Cobertura fixture file by narrowing .gitignore exclusions for checked-in test inputs.

Changes:

  • Rewrote Get-EvalEvidence in Measure-SkillCoverage.ps1 to parse the repo’s actual eval spec shape (graders/config + multiline scalars) and treat literal grader values as literals during pattern matching.
  • Added/updated multiple dotnet-test eval stimuli/rubrics and fixtures to cover previously-unmeasured or genuinely-uncovered teaching points.
  • Added a missing coverage.cobertura.xml fixture and adjusted .gitignore to allow checked-in coverage reports under tests/**/fixtures/**.
Show a summary per file
File Description
tests/dotnet-test/test-tagging/eval.yaml Adds graders for NUnit [Category] evidence and adds a Go “report-only” stimulus ensuring no source modifications.
tests/dotnet-test/test-smell-detection/fixtures/skip-and-magic/Inventory/InventoryService.cs Adds missing production class for the skip-and-magic fixture.
tests/dotnet-test/test-smell-detection/fixtures/skip-and-magic/Inventory/Inventory.csproj Adds the Inventory project to support the fixture.
tests/dotnet-test/test-smell-detection/fixtures/skip-and-magic/Inventory.Tests/Inventory.Tests.csproj Adds a project reference from tests to Inventory so it builds.
tests/dotnet-test/test-smell-detection/eval.yaml Adds a new stimulus/rubric emphasizing nuanced smell classification and concrete fixes.
tests/dotnet-test/test-gap-analysis/eval.yaml Strengthens rubric requirements around empirical survivor confirmation and prioritization.
tests/dotnet-test/test-anti-patterns/eval.yaml Strengthens rubric requirements around per-finding location and consistent counting/prioritization.
tests/dotnet-test/migrate-static-to-wrapper/fixtures/with-tests/Billing/Services/SubscriptionService.cs Adds a fixture class that still uses DateTime.UtcNow as the migration target.
tests/dotnet-test/migrate-static-to-wrapper/fixtures/with-tests/Billing/Services/InvoiceService.cs Adds a fixture class intentionally left on the static clock for scope-discipline grading.
tests/dotnet-test/migrate-static-to-wrapper/fixtures/with-tests/Billing/Billing.csproj Adds Billing project for the with-tests fixture.
tests/dotnet-test/migrate-static-to-wrapper/fixtures/with-tests/Billing/Abstractions/SystemClock.cs Adds a production SystemClock : IClock implementation for the seam.
tests/dotnet-test/migrate-static-to-wrapper/fixtures/with-tests/Billing/Abstractions/IClock.cs Adds an IClock seam used by the migration stimulus.
tests/dotnet-test/migrate-static-to-wrapper/fixtures/with-tests/Billing.Tests/SubscriptionServiceTests.cs Adds MSTest coverage for the fixture’s SubscriptionService.
tests/dotnet-test/migrate-static-to-wrapper/fixtures/with-tests/Billing.Tests/Billing.Tests.csproj Adds MSTest project and project reference to Billing.
tests/dotnet-test/migrate-static-to-wrapper/eval.yaml Adds a new stimulus enforcing scope discipline + required using + test double usage.
tests/dotnet-test/detect-static-dependencies/eval.yaml Adds a new stimulus enforcing one authoritative total, file:line locations, and pure helper exclusions.
tests/dotnet-test/crap-score/fixtures/refactor-required/coverage.cobertura.xml Adds the missing Cobertura XML test input file.
tests/dotnet-test/crap-score/eval.yaml Aligns rubric numbers with the checked-in Cobertura values.
tests/dotnet-test/assertion-quality/eval.yaml Tightens rubric around metric arithmetic and avoiding manufactured problems.
eng/skill-coverage/Measure-SkillCoverage.ps1 Replaces the old eval parser with an indentation-driven grader/rubric parser for real evidence extraction.
.gitignore Narrowly un-ignores tests/**/fixtures/**/coverage* so fixture coverage files can be committed.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 20/21 changed files
  • Comments generated: 1

Comment on lines +301 to +310
function Remove-YamlQuoting([string]$text) {
$t = $text.Trim()
if ($t.Length -ge 2 -and $t.StartsWith('"') -and $t.EndsWith('"')) {
return ($t.Substring(1, $t.Length - 2) -replace '\\\\', '\')
}
if ($t.Length -ge 2 -and $t.StartsWith("'") -and $t.EndsWith("'")) {
return $t.Substring(1, $t.Length - 2)
}
return $t
}
@github-actions github-actions Bot added the waiting-on-author PR state label label Jul 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

👋 @Evangelink — this PR has 1 unresolved review thread(s),merge conflict. When you're ready, please address the feedback and push an update; the triage bot will pick up the next state automatically. (Add the no-stale label to silence further pings.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting-on-author PR state label

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants