Evaluate PR Tests
dotnet/maui
Reviews the tests added in a pull request for fix coverage, quality, edge cases and test type, and recommends lighter test types where they would do.
Pseudo-mutation analysis ONLY: answer whether tests would catch a bug if production code changed, which meaningful changes would still pass, or which caller-visible mutations existing assertions…
$ npx skills add dotnet/skills --skill test-gap-analysis -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install dotnet/skills test-gap-analysis --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/dotnet-test/skills/test-gap-analysis .claude/skills/test-gap-analysis && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "test-gap-analysis" agent skill from https://github.com/dotnet/skills/tree/main/plugins/dotnet-test/skills/test-gap-analysis into .claude/skills/test-gap-analysis/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "test-gap-analysis", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/dotnet/skills/tree/main/plugins/dotnet-test/skills/test-gap-analysisType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add dotnet/skills --skill test-gap-analysis -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install dotnet/skills test-gap-analysis --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/dotnet-test/skills/test-gap-analysis .agents/skills/test-gap-analysis && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "test-gap-analysis" agent skill from https://github.com/dotnet/skills/tree/main/plugins/dotnet-test/skills/test-gap-analysis into .agents/skills/test-gap-analysis/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "test-gap-analysis", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add dotnet/skills --skill test-gap-analysis -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install dotnet/skills test-gap-analysis --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/dotnet-test/skills/test-gap-analysis .cursor/skills/test-gap-analysis && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "test-gap-analysis" agent skill from https://github.com/dotnet/skills/tree/main/plugins/dotnet-test/skills/test-gap-analysis into .cursor/skills/test-gap-analysis/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "test-gap-analysis", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/dotnet/skills.git --path plugins/dotnet-test/skills/test-gap-analysis--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add dotnet/skills --skill test-gap-analysis -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install dotnet/skills test-gap-analysis --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/dotnet-test/skills/test-gap-analysis .gemini/skills/test-gap-analysis && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "test-gap-analysis" agent skill from https://github.com/dotnet/skills/tree/main/plugins/dotnet-test/skills/test-gap-analysis into .gemini/skills/test-gap-analysis/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "test-gap-analysis", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install dotnet/skills test-gap-analysisInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add dotnet/skills --skill test-gap-analysis -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/dotnet-test/skills/test-gap-analysis .github/skills/test-gap-analysis && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "test-gap-analysis" agent skill from https://github.com/dotnet/skills/tree/main/plugins/dotnet-test/skills/test-gap-analysis into .github/skills/test-gap-analysis/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "test-gap-analysis", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add dotnet/skills --skill test-gap-analysis -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install dotnet/skills test-gap-analysis --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dotnet/skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/dotnet-test/skills/test-gap-analysis .opencode/skills/test-gap-analysis && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "test-gap-analysis" agent skill from https://github.com/dotnet/skills/tree/main/plugins/dotnet-test/skills/test-gap-analysis into .opencode/skills/test-gap-analysis/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "test-gap-analysis", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
test-gap-analysisPseudo-mutation analysis ONLY: answer whether tests would catch a bug if production code changed, which meaningful changes would still pass, or which caller-visible mutations existing assertions…
Test Gap Analysis is an agent skill from dotnet/skills, published by the product's own GitHub organization. Pseudo-mutation analysis ONLY: answer whether tests would catch a bug if production code changed, which meaningful changes would still pass, or which caller-visible mutations existing assertions would miss; verify candidates when requested, then optionally close verified gaps. Activate for behavioral blind spots or missing edge cases tied to production behavior. Polyglot. DO NOT USE FOR: suite organization, taxonomy, metadata, or distribution reports (test-tagging); .NET line-vs-branch or Cobertura…
Its SKILL.md is about 4.5k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/mutation-catalog.md`).
It sits in Testing & QA, covering Test coverage. It works with .NET. The repository describes itself as: Repository for skills to assist AI coding agents with .NET and C. The licence is MIT.
7 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 8d670fa. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
dotnetFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Test Gap Analysis loads about 4.5k tokens when it runs, and up to ~5.4k if it reads all its reference files. Until then it costs about 200 tokens; SKILL.md has 2,345 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from dotnet/skills at commit 8d670fa, republished under its MIT licence (© dotnet). 2,345 words, ~4,463 tokens.
.claude/skills/test-gap-analysis/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.Answer one question: which caller-visible production behaviors could change without an existing test failing? Mutation reasoning is a probe, not the goal. Inventory public outcomes first, then verify only credible gaps.
Discover production and test files from manifests and file types. After a narrow search misses, inspect the current directory broadly before asking for paths.
| Request | Action |
|---|---|
| One component or named risk | Inventory every high-risk public outcome in scope; do not edit production code unless verification was requested |
| General small-component review | Inventory distinct outcomes and report caller-visible gaps from source/assertion mapping |
| Explicit survivor verification | Inventory all requested outcomes; execute one representative observable candidate for each distinct high-risk outcome under verification, then classify it as Survived or Killed |
| Explicit exhaustive audit | Read references/mutation-catalog.md and classify all meaningful candidates |
| Add tests to an existing suite | Analyze first; add tests only for verified survivors or demonstrated no-coverage outcomes |
| Create a new suite | Stop and use code-testing-agent |
When the request names a risk, turn it into a one-line public-outcome allowlist
before reading code. An outcome is not in scope merely because the same method writes it.
For money math, allow computed or returned amounts, rates, tier/boundary
choice, percentage base/order, floors/caps, and rounding; exclude non-monetary
state predicates (including derived booleans), identity, and formatting. Private
code is in scope only to trace an allowed outcome.
Do not expand a focused request into a repository audit, plan artifact, or
dashboard. Use source and tests directly for familiar frameworks. Invoke
test-analysis-extensions only when discovery or assertion semantics are
unclear.
Run the narrowest existing test command once. Choose it from the project
manifest; Microsoft.Testing.Platform executables may require dotnet run.
Confirm tests executed: exit 0 with build-only output is not green. If that one
attempt cannot run the suite, do not troubleshoot the runner or try alternate
commands for an advisory review; continue statically and label all candidates
unverified. Do not infer a project-configuration cause from missing output;
name a cause only when the command reports it.
Missing runner output limits only claims of empirical mutation survival. It does not make source-proven facts tentative: a public outcome with no reaching test is still No coverage, and an exact expected value derived from the unmodified implementation is still actionable. State the baseline limitation once, then give the static source/assertion conclusion directly instead of hedging every row.
For an advisory review such as "would tests catch this?", stop execution after that baseline. Source-to-assertion mapping is sufficient evidence for No coverage and Candidate survivor (unverified). Trace or run the unmodified code once only when an original value is unclear. Apply mutations only for explicit verification, an exhaustive audit, or closing gaps with tests.
Any focused mutation budget limits execution, not discovery. Keep every distinct unasserted public outcome in the inventory.
For each public entry point, map:
Use public input/sequence -> expected outcome -> existing assertion -> gap.
One asserted return field does not cover another. One allowed result does not
cover its denial.
Money math: inventory the no-op path, every rate/tier and exact boundary, operation order, percentage base or composition, floor/cap, and rounding. Trace private helpers through the public result. A test asserting only a broad range does not pin any exact amount. For each actionable money row, derive one witness input and its exact original result through the complete call chain; do not recommend a generic "assert the exact amount" without supplying that amount.
Ordered guards and retries: inventory invalid below minimum | first valid | last allowed or retryable | first blocked | later blocked. For an upper guard
such as value >= limit, use limit - 1, limit, and limit + 1; the last
witness exposes narrowing to value == limit. Inventory every accepted and
rejected error class. When type matching is polymorphic, include a representative
derived accepted type that would expose exact-runtime-type narrowing. A test at
the first blocked value does not protect the last allowed or later blocked value.
Authorization: enumerate each relevant identity/role, resource class, and
action from the caller's view. Untested false, forbidden, and unchanged-role
outcomes are first-class security gaps. Do not analyze variants of an allowed
path while a denial outcome remains uninventoried. Check each public surface:
Reserve execution for wholly untested public branches before another variant of a partially covered helper. If more than five high-risk behaviors are unasserted, execute the top 3-5 and keep the rest visible as No coverage or Candidate survivor (unverified).
Execution never replaces the ledger. Before mutating or answering, classify every required outcome, including each invalid input, guard boundary, classifier arm, action, and denial.
Completeness checkpoint: before selecting findings, explicitly account for
every independent mode/flag, both zero and negative for a <= 0 guard, every
accepted exception class, and a representative derived accepted exception when
matching is polymorphic. For a removed guard, trace the fallthrough: if it still
produces the same public exception type, it is equivalent unless finer exception
metadata is an established contract.
First replay each exact mutation against every existing asserted input or sequence with all arguments fixed. Any changed return, exception, state, or side effect is Likely killed; a dedicated single-purpose test is unnecessary. Never compare the mutant on one input with the original on another.
For survivors, choose a witness before execution or reporting and state
witness -> original observation -> mutant observation. Reuse it in the
smallest test. Admit it only when the last two differ publicly after tracing the
full call chain; otherwise choose a distinguishing witness or drop it.
Exclude:
ParamName metadata, or other semantics
not established by the current contract, source intent, or tests;result < floor ? floor : result to <= is equivalent at
equality because both branches return floor;Missing direct assertions do not prove No coverage: first trace existing assertions through public callers and shared branches. Missing assertions make an observable candidate a survivor; they do not make an inert mutation meaningful.
Rank: (1) security denials, financial outcomes, errors, and state changes; (2) wholly unasserted public outcomes; (3) boundaries or exact values reached by weak assertions; (4) alternate variants of already-asserted behavior.
Finish the inventory before selecting mutations or a verdict. One killed attempt, exception type, or switch arm does not clear its siblings.
Choose the verdict from the completed inventory:
A handful of validation gaps does not make an otherwise broad suite Mixed unless validation is the named risk or the gaps threaten security, data, or other contract-critical behavior.
When the inventory meets the Strong criteria above, lead with Strong and
name the protected boundaries and dual assertions before listing minor gaps. Do
not open with Mixed, "only core paths", or a risk-heavy dashboard.
Stop when existing assertions kill the remaining candidates or no credible public survivor remains. Do not mutate every operator merely to fill a report or calculate a score.
| Result | Meaning |
|---|---|
| Likely killed | An existing assertion observes the changed outcome |
| Candidate survivor (unverified) | Observable change appears unasserted; not executed |
| Survived | Exact observable mutation executed and tests stayed green |
| No coverage | No test reaches the public outcome; report the missing branch without inventing a survivor |
| Equivalent | No public observation changes; omit from findings |
Outside explicit verification, an exhaustive audit, or a requested test addition, execute no mutations. Do not mutate to confirm obvious no coverage. For explicit verification, execute one representative candidate per distinct high-risk outcome in scope; do not stop after the first one or two while another guard, action branch, error class, or denial remains unclassified. Omit equivalent syntax variants.
Enter this phase only for explicit verification, an exhaustive audit, or a requested test addition.
Never leave mutations in the workspace. Before reporting, reconcile every unasserted high-risk outcome as Survived, Candidate survivor (unverified), No coverage, or omitted Equivalent. Stop when no credible public gap remains; do not fill a report with internal details or calculate a score unless the user requested an exhaustive audit.
Scale the response to the request.
For focused or small analysis, return:
A one-line verdict: Strong, Mixed, or Weak, with the reason.
For a Strong suite, one short strengths sentence naming the concrete protected boundaries, guards, or paired observations that justify the verdict.
One compact row per actionable Survived, Candidate survivor (unverified), or No coverage outcome. Before adding a row, apply the outcome allowlist when the request names a risk, then apply the observable-candidate rules; omit any candidate that fails either filter. Include every high-risk outcome, use one row per distinct public outcome, and consolidate only related low-risk variants:
| Risk | Public outcome | Change | Result/evidence | Smallest test |
|---|
Every gap needs a distinguishing witness and a concrete smallest test. An error-path gap must name an invalid input and the expected error/result.
For a Mixed or Weak suite, one short strengths sentence naming important killed behavior.
When the request names exclusions, one short scope sentence naming the generated, trivial, or unrelated code intentionally skipped.
Do not repeat the table in prose or report discarded mutants, tool chronology, or in-flight reasoning.
For an exhaustive audit, add counts for Killed / Survived / No coverage / Equivalent and group findings by risk. Count only executed or definitively classified candidates.
For test additions, name the tests added, the verified mutations they kill, and the successful final command.
? propagation versus panic
is observable behavior; in C#, exception type and whether an input guard
accepts or rejects a value are observable behavior.© dotnet, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file (references) in plugins/dotnet-test/skills/test-gap-analysis of dotnet/skills.
Open the folder on GitHubat commit 8d670fa
We found 2 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in dotnet/skills, which our catalogue first saw on October 7, 2026.
Test Gap Analysis next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Test Gap Analysis this skilldotnet/skills | 5.6k | 1 repos | ~4.5k | Automated safety check: Pass | MIT | |
| Evaluate PR Testsdotnet/maui | 23k | — | ~2.9k | Automated safety check: Pass | MIT | |
| Coverage Analysismicrosoft/testfx | 1k | — | ~7.3k | Automated safety check: Pass | MIT | |
| Coverage Analysisrunceel/ReactiveProperty | 944 | — | ~5.9k | Automated safety check: Warn | MIT | |
| Stryker Dotnetardalis/RiverBooks | 134 | — | ~1.9k | Automated safety check: Pass | None | |
| CoverageLog2n-io/Typhon | 250 | — | ~787 | Automated safety check: Pass | Custom licence |
dotnet/maui
Reviews the tests added in a pull request for fix coverage, quality, edge cases and test type, and recommends lighter test types where they would do.
microsoft/testfx
Project-wide code coverage and CRAP (Change Risk Anti-Patterns) score analysis for .NET projects.
runceel/ReactiveProperty
Automated, project-wide code coverage and CRAP (Change Risk Anti-Patterns) score analysis for .NET projects with existing unit tests.
ardalis/RiverBooks
Run Stryker.NET mutation testing against a specific .NET source file.
Log2n-io/Typhon
Run code coverage analysis, track class-level results, and generate trend reports
novotnyllc/dotnet-artisan
Defines .NET test strategy and implementation patterns across xUnit v3 (Facts, Theories, fixtures, IAsyncLifetime), integration testing (WebApplicationFactory, Testcontainers), Aspire testing…
dotnet/skills
Resolves .NET runtime frames in Apple .ips crash logs to function names, source files and line numbers using dSYM symbols, atos and the Microsoft symbol server.
dotnet/skills
Resolves native crash frames from .NET Android tombstones to function names, source files and line numbers using BuildIds, Microsoft's symbol server and llvm-symbolizer.
dotnet/skills
Scans C# and .NET code for about 50 performance anti-patterns and reports prioritized findings with concrete fixes, at a scan depth you choose.
dotnet/skills
Statically pairs source files with test files to list code that no test references, using Roslyn for C# or tree-sitter for many languages, with no build.
dotnet/skills
Activate this skill when BenchmarkDotNet (BDN) is involved in the task — creating, running, configuring, or reviewing BDN benchmarks.
dotnet/skills
Makes .NET projects compatible with Native AOT and trimming by resolving IL trim and AOT analyzer warnings through annotations rather than suppressions.
Works with
Categories
Pseudo-mutation analysis ONLY: answer whether tests would catch a bug if production code changed, which meaningful changes would still pass, or which caller-visible mutations existing assertions…. Test Gap Analysis is an agent skill from dotnet/skills, published by the product's own GitHub organization. Pseudo-mutation analysis ONLY: answer whether tests would catch a bug if production code changed, which meaningful changes would still pass, or which caller-visible mutations existing assertions would miss; verify candidates when requested, then optionally close verified gaps.
Test Gap Analysis fits situations like: : suite organization; distribution reports (test-tagging); .NET line-vs-branch; cobertura interpretation.
Run `npx skills add dotnet/skills --skill test-gap-analysis -a claude-code`. Or copy the skill folder (plugins/dotnet-test/skills/test-gap-analysis in dotnet/skills) into .claude/skills/test-gap-analysis in your project. Claude Code loads it when a task matches its description.
Run `npx skills add dotnet/skills --skill test-gap-analysis -a codex`. Or copy the skill folder (plugins/dotnet-test/skills/test-gap-analysis in dotnet/skills) into .agents/skills/test-gap-analysis in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add dotnet/skills --skill test-gap-analysis -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/test-gap-analysis, .gemini/skills/test-gap-analysis, .github/skills/test-gap-analysis and .opencode/skills/test-gap-analysis in your project.
Going by SKILL.md and its folder, Test Gap Analysis needs the command-line tools its instructions call (dotnet).
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Test Gap Analysis is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.5k tokens (SKILL.md is roughly 18k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 914 tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Test Gap Analysis: Evaluate PR Tests (dotnet/maui, 23k stars), Coverage Analysis (microsoft/testfx, 1k stars), Coverage Analysis (runceel/ReactiveProperty, 944 stars) and Stryker Dotnet (ardalis/RiverBooks, 134 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
dotnet (a GitHub organization, an official publisher) maintains it in dotnet/skills, which has 5,568 GitHub stars. The repository holds 91 skills in this directory. The repository was last updated on October 7, 2026.
Source: dotnet/skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.