.github/skills/detect-static-dependencies/SKILL.md
Scan C# source files for hard-to-test static dependencies — DateTime.Now/UtcNow, File.*, Directory.*, Environment.*, HttpClient, Console.*, Process.*, and other untestable statics. Produces a ranked report of static call sites by frequency. USE FOR: find untestable statics, scan for static dependencies, testability audit, identify hard-to-mock code, find DateTime.Now usage, detect static coupling, testability report, static analysis for testability. DO NOT USE FOR: generating wrappers (use generate-testability-wrappers), migrating code (use migrate-static-to-wrapper), general code review, or finding statics that are already behind abstractions.
npx skillsauth add microsoft/vstest detect-static-dependenciesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Scan a C# codebase for calls to hard-to-test static APIs and produce a ranked report showing which statics appear most frequently, which files are most affected, and which abstractions already exist in the .NET ecosystem to replace them.
generate-testability-wrappers)migrate-static-to-wrapper)TimeProvider| Input | Required | Description |
|-------|----------|-------------|
| Target path | Yes | A file, directory, project (.csproj), or solution (.sln) to scan |
| Exclusion patterns | No | Glob patterns to skip (e.g., **/obj/**, **/Migrations/**) |
| Category filter | No | Limit to specific categories: time, filesystem, environment, network, console, process |
Resolve the target to a set of .cs files:
.cs file, scan that single file..cs files recursively (excluding obj/, bin/)..csproj, find its directory and scan .cs files within..sln, parse it, find all project directories, and scan .cs files across all projects.Always exclude obj/, bin/, and any user-specified exclusion patterns.
Scan each file for calls matching these categories:
| Category | Patterns to search for | Recommended replacement |
|----------|----------------------|------------------------|
| Time | DateTime.Now, DateTime.UtcNow, DateTime.Today, DateTimeOffset.Now, DateTimeOffset.UtcNow, Task.Delay(, new CancellationTokenSource(TimeSpan | TimeProvider (.NET 8+) |
| File System | File.ReadAllText(, File.WriteAllText(, File.Exists(, File.Delete(, File.Copy(, File.Move(, Directory.Exists(, Directory.CreateDirectory(, Directory.GetFiles(, Directory.Delete(, Path.Combine(, Path.GetTempPath( | IFileSystem (System.IO.Abstractions NuGet) |
| Environment | Environment.GetEnvironmentVariable(, Environment.SetEnvironmentVariable(, Environment.MachineName, Environment.UserName, Environment.CurrentDirectory, Environment.Exit( | Custom IEnvironmentProvider |
| Network | new HttpClient(, HttpClient.GetAsync(, HttpClient.PostAsync(, HttpClient.SendAsync( | IHttpClientFactory (built-in) |
| Console | Console.WriteLine(, Console.ReadLine(, Console.Write(, Console.ReadKey( | IConsole wrapper or ILogger |
| Process | Process.Start(, Process.GetCurrentProcess(, Process.GetProcessesByName( | Custom IProcessRunner |
Count each static call pattern across the entire scan scope. Produce a summary with:
TimeProvider (built-in since .NET 8)System.IO.Abstractions (NuGet package)IHttpClientFactory (built-in)IEnvironmentProviderIConsole or ILoggerIProcessRunnerFormat the output as a structured report:
## Static Dependency Report
**Scope**: <project/solution name>
**Files scanned**: <count>
**Total static call sites**: <count>
### Category Summary
| Category | Call Sites | Recommended Abstraction |
|-------------|-----------|------------------------|
| Time | 42 | TimeProvider (.NET 8+) |
| File System | 31 | System.IO.Abstractions |
| Environment | 12 | IEnvironmentProvider |
| ... | ... | ... |
### Top 10 Patterns
| # | Pattern | Count | Files |
|---|---------------------|-------|-------|
| 1 | DateTime.UtcNow | 28 | 14 |
| 2 | File.ReadAllText | 18 | 9 |
| ... |
### Most Affected Files
| File | Static Calls | Categories |
|-------------------------------|-------------|---------------------|
| Services/OrderProcessor.cs | 12 | Time, FileSystem |
| ... |
### Migration Priority
1. **Time** (42 sites) — Use `TimeProvider`, zero NuGet dependencies on .NET 8+
2. **File System** (31 sites) — Use `System.IO.Abstractions` NuGet package
3. ...
Based on the report, recommend:
generate-testability-wrappers for custom wrapper generationmigrate-static-to-wrapper for mechanical bulk migration.cs files in scope were scanned (check count)obj/ and bin/ directories were excluded| Pitfall | Solution |
|---------|----------|
| Scanning obj/ or generated code | Always exclude obj/, bin/, and *.Designer.cs |
| Counting wrapped calls as statics | Check if the call is behind an interface or injected service before counting |
| Missing statics inside lambdas/LINQ | Search covers all code within .cs files, including lambdas |
| Recommending TimeProvider on < .NET 8 | Check TargetFramework in .csproj — if < net8.0, recommend NodaTime.IClock or custom ISystemClock |
| Ignoring test projects | Only scan production code — exclude *.Tests.csproj projects from the scan |
development
Best practices for writing MSTest 3.x/4.x unit tests. Use when the user needs to write, improve, fix, or review MSTest tests, including modern assertions, data-driven tests, test lifecycle, and common anti-patterns. Also use when fixing test issues like swapped Assert.AreEqual arguments, incorrect assertion usage, or modernizing legacy test code. Covers MSTest.Sdk, sealed classes, Assert.Throws, DynamicData with ValueTuples, TestContext, and conditional execution.
development
Build, test, and validate changes in the vstest repository. Use when building vstest projects, running unit tests, smoke tests, or acceptance tests, or when deploying locally built vstest.console for manual testing.
development
Validate that commands documented in skill files actually work. Use when creating, updating, or reviewing skills to ensure all documented commands exit with code 0.
testing
Parse and analyze Visual Studio TRX test result files. Use when asked about slow tests, test durations, test frequency, flaky tests, failure analysis, or test execution patterns from TRX files.