Detects duplicate boilerplate, copy-paste tests, and structural maintainability issues across .NET test suites. Use when the user asks to reduce repetition, consolidate similar test methods, convert copy-paste tests to data-driven parameterized tests, suggest a better test structure, or identify refactoring opportunities. Identifies repeated construction, assertion patterns, copy-paste methods convertible to DataRow/Theory/TestCase, redundant setup/teardown, and shared infrastructure. Produces an analysis report with concrete before/after suggestions. Works with MSTest, xUnit, NUnit, and TUnit. DO NOT USE FOR: writing new tests (use writing-mstest-tests), reviewing test quality or anti-patterns (use test-anti-patterns), or deep mock auditing (use exp-mock-usage-analysis).
npx skills add https://github.com/dotnet/skills --skill exp-test-maintainability
Analyze .NET test code for maintainability issues: duplicated boilerplate, copy-paste test methods, and structural repetition across test methods and classes. Produce a report of refactoring opportunities with concrete before/after suggestions. The goal is analysis only — do not modify any files.
writing-mstest-tests)test-anti-patterns)| Input | Required | Description |
|-------|----------|-------------|
| Test code | Yes | One or more test files or a test project directory to analyze |
| Production code | No | The code under test, for context on what abstractions might help |
| Scope | No | Whether to analyze within a single class or across multiple classes |
Read all test files the user provides or references. If the user points to a directory or project, scan for all test files using these framework markers:
| Framework | Test class markers | Test method markers |
|-----------|--------------------|---------------------|
| MSTest | [TestClass] | [TestMethod], [DataTestMethod] |
| xUnit | *(none — convention-based)* | [Fact], [Theory] |
| NUnit | [TestFixture] | [Test], [TestCase], [TestCaseSource] |
| TUnit | *(none — convention-based)* | [Test] |
Scan for these categories:
Look for the same object being constructed in 3+ test methods with identical or near-identical parameters.
Indicators:
new ClassName(...) appearing with identical arguments in multiple testsPotential refactorings:
CreateSut(), CreateDefaultOrder())[TestInitialize]/constructor/[SetUp] for shared constructionExample — before:
[TestMethod]
public void Process_ValidOrder_Succeeds()
{
var logger = new FakeLogger();
var email = new FakeEmailService();
var inventory = new FakeInventory(stock: 100);
var processor = new OrderProcessor(logger, email, inventory);
// ...
}
[TestMethod]
public void Process_EmptyItems_Fails()
{
var logger = new FakeLogger();
var email = new FakeEmailService();
var inventory = new FakeInventory(stock: 100);
var processor = new OrderProcessor(logger, email, inventory);
// ...
}
After — extract factory:
private static OrderProcessor CreateProcessor(int stock = 100)
{
return new OrderProcessor(new FakeLogger(), new FakeEmailService(), new FakeInventory(stock));
}
Look for the same sequence of assertions appearing in 3+ test methods.
Indicators:
Assert.AreEqual calls across methodsPotential refactorings:
AssertValidOrder(order, expectedTotal, expectedStatus))Verify method that checks a standard set of propertiesLook for test methods with near-identical bodies differing only in input values or a single parameter.
Indicators:
[DataRow]/[Theory]/[TestCase]Method_Input1_Result, Method_Input2_ResultPotential refactorings:
[DataRow]/[InlineData]/[TestCase][DynamicData]/[MemberData]/[TestCaseSource] for complex inputs[DataRow] with DisplayName over [DynamicData] when all values are compile-time constants. Reserve [DynamicData] for computed or complex values.DisplayName for non-obvious parameter values. [DataRow("Gold", 100.0, 90.0)] is self-explanatory; [DataRow(3, 7, 42)] is not.Look for initialization or cleanup code repeated across test classes.
Indicators:
[TestInitialize]/[SetUp] methods with similar bodiesusing/IDisposable cleanup pattern across classesPotential refactorings:
Look for structural patterns shared across test classes.
Indicators:
HttpClient setup with similar DelegatingHandler patternsPotential refactorings:
Before reporting, filter findings through these rules:
new Calculator() or new List<int>() is not meaningful boilerplate. Don't recommend builders for new User(1, "Alice") either.Present findings in this structure:
| Pitfall | Solution |
|---------|----------|
| Flagging AAA structure as duplication | The Arrange-Act-Assert pattern is not boilerplate — flag only when the actual code repeats |
| Suggesting extraction for 2 occurrences | Wait for 3+ before recommending extraction |
| Recommending base classes for everything | Prefer composition (helpers, factories) over inheritance |
| Ignoring the readability cost | Every extraction adds indirection — note the trade-off |
| Flagging simple new X() as boilerplate | Only flag complex construction with multiple parameters or configuration |
| Recommending DRY at the expense of test isolation | Tests that share mutable state through helpers become coupled — warn about this |
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
Use when implementing any feature or bugfix, before writing implementation code
Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes
Use when about to claim work is complete, fixed, or passing, before committing or creating PRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always
Expert guidance for systematic backtesting of trading strategies. Use when developing, testing, stress-testing, or validating quantitative trading strategies. Covers "beating ideas to death" methodology, parameter robustness testing, slippage modeling, bias prevention, and interpreting backtest results. Applicable when user asks about backtesting, strategy validation, robustness testing, avoiding overfitting, or systematic trading development.
Cloud laboratory platform for automated protein testing and validation. Use when designing proteins and needing experimental validation including binding assays, expression testing, thermostability measurements, enzyme activity assays, or protein sequence optimization. Also use for submitting experiments via API, tracking experiment status, downloading results, optimizing protein sequences for better expression using computational tools (NetSolP, SoluProt, SolubleMPNN, ESM), or managing protein design workflows with wet-lab validation.
This skill should be used for time series machine learning tasks including classification, regression, clustering, forecasting, anomaly detection, segmentation, and similarity search. Use when working with temporal data, sequential patterns, or time-indexed observations requiring specialized algorithms beyond standard ML approaches. Particularly suited for univariate and multivariate time series analysis with scikit-learn compatible APIs.
Take dotnet/exp-test-maintainability from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.