Skip to content
Development
Skill

/test-anti-patterns

Audit a test file or suite; produce a severity-ranked diagnostic report. ALWAYS USE for tests that verify nothing, missing/tautological assertions, swallowed/broad exceptions, flaky/order-dependent tests, duplication, or magic values. Polyglot. DO NOT USE for direct edits:

From plugin
dotnet-skills
5.4k100 skills16 agents
Install
$ npx -y skills add dotnet/skills --skill test-anti-patterns --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/test-anti-patterns

Context preview

The summary Claude sees to decide when to auto-load this skill.

Audit a test file or suite; produce a severity-ranked diagnostic report. ALWAYS USE for tests that verify nothing, missing/tautological assertions, swallowed/broad exceptions, flaky/order-dependent tests, duplication, or magic values. Polyglot. DO NOT USE for direct edits:

SKILL.md

test-anti-patterns.SKILL.md
name: test-anti-patterns
description: >
  Audit a test file or suite; produce a severity-ranked diagnostic report.
  ALWAYS USE for tests that verify nothing, missing/tautological
  assertions, swallowed/broad exceptions, flaky/order-dependent tests,
  duplication, or magic values. Polyglot. DO NOT USE for direct edits:
  writing-mstest-tests owns supplied MSTest assertions/attributes/lifecycle;
  code-testing-agent owns new tests. Exclude running tests, migration, assertion
  metrics (assertion-quality), raw .NET coverage collection (run-tests),
  non-.NET coverage collection/analysis (native tooling), project-wide .NET coverage/CRAP
  (coverage-analysis), named-target .NET CRAP
  (crap-score), behavioral/pseudo-mutation gaps (test-gap-analysis), test-mix/
  happy-vs-error classification and trait distributions (test-tagging), or the
  testsmells.org catalog (test-smell-detection).
license: MIT

Test Anti-Pattern Detection

Quick, pragmatic analysis of test code in any supported language for anti-patterns and quality issues that undermine test reliability, maintainability, and diagnostic value.

> **Language-specific guidance**: Try `test-analysis-extensions` once. If it is > unavailable, continue immediately with this skill's built-in framework rules; > never block the audit on the helper.

When to Use

  • User asks to review test quality or find test smells
  • User wants to know why tests are flaky or unreliable
  • User asks "are my tests good?" or "what's wrong with my tests?"
  • User requests a test audit or test code review
  • User wants diagnostic findings before deciding what to improve

When Not to Use

  • User wants to write new tests from scratch (use `code-testing-agent`)
  • User wants direct implementation fixes rather than a diagnostic review (use the relevant write/edit skill)
  • User asks to fix swapped `Assert.AreEqual` argument order in MSTest (use `writing-mstest-tests`)
  • User asks to convert MSTest `DynamicData` from `IEnumerable<object[]>` to `ValueTuple` (use `writing-mstest-tests`)
  • User wants to run or execute tests (use `run-tests` for .NET)
  • User wants to migrate between test frameworks or versions (use migration skills)
  • User wants raw .NET coverage collection (use `run-tests`), non-.NET coverage collection or analysis (use native tooling), project-wide .NET coverage/CRAP metrics (use `coverage-analysis`), or named-target .NET CRAP (use `crap-score`)
  • User asks whether tests would catch a bug or wants behavioral/pseudo-mutation gaps (use `test-gap-analysis`)
  • User wants test-mix or happy-vs-error-path classification, standardized tagging, or trait/category distributions (use `test-tagging`)
  • User wants a deep formal test smell audit with academic taxonomy and extended catalog (use `test-smell-detection`)

Inputs

| Input | Required | Description | |-------|----------|-------------| | Test scope | No | Test files, classes, directory, or project to analyze. Discover from the current workspace when omitted. | | Production code | No | The code under test, for context on what tests should verify | | Specific concern | No | A focused area like "flakiness" or "naming" to narrow the review |

Workflow

Step 1: Detect language and load extension

Resolve the named test path from the current workspace before asking for input. When no path is supplied, discover test files under the current directory using the repository manifests and conventional test markers. The skill context's `Base directory` is documentation storage, not the user's workspace; never resolve target files relative to it.

If one reader says a path is missing but a workspace glob/search finds it, normalize that exact path and retry. Use a shell text reader (`sed`/`cat` on Unix, `Get-Content` on PowerShell) only for a confirmed reader availability, transport, or path-normalization failure and only after verifying the canonical path remains inside the current workspace. Stop on content-exclusion, permission/policy, workspace-boundary, or unknown failures. Audit any discovered file that a permitted reader can access; never ask the user to paste it. If every permitted reader fails, report the exact blocker without bypassing security boundaries.

Identify the language and framework. Try the matching `test-analysis-extensions` guidance once; if unavailable, use the catalog below.

Step 2: Gather the test code

Read every test file in the resolved scope. Use extension discovery markers when loaded; otherwise use the built-in markers in this skill (attributes such as `[TestClass]`/`[Fact]`/`[Test]`, `test_*.py`, `*.test.*`, `*_test.go`, `*_spec.rb`, `#[test]`, `*.Tests.ps1`, `TEST(...)`, and `TEST_CASE(...)`).

If production code is available, read it too -- this is critical for detecting tests that are coupled to implementation details rather than behavior.

Step 3: Scan for anti-patterns

Check each test file against the anti-pattern catalog below. Report findings grouped by severity. Use extension mappings when loaded; otherwise use the cross-framework examples in the catalog.

Before drafting the report, make a private completeness ledger with one row for every test method and every class-level fixture/resource. Record its oracle (or absence), exception handling, state/time dependencies, and disposition. Do not publish until every row is either attached to a finding or explicitly judged sound. In particular:

  • `actual != oldValue` is a weak mutation oracle: it accepts every wrong new

value. Require the exact expected value.

  • Include unused or undisposed class-level resources; method-only scans miss

fields such as a static `HttpClient`.

  • When production code is supplied, note obvious untested contracts adjacent to

a finding, but do not perform exhaustive branch or mutation analysis. Route that broader question to `test-gap-analysis`.

Critical -- Tests that give false confidence

| Anti-Pattern | What to Look For | |---|---| | **No assertions** | Test methods t

Read more
Ships withdotnet-skills

This repository contains the .NET team's curated set of portable skills and host-specific custom agents for coding agents. For information about the Agent Skills standard, see agentskills.io.

Get the whole plugin

Other skills on dotnet-skills.