.NET API Compatibility Design
Aaronontheweb/dotnet-skills
Applies extend-only design rules to NuGet packages and distributed systems, covering source, binary and wire compatibility and how to deprecate members safely.
Generate wrapper interfaces and DI registration for hard-to-test static dependencies in C.
$ npx skills add microsoft/testfx --skill generate-testability-wrappers -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install microsoft/testfx generate-testability-wrappers --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/microsoft/testfx.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/generate-testability-wrappers .claude/skills/generate-testability-wrappers && 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 "generate-testability-wrappers" agent skill from https://github.com/microsoft/testfx/tree/main/.agents/skills/generate-testability-wrappers into .claude/skills/generate-testability-wrappers/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "generate-testability-wrappers", 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/microsoft/testfx/tree/main/.agents/skills/generate-testability-wrappersType 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 microsoft/testfx --skill generate-testability-wrappers -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install microsoft/testfx generate-testability-wrappers --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/microsoft/testfx.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/generate-testability-wrappers .agents/skills/generate-testability-wrappers && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "generate-testability-wrappers" agent skill from https://github.com/microsoft/testfx/tree/main/.agents/skills/generate-testability-wrappers into .agents/skills/generate-testability-wrappers/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "generate-testability-wrappers", 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 microsoft/testfx --skill generate-testability-wrappers -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install microsoft/testfx generate-testability-wrappers --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/microsoft/testfx.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/generate-testability-wrappers .cursor/skills/generate-testability-wrappers && 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 "generate-testability-wrappers" agent skill from https://github.com/microsoft/testfx/tree/main/.agents/skills/generate-testability-wrappers into .cursor/skills/generate-testability-wrappers/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "generate-testability-wrappers", 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/microsoft/testfx.git --path .agents/skills/generate-testability-wrappers--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 microsoft/testfx --skill generate-testability-wrappers -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install microsoft/testfx generate-testability-wrappers --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/microsoft/testfx.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/generate-testability-wrappers .gemini/skills/generate-testability-wrappers && 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 "generate-testability-wrappers" agent skill from https://github.com/microsoft/testfx/tree/main/.agents/skills/generate-testability-wrappers into .gemini/skills/generate-testability-wrappers/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "generate-testability-wrappers", 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 microsoft/testfx generate-testability-wrappersInstalls 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 microsoft/testfx --skill generate-testability-wrappers -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/microsoft/testfx.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/generate-testability-wrappers .github/skills/generate-testability-wrappers && 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 "generate-testability-wrappers" agent skill from https://github.com/microsoft/testfx/tree/main/.agents/skills/generate-testability-wrappers into .github/skills/generate-testability-wrappers/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "generate-testability-wrappers", 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 microsoft/testfx --skill generate-testability-wrappers -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install microsoft/testfx generate-testability-wrappers --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/microsoft/testfx.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/generate-testability-wrappers .opencode/skills/generate-testability-wrappers && 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 "generate-testability-wrappers" agent skill from https://github.com/microsoft/testfx/tree/main/.agents/skills/generate-testability-wrappers into .opencode/skills/generate-testability-wrappers/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "generate-testability-wrappers", 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.
generate-testability-wrappersGenerate wrapper interfaces and DI registration for hard-to-test static dependencies in C.
Generate Testability Wrappers is an agent skill from microsoft/testfx, published by the product's own GitHub organization. Generate wrapper interfaces and DI registration for hard-to-test static dependencies in C. Produces IFileSystem, IEnvironmentProvider, IConsole, IProcessRunner wrappers, or guides adoption of TimeProvider and IHttpClientFactory. USE FOR: generate wrapper for static, create IFileSystem wrapper, wrap DateTime.Now, make static testable, make class testable, create abstraction for File., generate DI registration, TimeProvider adoption, IHttpClientFactory setup, testability wrapper, mock-friendly interface, mock time…
Its SKILL.md is about 2.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Backend & APIs, covering API design. It works with .NET and C#. The repository describes itself as: This repository holds the source code of Microsoft.Testing.Platform (MTP), a lightweight alternative to VSTest, as well as MSTest adapter and framework. The licence is MIT.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 44b9dcc. 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.
Generate Testability Wrappers loads about 2.2k tokens when it runs. Until then it costs about 236 tokens; SKILL.md has 647 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 microsoft/testfx at commit 44b9dcc, republished under its MIT licence (© microsoft). 647 words, ~2,190 tokens.
.claude/skills/generate-testability-wrappers/SKILL.md (or your agent's skills folder).Generate wrapper interfaces, default implementations, and DI service registration code for untestable static dependencies. For statics that already have .NET built-in abstractions (TimeProvider, IHttpClientFactory), guide adoption of the built-in. For statics without built-in alternatives, generate custom minimal wrappers.
detect-static-dependencies and identifying which statics to wrapTimeProvider (.NET 8+) or System.IO.AbstractionsEnvironment.*, Console.*, or Process.*detect-static-dependencies)migrate-static-to-wrapper)| Input | Required | Description |
|---|---|---|
| Static category | Yes | Which category: time, filesystem, environment, network, console, process |
| Target framework | Yes | The TargetFramework from .csproj (affects which built-in abstractions exist) |
| DI container | No | Which DI framework: microsoft (default), autofac, none (ambient context) |
| Namespace | No | Target namespace for generated wrapper code |
Based on the category and target framework:
| Category | .NET 8+ | .NET 6-7 | .NET Framework |
|---|---|---|---|
| Time | TimeProvider (built-in) | TimeProvider via Microsoft.Bcl.TimeProvider NuGet | Custom ISystemClock |
| File system | System.IO.Abstractions (NuGet) | Same | Same |
| HTTP | IHttpClientFactory (built-in) | Same | Same |
| Environment | Custom IEnvironmentProvider | Same | Same |
| Console | Custom IConsole | Same | Same |
| Process | Custom IProcessRunner | Same | Same |
No wrapper code needed — guide the user:
builder.Services.AddSingleton(TimeProvider.System);public class OrderProcessor(TimeProvider timeProvider)
{
public bool IsExpired(Order order)
=> timeProvider.GetUtcNow() > order.ExpiresAt;
}FakeTimeProvider:// Requires Microsoft.Extensions.TimeProvider.Testing NuGet
var fakeTime = new FakeTimeProvider(new DateTimeOffset(2026, 1, 15, 0, 0, 0, TimeSpan.Zero));
var processor = new OrderProcessor(fakeTime);
fakeTime.Advance(TimeSpan.FromDays(1));
Assert.True(processor.IsExpired(order));Guide: install Microsoft.Bcl.TimeProvider NuGet. Same API as above.
No wrapper code needed — register typed clients via builder.Services.AddHttpClient<MyService>() and inject HttpClient directly into the class constructor.
For categories without built-in abstractions, follow this template:
Only include methods that were actually detected in the codebase. Do NOT generate a wrapper for every possible member — wrap only what is used.
namespace <Namespace>;
/// <summary>
/// Abstraction over <static class> for testability.
/// </summary>
public interface I<WrapperName>
{
// One method per detected static call
<return type> <MethodName>(<parameters>);
}namespace <Namespace>;
/// <summary>
/// Default implementation that delegates to <static class>.
/// </summary>
public sealed class <WrapperName> : I<WrapperName>
{
public <return type> <MethodName>(<parameters>)
=> <StaticClass>.<Method>(<arguments>);
}// In Program.cs or Startup.cs:
builder.Services.AddSingleton<I<WrapperName>, <WrapperName>>();Prefer the established System.IO.Abstractions NuGet package over custom wrappers:
dotnet add package System.IO.Abstractionsbuilder.Services.AddSingleton<IFileSystem, FileSystem>();IFileSystem into classes:public class ConfigLoader(IFileSystem fileSystem)
{
public string LoadConfig(string path)
=> fileSystem.File.ReadAllText(path);
}MockFileSystem:dotnet add <TestProject> package System.IO.Abstractions.TestingHelpersvar mockFs = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ "/config.json", new MockFileData("{\"key\": \"value\"}") }
});
var loader = new ConfigLoader(mockFs);
Assert.Equal("{\"key\": \"value\"}", loader.LoadConfig("/config.json"));If the codebase does not use DI (e.g., old console app, library code), offer the ambient context pattern:
public static class Clock
{
private static readonly AsyncLocal<Func<DateTimeOffset>?> s_override = new();
public static DateTimeOffset UtcNow
=> s_override.Value?.Invoke() ?? TimeProvider.System.GetUtcNow();
public static IDisposable Override(DateTimeOffset fixedTime)
{
s_override.Value = () => fixedTime;
return new Scope();
}
private sealed class Scope : IDisposable
{
public void Dispose() => s_override.Value = null;
}
}Key trade-offs: AsyncLocal<T> ensures parallel tests don't interfere; production cost is one null check per call; the static readonly field is essentially free.
Generate files following the project's existing conventions:
Abstractions/ or Interfaces/ folder, place the interface thereInfrastructure/ or Services/ folder, place the implementation thereAlways generate:
AddSingleton for stateless wrappers, AddTransient for stateful onesTimeProvider is recommended over custom ISystemClockAsyncLocal<T>, scoped disposal, and trade-off explanation| Pitfall | Solution |
|---|---|
| Wrapping ALL members of a static class | Only wrap methods actually called in the codebase |
| Custom time wrapper on .NET 8+ | Use built-in TimeProvider instead |
| Custom file system wrapper | Prefer System.IO.Abstractions NuGet — battle-tested, complete |
| Registering scoped when singleton suffices | Stateless wrappers should be AddSingleton |
| Forgetting test helper packages | Microsoft.Extensions.TimeProvider.Testing for time, System.IO.Abstractions.TestingHelpers for filesystem |
Ambient context without AsyncLocal | Non-async [ThreadStatic] breaks with async/await — always use AsyncLocal<T> |
© microsoft, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/generate-testability-wrappers of microsoft/testfx.
Open the folder on GitHubat commit 44b9dcc
Generate Testability Wrappers 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 |
|---|---|---|---|---|---|---|
| Generate Testability Wrappers this skillmicrosoft/testfx | 1k | — | ~2.2k | Automated safety check: Pass | MIT | |
| .NET API Compatibility DesignAaronontheweb/dotnet-skills | 1.2k | 2 repos | ~2.7k | Automated safety check: Pass | MIT | |
| Csharp Nullable Reference TypesAaronontheweb/dotnet-skills | 1.2k | 1 repos | ~2.9k | Automated safety check: Pass | MIT | |
| Generate Testability Wrappersdotnet/skills | 5.6k | 1 repos | ~3.9k | Automated safety check: Pass | MIT | |
| Csharp Dotnetericrisco/rsc-harness | 156 | — | ~3.3k | Automated safety check: Pass | MIT | |
| Aa Batching PaymastersNethereum/Nethereum | 2.3k | — | ~1.5k | Automated safety check: Pass | MIT |
Aaronontheweb/dotnet-skills
Applies extend-only design rules to NuGet packages and distributed systems, covering source, binary and wire compatibility and how to deprecate members safely.
Aaronontheweb/dotnet-skills
Guidelines for introducing and using nullable reference types (NRT) and System.Diagnostics.CodeAnalysis nullable attributes in C / .NET codebases.
dotnet/skills
DO NOT USE when the target already consumes an injected interface or built-in abstraction such as IFileSystem or TimeProvider, even if the request says "generate a wrapper"; no new wrapper is needed.
ericrisco/rsc-harness
A skill your agent uses when writing, reviewing, testing, or shipping C / .NET code — ASP.NET Core APIs (minimal APIs vs controllers), EF Core data access, async correctness, solution layout in…
Nethereum/Nethereum
Help users batch multiple calls into a single UserOperation and sponsor gas with paymasters using Nethereum Account Abstraction.
querylenshq/ef-querylens
Comprehensive C and .NET development skill for TSP projects.
microsoft/testfx
Guide for organizing MSBuild infrastructure with Directory.Build.props, Directory.Build.targets, Directory.Packages.props, and Directory.Build.rsp.
microsoft/testfx
Analyze MSBuild binary logs to diagnose build failures. An agent skill from microsoft/testfx.
microsoft/testfx
Project-wide code coverage and CRAP (Change Risk Anti-Patterns) score analysis for .NET projects.
microsoft/testfx
Guide for optimizing MSBuild incremental builds. An agent skill from microsoft/testfx.
microsoft/testfx
Guide for modernizing and migrating MSBuild project files to SDK-style format.
microsoft/testfx
Catalog of MSBuild anti-patterns with detection rules and fix recipes.
Categories
Generate wrapper interfaces and DI registration for hard-to-test static dependencies in C. Generate Testability Wrappers is an agent skill from microsoft/testfx, published by the product's own GitHub organization. Generate wrapper interfaces and DI registration for hard-to-test static dependencies in C.
Generate Testability Wrappers fits situations like: : generate wrapper for static; create IFileSystem wrapper; wrap DateTime.Now; make static testable.
Run `npx skills add microsoft/testfx --skill generate-testability-wrappers -a claude-code`. Or copy the skill folder (.agents/skills/generate-testability-wrappers in microsoft/testfx) into .claude/skills/generate-testability-wrappers in your project. Claude Code loads it when a task matches its description.
Run `npx skills add microsoft/testfx --skill generate-testability-wrappers -a codex`. Or copy the skill folder (.agents/skills/generate-testability-wrappers in microsoft/testfx) into .agents/skills/generate-testability-wrappers 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 microsoft/testfx --skill generate-testability-wrappers -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/generate-testability-wrappers, .gemini/skills/generate-testability-wrappers, .github/skills/generate-testability-wrappers and .opencode/skills/generate-testability-wrappers in your project.
Going by SKILL.md and its folder, Generate Testability Wrappers 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.
Generate Testability Wrappers is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.2k tokens (SKILL.md is roughly 8.8k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Generate Testability Wrappers: .NET API Compatibility Design (Aaronontheweb/dotnet-skills, 1.2k stars), Csharp Nullable Reference Types (Aaronontheweb/dotnet-skills, 1.2k stars), Generate Testability Wrappers (dotnet/skills, 5.6k stars) and Csharp Dotnet (ericrisco/rsc-harness, 156 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
microsoft (a GitHub organization, an official publisher) maintains it in microsoft/testfx, which has 1,047 GitHub stars. The repository holds 44 skills in this directory. The repository was last updated on October 7, 2026.
Source: microsoft/testfx on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.