Close the dotnet-test skill-coverage gaps from the PR 945 report#949
Conversation
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
Skill Coverage Report
|
There was a problem hiding this comment.
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-EvalEvidenceinMeasure-SkillCoverage.ps1to 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-testeval stimuli/rubrics and fixtures to cover previously-unmeasured or genuinely-uncovered teaching points. - Added a missing
coverage.cobertura.xmlfixture and adjusted.gitignoreto allow checked-in coverage reports undertests/**/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
| 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 | ||
| } |
|
👋 @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 |
Summary
The skill coverage report on #945 flagged roughly 190 uncovered teaching points across 9
dotnet-testskills, 7 of them at 0%. Reproducing it locally showed those skills all reportEvidence items: 0, so most of that number was a measurement artifact rather than a real gap.eng/skill-coverage/Measure-SkillCoverage.ps1parses an eval schema this repo does not use. It looks forassertions:blocks with siblingpattern:/value:keys, but all 97tests/**/eval.yamlfiles usegraders:with a nestedconfig: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 overfittingeng/skill-validator/src/docs/OverfittingDetection.mdwarns about.1. Fix the measurement.
Get-EvalEvidenceis rewritten as an indentation-driven parser that reads the real spec shape: graders with nested config (pattern,substring,value,command,stdout_contains,stdout_matches, andpathfor 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 forfile:linelocations, one authoritative total, and pure helpers such asPath.Combineexcluded from the needs-wrapping total.migrate-static-to-wrapper: newwith-testsfixture (a customIClockseam plus an MSTest project) and a stimulus covering the requiredusingdirective, test doubles in the updated tests, and scope discipline.test-smell-detection: wires up the orphanedskip-and-magicfixture, 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 orphanedgo-report-onlyfixture 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-scorestimuli referencefixtures/refactor-required/coverage.cobertura.xml, which never landed because.gitignore'scoverage*.xmlrule 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
Read-YamlScalarand the section-tracking loop is welcome..gitignorenegation is deliberately narrow (tests/**/fixtures/**/coverage*) so real coverage output stays ignored everywhere else.dev/amauryleve/dotnet-test-eval-followups(Fix dotnet-test findings from the refreshed cross-family eval (#899) #945) and targets that branch, so it shows only the one commit. It should merge after Fix dotnet-test findings from the refreshed cross-family eval (#899) #945.Related issue
Follows up the coverage report on #945.
Validation
Measure-SkillCoverage.ps1 -All -Format Jsoncross-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.tests/**/eval.yamlfiles parse.src:references resolve. Before this change 3 were missing (thecrap-scoreCobertura file).dotnet test Billing.Testson the newwith-testsfixture: 3 passed, 0 failed.dotnet build Inventory.Testson the repairedskip-and-magicfixture: build succeeded, 0 warnings, 0 errors. Build artifacts and the temporaryglobal.jsonused to bypass the repo-root MTP runner setting were removed afterwards.Extract-MethodCoverage.ps1against the new Cobertura fixture returns the intended values (ApplySurcharges 60% / complexity 14, ClassifyAccount 63.2% / complexity 17, RoundToCurrency 100% / complexity 3).skill-validator checkcould not run: building it downloads@github/copilot-win32-x64from npmjs and the sandbox blocks that TLS handshake. Noplugins/**content changed in this PR, so its checks are unaffected.Checklist
eng/known-domains.txtfor any new external domains referenced by skill content. (N/A - no new external domains)