Source profileQuality 93/100

dotnet/skills/plugins/dotnet-test/skills/test-anti-patterns/SKILL.md

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: 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), n

Source repository stars
5,277
Declared platforms
0
Static risk flags
1
Last source update
2026-08-28
Source checked
2026-08-28

Decision brief

What it does: where it fits

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

Best for

  • 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?"

Not for

  • 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)

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/dotnet/skills --skill "plugins/dotnet-test/skills/test-anti-patterns"
Safe inspection promptEditorial

Inspect the Agent Skill "test-anti-patterns" from https://github.com/dotnet/skills/blob/2b9056bd9152490cc698c5b3e61c9f9a1c135776/plugins/dotnet-test/skills/test-anti-patterns/SKILL.md at commit 2b9056bd9152490cc698c5b3e61c9f9a1c135776. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    Workflow

    Identify the target codebase's language and test framework. Call the test-analysis-extensions skill and read the matching extension file. The extension file documents framework-specific anti-pattern markers — what counts as a sleep/wait, a test marker, a skip, a setup/teardown,…

    Critical/High: Only for issues that cause tests to give false confidence or be unreliable. A test that always passes regardless of correctness is Critical. Flaky shared state is High. Missing-await on async assertions i…Medium: Only for issues that actively harm maintainability -- 5+ nearly-identical tests, truly meaningless names like Test1 / test / it1.Low: Cosmetic naming mismatches, minor style preferences, assertion messages that could be better. When in doubt, rate Low.
  2. 02

    Step 1: Detect language and load extension

    Identify the target codebase's language and test framework. Call the test-analysis-extensions skill and read the matching extension file. The extension file documents framework-specific anti-pattern markers — what counts as a sleep/wait, a test marker, a skip, a setup/teardown,…

    Identify the target codebase's language and test framework. Call the test-analysis-extensions skill and read the matching extension file. The extension file documents framework-specific anti-pattern markers — what count…
  3. 03

    Step 2: Gather the test code

    Read the test files the user wants reviewed. If the user points to a directory or project, scan for all test files using the discovery markers in the loaded language extension file (e.g., [TestClass]/[Fact]/[Test] for .NET, test.py / def test for pytest, .test.ts / it() for Jest…

    Read the test files the user wants reviewed. If the user points to a directory or project, scan for all test files using the discovery markers in the loaded language extension file (e.g., [TestClass]/[Fact]/[Test] for .…If production code is available, read it too -- this is critical for detecting tests that are coupled to implementation details rather than behavior.
  4. 04

    Step 3: Scan for anti-patterns

    Check each test file against the anti-pattern catalog below. Report findings grouped by severity. The examples are .NET-centric but the patterns generalize — use the loaded language extension file to map each pattern to the framework you are auditing.

    Check each test file against the anti-pattern catalog below. Report findings grouped by severity. The examples are .NET-centric but the patterns generalize — use the loaded language extension file to map each pattern to…
  5. 05

    Step 4: Calibrate severity honestly

    Before reporting, re-check each finding against these severity rules:

    Critical/High: Only for issues that cause tests to give false confidence or be unreliable. A test that always passes regardless of correctness is Critical. Flaky shared state is High. Missing-await on async assertions i…Medium: Only for issues that actively harm maintainability -- 5+ nearly-identical tests, truly meaningless names like Test1 / test / it1.Low: Cosmetic naming mismatches, minor style preferences, assertion messages that could be better. When in doubt, rate Low.

Permission review

Static risk signals and limitations

Reads files

low · line 6

The documentation asks the agent to read local files, directories, or repositories.

**Language-specific guidance**: Call the `test-analysis-extensions` skill to discover available extension files, then read the file matching the target codebase (e.g., `extensions/dotnet.md`, `extensions/python.md`, `extensions/typescript.m

Reads files

low · line 41

The documentation asks the agent to read local files, directories, or repositories.

Identify the target codebase's language and test framework. Call the `test-analysis-extensions` skill and read the matching extension file. The extension file documents framework-specific anti-pattern markers — what counts as a sleep/wait,

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score93/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars5,277SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
dotnet/skills
Skill path
plugins/dotnet-test/skills/test-anti-patterns/SKILL.md
Commit
2b9056bd9152490cc698c5b3e61c9f9a1c135776
License
MIT
Collected
2026-08-28
Default branch
main
View the original SKILL.md

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: Call the test-analysis-extensions skill to discover available extension files, then read the file matching the target codebase (e.g., extensions/dotnet.md, extensions/python.md, extensions/typescript.md, extensions/go.md). The extension file tells you which sleep / time / random / skip / setup-teardown / mystery-guest APIs to look for in that language.

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

InputRequiredDescription
Test codeYesOne or more test files or classes to analyze
Production codeNoThe code under test, for context on what tests should verify
Specific concernNoA focused area like "flakiness" or "naming" to narrow the review

Workflow

Step 1: Detect language and load extension

Identify the target codebase's language and test framework. Call the test-analysis-extensions skill and read the matching extension file. The extension file documents framework-specific anti-pattern markers — what counts as a sleep/wait, a test marker, a skip, a setup/teardown, a shared-state hot spot, and an integration boundary — so this skill stays language-neutral.

Step 2: Gather the test code

Read the test files the user wants reviewed. If the user points to a directory or project, scan for all test files using the discovery markers in the loaded language extension file (e.g., [TestClass]/[Fact]/[Test] for .NET, test_*.py / def test_* for pytest, *.test.ts / it() for Jest, *Test.java / @Test for JUnit, *_test.go / func TestXxx for Go, *_spec.rb for RSpec, #[test] for Rust, *.Tests.ps1 / Describe for Pester, TEST(...) for GoogleTest, TEST_CASE(...) for Catch2/doctest).

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. The examples are .NET-centric but the patterns generalize — use the loaded language extension file to map each pattern to the framework you are auditing.

Critical -- Tests that give false confidence

Anti-PatternWhat to Look For
No assertionsTest methods that execute code but never assert anything. A passing test without assertions proves nothing. In .NET look for missing Assert.*; in pytest a function with no assert and no pytest.raises; in Jest no expect(...); in JUnit no assert*/assertThat; in Go a test that never calls t.Error*, t.Fatal*, or testify; in RSpec a block with no expect; in Pester no Should. Mock-call verifications (verify(mock), expect(mock).toHaveBeenCalled, Should -Invoke) are real assertions.
Missing await on async assertions (JS/TS, .NET, Python, Kotlin, Swift)expect(promise).resolves.toBe(x) without await/return, pytest-asyncio test with un-awaited coroutine, async Task xUnit test calling Assert.ThrowsAsync without await, Kotest suspending test without runTest, Swift Testing async test without await. These tests silently pass even when the underlying assertion would have failed.
Coverage touchingTest class that methodically calls every public member on a type — often in alphabetical or declaration order — without asserting meaningful outcomes. Each test typically does var result = sut.MethodName(...) (or result = sut.method_name(...), sut.methodName(), sut.MethodName(t)) with no assertion, or only a trivial null/None/nil check. The intent is to inflate code-coverage metrics rather than verify behavior. Distinct from a single assertion-free test: the pattern is systematic coverage of the surface area with no real verification.
Self-referential assertionThe expected value is computed from the same actual value, such as Assert.AreEqual(dto.Name, dto.Name), Assert.AreEqual(result, result), or equivalents. Do not apply this label merely because a valid identity, clone, serialization, or round-trip contract compares output with input: those assertions can fail. Instead check whether the input exercises a transformation and whether independently known representation, field, reference-identity, or invalid-input assertions are missing.
Swallowed exceptionstry { ... } catch { }, catch (Exception) without rethrowing or asserting (.NET); bare except: or except Exception: with pass (Python); try { ... } catch (e) {} (JS/TS/Java); defer recover() without re-panic and no assertion (Go); rescue StandardError with no assertion (Ruby); Result::unwrap_or(...) swallowing errors in a test (Rust); empty catch block (Kotlin/Swift).
Assert in catch block onlytry { Act(); } catch (Exception ex) { Assert.Fail(ex.Message); } (and equivalents in other languages) -- use Assert.ThrowsException / pytest.raises / expect(fn).toThrow / assertThrows / assert.Error(t, err) / #[should_panic] / Should -Throw / EXPECT_THROW instead. The test passes when no exception is thrown even if the result is wrong.
Always-true assertionsAssert.IsTrue(true), Assert.AreEqual(x, x), assert True, expect(true).toBe(true), assert.True(t, true), assert!(true), or conditions that can never fail.
Commented-out assertionsAssertions that were disabled but the test still runs, giving the illusion of coverage.

High -- Tests likely to cause pain

Anti-PatternWhat to Look For
Flakiness indicatorsWall-clock sleeps/waits used for synchronization: Thread.Sleep / Task.Delay (.NET), time.sleep (Python), setTimeout / await new Promise(r => setTimeout(...)) (JS/TS), Thread.sleep (Java/Kotlin), time.Sleep (Go), sleep (Ruby/Bash), std::thread::sleep (Rust), Start-Sleep (Pester), std::this_thread::sleep_for (C++). Wall-clock reads without abstraction: DateTime.Now/UtcNow, datetime.now()/datetime.utcnow(), Date.now() / new Date(), System.currentTimeMillis(), time.Now(), Time.now, Instant::now(), Date()/Date.now, Get-Date, std::chrono::system_clock::now. Unseeded randomness: new Random(), random.random()/random.randint(), Math.random(), new Random() (Java/Kotlin), rand.Int() without seed, rand (Ruby), rand::random() (Rust). Environment-dependent paths (hard-coded C:\..., /tmp/..., network hosts).
Test ordering dependencyStatic/global mutable state modified across tests; setup that doesn't fully reset state ([TestInitialize], setUp, beforeEach, before(:each), BeforeEach, t.Cleanup); tests that fail when run individually but pass in suite (or vice versa). Examples per language: static fields (.NET/Java), module-level globals (Python), top-level let/const in test file (JS/TS), var package globals (Go), class variables (Ruby), static mut/lazy_static!/OnceCell (Rust), $script: variables (PowerShell).
Over-mockingMore mock setup lines than actual test logic. Verifying exact call sequences on mocks rather than outcomes. Mocking types the test owns. Per language: Moq/NSubstitute/FakeItEasy (.NET), unittest.mock / pytest-mock (Python), Jest auto-mocks / Sinon (JS/TS), Mockito/PowerMock (Java), gomock/testify mock (Go), RSpec mocks/mocha (Ruby), mockall (Rust), MockK (Kotlin), Mock cmdlet (Pester), gmock (C++). For a deep mock audit in .NET, use exp-mock-usage-analysis.
Implementation couplingTesting private methods via reflection (MethodInfo.Invoke, getattr in Python, (thing as any) in TS, Field.setAccessible(true) in Java, Object#send in Ruby, internal pub(crate) access in Rust). Asserting on internal state instead of observable behavior. Verifying exact method call counts on collaborators instead of business outcomes.
Broad exception assertionsAssert.ThrowsException<Exception>(...) (.NET) / pytest.raises(Exception) / expect(fn).toThrow(Error) without a message matcher / assertThrows(Exception.class, ...) (Java) / assert.Error(t, err) without checking the kind / expect { ... }.to raise_error without class (RSpec) / #[should_panic] without expected = "..." / Should -Throw without -ExpectedMessage / EXPECT_ANY_THROW instead of EXPECT_THROW(stmt, SpecificType).

Medium -- Maintainability and clarity issues

Anti-PatternWhat to Look For
Poor namingTest names like Test1, TestMethod, test, names that don't describe the scenario or expected outcome. Good naming differs by language convention — see the loaded language extension file (e.g., Add_NegativeNumber_ThrowsArgumentException for .NET, test_add_negative_number_raises_value_error for pytest, addNegativeNumber_throwsArgumentException for Java, 'adds negative number throws' for Jest descriptions, TestAdd_NegativeNumber_ReturnsError for Go).
Magic valuesUnexplained numbers or strings in arrange/assert: Assert.AreEqual(42, result) / assert result == 42 / expect(result).toBe(42) -- what does 42 mean?
Duplicate testsThree or more test methods with near-identical bodies that differ only in a single input value. Should be parametrized: [DataRow]/[Theory]/[TestCase] (.NET), @pytest.mark.parametrize (pytest), test.each / it.each (Jest/Vitest), @ParameterizedTest + @ValueSource (JUnit 5), @DataProvider (TestNG), Go table-driven tests, where / shared examples (RSpec), #[rstest] (Rust), @ParameterizedTest + @MethodSource (Kotlin), -ForEach / -TestCases (Pester), INSTANTIATE_TEST_SUITE_P (GoogleTest), SECTION / GENERATE (Catch2), TEST_CASE_TEMPLATE (doctest). For a detailed duplication analysis in .NET, use exp-test-maintainability. Note: Two tests covering distinct boundary conditions (e.g., zero vs. negative) are NOT duplicates -- separate tests for different edge cases provide clearer failure diagnostics and are a valid practice.
Giant testsTest methods exceeding ~30 lines or testing multiple behaviors at once. Hard to diagnose when they fail.
Assertion messages that repeat the assertionAssert.AreEqual(expected, actual, "Expected and actual are not equal") / assert x == y, "x is not equal to y" / assertEquals(x, y, "values not equal") add no information. Messages should describe the business meaning.
Missing AAA / Given-When-Then separationArrange/Act/Assert (or Given/When/Then for BDD frameworks like RSpec, Kotest behavior specs, Pester) phases are interleaved or indistinguishable.

Low -- Style and hygiene

Anti-PatternWhat to Look For
Unused test infrastructureSetup/teardown hooks that do nothing — [TestInitialize]/[SetUp]/[BeforeEach], setUp/@BeforeEach/@BeforeAll, beforeEach/beforeAll, before(:each)/before(:all), BeforeEach/BeforeAll (Pester), setUpWithError (XCTest) — and test helper methods that are never called.
Unmanaged resourcesTest creates disposable/closeable resources without cleanup: HttpClient/Stream without using (.NET), file/connection without with block or try/finally (Python), FileInputStream without try-with-resources (Java), defer file.Close() missing (Go), connection without ensure (Ruby), Drop not relied on / forgotten close (Rust), missing teardown for temp files / DBs in any language.
Print debuggingLeftover Console.WriteLine / Debug.WriteLine / print() / console.log / System.out.println / fmt.Println / puts / dbg! / Write-Host / std::cout statements used during test development.
Inconsistent naming conventionMix of naming styles in the same test class/module/file (e.g., some use Method_Scenario_Expected, others use ShouldDoSomething).

Step 4: Calibrate severity honestly

Before reporting, re-check each finding against these severity rules:

  • Critical/High: Only for issues that cause tests to give false confidence or be unreliable. A test that always passes regardless of correctness is Critical. Flaky shared state is High. Missing-await on async assertions is Critical (silent pass).
  • Medium: Only for issues that actively harm maintainability -- 5+ nearly-identical tests, truly meaningless names like Test1 / test / it1.
  • Low: Cosmetic naming mismatches, minor style preferences, assertion messages that could be better. When in doubt, rate Low.
  • Use the caller's severity vocabulary consistently. If the caller asks for Critical / Warning / Info, map reliability risks to Warning and maintenance/cosmetic concerns to Info rather than silently collapsing every item into Critical. Severity describes the demonstrated failure mode, not how much prose a finding receives.
  • Separate a systemic finding from its instances. Coverage touching across a facade is one Critical systemic finding whose evidence lists every affected test. All assertion-free instances, including the last facade method, retain the same false-confidence severity. Report 1 finding / 6 affected tests, not six findings plus a seventh summary finding, and do not downgrade one instance merely to manufacture multiple tiers.
  • Do not severity-rank ordinary missing cases as anti-patterns. Adjacent untested branches, exception paths, and boundaries may be useful coverage opportunities, but list them separately from the anti-pattern counts unless a weak existing test specifically creates the gap. They are not Critical merely because the suite has a systemic Critical issue.
  • Not an issue (per-language nuance):
    • Go and Rust table-driven loops with sub-tests (t.Run / for case in cases { ... }) are idiomatic, not "Conditional Test Logic". Do NOT flag.
    • pytest bare assert is the canonical assertion form, not a missing assertion library. Do NOT flag.
    • Go tests use if got != want { t.Errorf(...) } as canonical equality. Do NOT flag as ad-hoc.
    • Separate tests for distinct boundary conditions (zero vs. negative vs. null). Do NOT flag as duplicates.
    • Explicit per-test setup instead of [TestInitialize] / beforeEach (this improves isolation).
    • Tests that are short and clear but could theoretically be consolidated.
    • Round-trip or serialization equality with non-trivial input. It is valid metamorphic evidence; suggest an independent representation assertion when two implementations could share the same bug.
    • Clone value equality. Keep it, and add distinct-reference or mutation- independence evidence when the contract promises a deep copy.
    • A validator or accessor returning the original value when pass-through is the production contract. Missing invalid-input cases are a coverage gap, not proof that the existing assertion is tautological.

IMPORTANT: If the tests are well-written, say so clearly up front. Do not inflate severity to justify the review. A review that finds zero Critical/High issues and only minor Low suggestions is a valid and valuable outcome. Lead with what the tests do well.

Step 5: Report findings

Depth bar — a tidy report that is shallower than an unassisted review is a failure. Before writing, satisfy all five:

  1. Account for every test in scope. Build the complete method/field inventory before summarizing. For a systematic pattern such as coverage touching, enumerate every affected test at least once rather than giving representative examples. A finding table that silently skips tests (or fixtures like an unused static HttpClient field) is incomplete. State the number reviewed.
  2. Verify the production contract before judging the oracle. Inspect the actual transformation, DTO fields, and promised identity/clone semantics. Never invent fields or require lossless round-tripping when production is intentionally lossy.
  3. Make every Critical/High fix complete and specific. Give the replacement assertion with the exact expected value (the computed discount, the exact CSV line, the full expected object), not a // assert something here placeholder.
  4. Name the adjacent gaps the tests should also cover — untested error paths, boundary values, and round-trip/culture-sensitivity risks in the same class. These are part of "what's wrong with my tests", and omitting them is the most common way this review loses to an unassisted one.
  5. Keep the report internally consistent. Summary counts must equal the enumerated findings. Publish a settled conclusion: do all reconsidering before you write, and never leave "wait, that's wrong" / "this should fail but doesn't" reasoning in the output.

Present findings in this structure:

  1. Summary -- Total issues found, broken down by severity (Critical / High / Medium / Low). If tests are well-written, lead with that assessment.
  2. Critical and High findings -- List each with:
    • The anti-pattern name
    • The specific location (file, method name, line)
    • A brief explanation of why it's a problem
    • A concrete fix (show before/after code when helpful)
  3. Medium and Low findings -- Summarize in a table unless the user wants full detail
  4. Positive observations -- Call out things the tests do well (sealed class, specific exception types, data-driven tests, clear AAA structure, proper use of fakes, good naming). Don't only report negatives.

Before publishing, assign each finding a stable identity. A grouped row counts as one finding regardless of how many methods it lists; separate rows count separately. Recompute the summary from those rows. Keep affected tests as a different number so a bundled finding cannot create a hidden count mismatch.

Step 6: Prioritize recommendations

If there are many findings, recommend which to fix first:

  1. Critical -- Fix immediately, these tests may be giving false confidence
  2. High -- Fix soon, these cause flakiness or maintenance burden
  3. Medium/Low -- Fix opportunistically during related edits

Validation

  • Every test method in scope is accounted for (reviewed count stated; none silently skipped)
  • Identity and round-trip findings match the production contract and use only real fields
  • Every finding includes a specific location (not just a general warning)
  • Every Critical/High finding includes a concrete fix with exact expected values
  • Adjacent untested error paths and boundary values are called out
  • Summary counts match the enumerated findings
  • Grouped findings distinguish finding count from affected-test count
  • Adjacent coverage opportunities are not inflated into Critical anti-pattern findings
  • Report covers all categories (assertions, isolation, naming, structure)
  • Positive observations are included alongside problems
  • Recommendations are prioritized by severity

Common Pitfalls

PitfallSolution
Reporting style issues as criticalNaming and formatting are Medium/Low, never Critical
Suggesting rewrites instead of targeted fixesShow minimal diffs -- change the assertion, not the whole test
Flagging intentional design choicesIf Thread.Sleep / time.sleep / time.Sleep is in an integration test testing actual timing, that's not an anti-pattern. Consider context.
Inventing false positives on clean codeIf tests follow best practices, say so. A review finding "0 Critical, 0 High, 1 Low" is perfectly valid. Don't inflate findings to justify the review.
Flagging separate boundary tests as duplicatesTwo tests for zero and negative inputs test different edge cases. Only flag as duplicates when 3+ tests have truly identical bodies differing by a single value.
Rating cosmetic issues as MediumNaming mismatches (e.g., method name says ArgumentException but asserts ArgumentOutOfRangeException) are Low, not Medium -- the test still works correctly.
Ignoring the test frameworkUse the terminology of the framework you loaded from the language extension; don't describe a pytest suite in MSTest terms.
Missing the forest for the treesIf 80% of tests have no assertions, lead with that systemic issue rather than listing every instance
Trading depth for tidinessA severity table and positive observations do not substitute for coverage of every test, exact expected values in fixes, and the adjacent error-path/boundary gaps
Contradicting yourself in the reportReason first, then write one settled verdict per finding — never emit "wait, that's wrong" / "should fail but doesn't" reconsiderations
Counts that don't add upThe summary's per-severity totals must match the findings you listed

Frequently asked questions

What to verify before installation and use

What does the test-anti-patterns source document cover?

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

How do I install test-anti-patterns?

The source record exposes this install command: npx skills add https://github.com/dotnet/skills --skill "plugins/dotnet-test/skills/test-anti-patterns". Inspect the command and pinned source before running it.

Which permission-related actions were detected?

Static rules flagged read-files in the source; the page lists the matching lines and excerpts.

Alternatives

Compare before choosing

Computed 10025,136

alirezarezvani/claude-skills

app-store-optimization

App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist

Computed 975,277

dotnet/skills

migrate-static-to-wrapper

Migrate C# static calls to a wrapper or built-in abstraction the user already named, within named files/projects, including affected fake-based test updates. USE FOR explicit DateTime.UtcNow/Now to TimeProvider, File.* to IFileSystem, existing IEnvironmentReader/ITextFileStore, scoped migrations, constructor injection, or a static API seam that keeps callers compiling and DateTimeKind unchanged. DO NOT USE when the user asks for behavior tests but leaves seam selection open (testability-obstacle

Computed 975,277

dotnet/skills

test-tagging

Classifies existing tests by standard traits and reports their distribution. MUST USE to categorize/tag/label tests, compare happy vs error paths, audit the test mix, or describe coverage shape by test type. Read bodies when names mislead. Apply canonical attributes; otherwise report only. DO NOT USE for test-quality audits, executed coverage or CRAP, behavioral gaps, writing tests, or migration.

Computed 97224

yonatangross/orchestkit

verify

Grade work that already exists and decide whether it can merge. Runs the project's current unit, integration, and E2E suites plus security scanning and type checking, scores every dimension 0-10, and returns a merge verdict with a VERIFIED-vs-CLAIMED evidence manifest. Writes no test files and edits no source. Use when verifying changes are ready to merge. Use /ork:cover instead when the tests still have to be written.