[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-dotnet-assertion-quality":3,"mdc-kt1v30-key":34,"related-repo-dotnet-assertion-quality":2486,"related-org-dotnet-assertion-quality":2589},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":22,"repoUrl":23,"updatedAt":24,"license":25,"forks":26,"topics":27,"repo":29,"sourceUrl":32,"mdContent":33},"assertion-quality","evaluate assertion quality in test suites","Analyzes the variety and depth of assertions across test suites in any language. Use when the user asks to evaluate assertion quality, find shallow tests, identify assertion-free tests (no assertions or only trivial ones like Assert.IsNotNull \u002F toBeTruthy()), flag self-referential or tautological assertions, measure assertion diversity, or audit whether tests verify different facets of behavior. Polyglot: .NET, Python, TS\u002FJS, Java, Go, Ruby, Rust, Swift, Kotlin, PowerShell, C++. DO NOT USE FOR: writing new tests (use code-testing-agent \u002F writing-mstest-tests), mutation reasoning about whether tests would catch a bug (use test-gap-analysis), or a general severity-ranked anti-pattern audit (use test-anti-patterns), fixing or rewriting assertions, or writing, fixing, or modernizing MSTest tests, assertions, or attributes (use writing-mstest-tests).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"dotnet",".NET (Microsoft)","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fdotnet.png",[12,16,19],{"name":13,"slug":14,"type":15},"QA","qa","tag",{"name":17,"slug":18,"type":15},"Code Analysis","code-analysis",{"name":20,"slug":21,"type":15},"Testing","testing",4576,"https:\u002F\u002Fgithub.com\u002Fdotnet\u002Fskills","2026-07-12T08:23:51.277743","MIT",332,[28],"agent-skills",{"repoUrl":23,"stars":22,"forks":26,"topics":30,"description":31},[28],"Repository for skills to assist AI coding agents with .NET and C#","https:\u002F\u002Fgithub.com\u002Fdotnet\u002Fskills\u002Ftree\u002FHEAD\u002Fplugins\u002Fdotnet-test\u002Fskills\u002Fassertion-quality","---\nname: assertion-quality\ndescription: \"Analyzes the variety and depth of assertions across test suites in any language. Use when the user asks to evaluate assertion quality, find shallow tests, identify assertion-free tests (no assertions or only trivial ones like Assert.IsNotNull \u002F toBeTruthy()), flag self-referential or tautological assertions, measure assertion diversity, or audit whether tests verify different facets of behavior. Polyglot: .NET, Python, TS\u002FJS, Java, Go, Ruby, Rust, Swift, Kotlin, PowerShell, C++. DO NOT USE FOR: writing new tests (use code-testing-agent \u002F writing-mstest-tests), mutation reasoning about whether tests would catch a bug (use test-gap-analysis), or a general severity-ranked anti-pattern audit (use test-anti-patterns), fixing or rewriting assertions, or writing, fixing, or modernizing MSTest tests, assertions, or attributes (use writing-mstest-tests).\"\nlicense: MIT\n---\n\n# Assertion Diversity Analysis\n\nAnalyze test code in any supported language to measure how varied and meaningful the assertions are. Produce a metrics report that reveals whether tests verify different facets of correctness — not just \"output equals X\" but also structure, exceptions, state transitions, side effects, and invariants.\n\n> **Language-specific guidance**: Call the `test-analysis-extensions` skill to discover available extension files, then read the file matching the target codebase's language and framework (e.g., `dotnet.md` for .NET, `python.md` for pytest, `typescript.md` for Jest, `go.md` for the standard `testing` package). You MUST read the relevant extension file before classifying assertions, because assertion APIs differ significantly across frameworks.\n\n## Why Assertion Diversity Matters\n\nLow assertion diversity signals shallow testing. Tests may pass while bugs hide in unasserted logic. Common symptoms:\n\n| Problem | Symptom | Consequence |\n|---------|---------|-------------|\n| Trivial assertions | Test contains only `Assert.IsNotNull(result)` \u002F `assert result is not None` \u002F `expect(x).toBeDefined()` | Test passes but doesn't verify correctness |\n| Single-value obsession | Always check one field or return value | Bugs in unasserted logic slip through |\n| No negative assertions | Never check what shouldn't happen | Regressions sneak in through false positives |\n| No state checks | Don't verify object state changes | Missed side-effects or lifecycle issues |\n| No structural checks | Only assert top-level value | Bugs in nested objects go unnoticed |\n| Assertion-free tests | Tests that call but don't verify | Code coverage lies; false security |\n\n## When to Use\n\n- User asks to evaluate assertion quality or depth\n- User asks \"are my tests actually testing anything meaningful?\"\n- User wants to know if test assertions are too shallow or trivial\n- User asks for assertion coverage metrics or diversity analysis\n- User suspects tests give false confidence despite passing\n- The `code-testing-generator` agent (or any test-generation workflow) calls this skill as a pre-completion self-review step on freshly generated tests, before declaring the run finished\n\n## When Not to Use\n\n- User wants to write new tests (use `code-testing-agent` for any language, or `writing-mstest-tests` for MSTest specifically)\n- User wants to detect anti-patterns beyond assertions (use `test-anti-patterns`)\n- User wants to fix or rewrite assertions (help them directly)\n- User asks about code coverage percentages (out of scope — this analyzes assertion quality, not line coverage)\n\n## Inputs\n\n| Input | Required | Description |\n|-------|----------|-------------|\n| Test code | Yes | One or more test files or a test project directory to analyze |\n| Production code | No | The code under test, to evaluate whether assertions cover the important behaviors |\n\n## Workflow\n\n### Step 1: Detect language and load extension\n\nIdentify the target codebase's language and test framework. Call the `test-analysis-extensions` skill and read the matching extension file (e.g., `extensions\u002Fdotnet.md` for .NET, `extensions\u002Fpython.md` for pytest, `extensions\u002Ftypescript.md` for Jest\u002FVitest, `extensions\u002Fgo.md` for Go). The extension file lists the framework-specific assertion APIs you will classify in Step 3.\n\n### Step 2: Gather the test code\n\nRead all test files the user provides. If the user points to a directory or project, scan for all test files using the markers in the language extension file (e.g., `[TestMethod]` for MSTest, `def test_*` for pytest, `it()` \u002F `test()` for Jest, `func TestXxx` for Go).\n\n### Step 3: Classify every assertion\n\nFor each test method, identify all assertions and classify them into these language-neutral categories:\n\n| Category | What it verifies | Examples across languages |\n|----------|------------------|----------------------------|\n| **Equality** | Return value matches expected | `Assert.AreEqual` (MSTest), `Assert.Equal` (xUnit), `assert x == y` (pytest), `expect(x).toBe(y)` (Jest), `assertEquals` (JUnit), `if got != want { t.Error... }` \u002F `assert.Equal(t, want, got)` (Go), `x shouldBe y` (Kotest), `Should -Be` (Pester), `EXPECT_EQ` (GoogleTest) |\n| **Boolean** | Condition holds | `Assert.IsTrue`, `assert flag` (Python), `expect(x).toBeTruthy()` (Jest), `assertTrue` (JUnit), `assert.True(t, ok)` (testify), `x.shouldBeTrue()` (Kotest), `Should -BeTrue` (Pester), `EXPECT_TRUE` |\n| **Null \u002F None \u002F Nil** | Presence\u002Fabsence of value | `Assert.IsNull` (.NET), `assert x is None` (pytest), `expect(x).toBeNull()` (Jest), `assertNull` (JUnit), `assert.Nil(t, v)` (testify), `XCTAssertNil` (XCTest), `Should -BeNullOrEmpty` (Pester) |\n| **Exception \u002F Error** | Error handling behavior | `Assert.Throws\u003CT>()`, `pytest.raises(E)`, `expect(fn).toThrow(E)`, `assertThrows\u003CE>`, `assert.Error(t, err)` \u002F `assert.ErrorIs`, `#[should_panic]` (Rust), `XCTAssertThrowsError`, `Should -Throw`, `EXPECT_THROW` |\n| **Type checks** | Runtime type correctness | `Assert.IsInstanceOfType`, `assert isinstance(x, T)`, `expect(x).toBeInstanceOf(T)`, `assertInstanceOf`, `assert.IsType(t, T{}, v)`, `assert!(matches!(value, Pattern))` (Rust), `Should -BeOfType` |\n| **String** | Text content and format | `StringAssert.Contains`, `assert sub in s`, `expect(s).toMatch(\u002Fx\u002F)`, `assertTrue(s.contains(...))`, `assert.Contains(t, s, sub)`, `s shouldContain sub`, `Should -Match`, `EXPECT_THAT(s, HasSubstr(...))` |\n| **Collection** | Collection contents and structure | `CollectionAssert.Contains`, `assert item in collection`, `expect(arr).toContain(x)`, `assertIterableEquals`, `assert.Contains(t, slice, item)`, `col shouldContainExactly listOf(...)`, `Should -Contain`, `EXPECT_THAT(c, ElementsAre(...))` |\n| **Comparison** | Ordering and magnitude | `Assert.IsTrue(x > y)`, `Is.GreaterThan`, `assert x > y`, `expect(x).toBeGreaterThan(y)`, `assertTrue(x > y)`, `assert.Greater(t, x, y)` (testify) |\n| **Approximate** | Floating-point or tolerance-based | `Assert.AreEqual(expected, actual, delta)`, `pytest.approx(y)`, `expect(x).toBeCloseTo(y)`, `assertEquals(x, y, delta)`, `assert.InDelta(t, x, y, delta)`, `EXPECT_NEAR`, `EXPECT_DOUBLE_EQ` |\n| **Negative** | What should NOT happen | `Assert.AreNotEqual`, `assert x != y`, `expect(x).not.toBe(y)`, `assertNotEquals`, `assert.NotEqual(t, x, y)`, `refute` (Minitest \u002F Ruby), `Should -Not -Be` |\n| **State \u002F Side-effect** | State transitions and side effects | Assertions on object properties after mutation; mock-call verifications: `mock.Verify(...)` (Moq), `mock_method.assert_called_with(...)` (Python `unittest.mock`), `expect(mock).toHaveBeenCalledWith(...)` (Jest), `verify(mock).method(...)` (Mockito), `Should -Invoke` (Pester), `expect { code }.to change(obj, :attr)` (RSpec) |\n| **Structural \u002F Deep** | Deep object correctness | `Assert.AreEqual` with rich-equality types, `assertThat(obj).usingRecursiveComparison()` (AssertJ), `.toEqual({...})` (Jest deep equality), `cmp.Diff` (Go go-cmp), snapshot tests (`.toMatchSnapshot()`, `syrupy`, `SnapshotTesting`), `assertThat(col).extracting(...)` (AssertJ chains) |\n\nA single assertion can belong to multiple categories (e.g., `Assert.AreNotEqual` is both Equality and Negative; `expect(mock).toHaveBeenCalledWith(...)` is both State\u002FSide-effect and a specific-call assertion).\n\nRead the loaded language extension file for the exact framework-specific list of assertion APIs.\n\n### Step 4: Compute metrics\n\nCalculate these metrics for the test suite:\n\n#### Per-test metrics\n- **Assertion count**: Number of assertions in each test method\n- **Assertion categories**: Which categories each test uses\n\n#### Suite-wide metrics\n- **Average assertions per test**: Total assertions \u002F total test methods\n- **Assertion type spread**: Number of distinct assertion categories used across the suite (out of 12)\n- **Tests with zero assertions**: Count and percentage of test methods with no assertions at all\n- **Tests with only trivial assertions**: Count and percentage of tests where every assertion is only a null check or `Assert.IsTrue(true)` — trivial means no meaningful value verification\n- **Tests with self-referential assertions**: Count and percentage of tests whose assertions compare an input to a round-tripped or identity-transformed version of itself (e.g., `Assert.AreEqual(input, Parse(input.ToString()))`) or assert a field against itself (`Assert.AreEqual(dto.Name, dto.Name)`). These are tautological — they verify the plumbing, not the behavior.\n- **Tests with negative assertions**: Count and percentage (target: at least 10% of tests should verify what should NOT happen)\n- **Tests with exception assertions**: Count and percentage\n- **Tests with state\u002Fside-effect assertions**: Count and percentage\n- **Tests with structural\u002Fdeep assertions**: Count and percentage\n- **Single-category tests**: Count and percentage of tests that use only one assertion category\n\n### Step 5: Apply calibration rules\n\nBefore reporting, calibrate findings:\n\n- **Trivial means truly trivial.** A null\u002FNone\u002Fnil check alone is trivial (`Assert.IsNotNull(result)`, `assert result is not None`, `expect(x).toBeDefined()`). But a null check followed by a meaningful value assertion is not trivial — the null check is a guard before the real assertion. Only flag a test as \"trivial\" if it has no meaningful value assertions.\n- **Boolean assertions checking meaningful conditions are not trivial.** `Assert.IsTrue(result.IsValid)` \u002F `assert result.is_valid` \u002F `expect(result.isValid).toBe(true)` check a specific property — these are Boolean assertions, not trivial ones. Always-true assertions (`Assert.IsTrue(true)`, `assert True`, `expect(true).toBe(true)`) are trivial.\n- **Consider the test's intent.** A test for a void method that verifies state change on a dependency is legitimate even if it only uses one Boolean assertion.\n- **Exception tests are inherently low-assertion-count.** `Assert.ThrowsException\u003CT>(() => ...)` \u002F `with pytest.raises(E): ...` \u002F `expect(fn).toThrow(E)` \u002F `#[should_panic]` may be the only assertion — that's fine for exception-focused tests. Don't penalize them for low assertion count.\n- **Mock-call verifications and bare assertion forms count.** Treat `verify(mock).method(...)` (Mockito), `expect(mock).toHaveBeenCalledWith(...)` (Jest), `Should -Invoke` (Pester), `bare assert` (pytest), `if got != want { t.Errorf(...) }` (Go) all as real assertions of the appropriate category. Do not treat them as missing-framework-API smells.\n- **Snapshot assertions** (`.toMatchSnapshot()`, `syrupy`, `SnapshotTesting`) count as Structural\u002FDeep assertions. Flag stale or never-updated snapshots separately.\n- **Property-based tests** (`@given` Hypothesis, `proptest!`, `forAll` Kotest) generate assertions implicitly through generated cases — count the inner assertion logic, not the outer scaffold.\n- **Don't conflate diversity with volume.** A test with 20 equality assertions has high volume but low diversity. A test with one equality, one null check, and one exception assertion has low volume but good diversity.\n- **Self-referential assertions are not meaningful equality checks.** Asserting that an output equals an input round-trip looks like a real equality assertion but is tautological when the operation under test is expected to be identity. Flag these separately from normal equality assertions. If the test's *purpose* is to verify a round-trip (serialize\u002Fdeserialize, encode\u002Fdecode), the assertion is valid — but it should be accompanied by assertions on non-trivial inputs that exercise the transformation.\n- **If assertions are well-diversified, say so.** A report concluding the suite has good diversity is perfectly valid.\n\n### Step 6: Report findings\n\n**Scale the report depth to the size and complexity of the suite.** The structure below is the full template for a substantial suite (roughly 15+ tests or a multi-file project). For a small or simple input (a single file with only a handful of tests), do not emit every section — a padded multi-section dashboard on a trivial input reads as noise and buries the answer. Instead, answer the user's question directly and concisely: which tests are assertion-free or trivial-only, the overall assertion-quality verdict, and concrete recommendations (still distinguishing intentional smoke tests from tests masquerading as real verification). Use only the sections that carry real signal for the input at hand; a short metric summary plus the assertion-free list and recommendations is often enough. Never omit the rubric-relevant substance (assertion-free\u002Ftrivial identification, the quality verdict, and concrete recommendations) — only trim structural overhead that adds no information.\n\nPresent the analysis in this structure:\n\n1. **Summary Dashboard** — A quick-reference table of key metrics:\n   ```\n   | Metric                        | Value  | Assessment |\n   |-------------------------------|--------|------------|\n   | Total tests                   | 25     | —          |\n   | Average assertions per test   | 2.4    | Moderate   |\n   | Assertion type spread         | 5\u002F12   | Low        |\n   | Tests with zero assertions    | 3 (12%)| Concerning |\n   | Tests with only trivial asserts | 4 (16%)| Acceptable |\n   | Tests with negative assertions | 2 (8%) | Below target |\n   | Single-category tests         | 15 (60%)| High       |\n   ```\n\n2. **Category Breakdown** — For each assertion category, show:\n   - How many tests use it\n   - Representative examples from the code\n   - Whether it's overused or underused relative to the code under test\n\n3. **Gap Analysis** — Based on the production code (if available), identify:\n   - Behaviors that are tested but only with equality checks\n   - Error paths with no exception assertions\n   - State-changing methods with no state verification\n   - Collections returned but never checked for contents\n\n4. **Recommendations** — Prioritized list of improvements:\n   - Which tests would benefit most from additional assertion types\n   - Which assertion categories are missing and why they matter\n   - Concrete examples of assertions that could be added\n\n5. **Assertion-free tests** — If any exist, list each one with its method name and what it appears to be testing, so the user can decide whether to add assertions or mark them as intentional smoke tests.\n\n## Validation\n\n- [ ] Every assertion in the test suite was classified into at least one category\n- [ ] Metrics are computed correctly (counts add up)\n- [ ] Trivial-assertion tests are correctly identified (not over-flagged)\n- [ ] Exception tests are not penalized for low assertion count\n- [ ] Boolean assertions on meaningful properties are not classified as trivial\n- [ ] Recommendations are concrete (name specific test methods and suggest specific assertion types)\n- [ ] If the suite has good diversity, the report acknowledges this\n\n## Common Pitfalls\n\n| Pitfall | Solution |\n|---------|----------|\n| Penalizing exception tests for low assertion count | Exception assertions are complete on their own — skip count warnings for these |\n| Flagging null\u002FNone\u002Fnil checks before value checks as trivial | Only flag tests where the null\u002FNone\u002Fnil check is the ONLY assertion |\n| Counting any Boolean assertion as trivial | Only always-true assertions (`Assert.IsTrue(true)`, `assert True`, `expect(true).toBe(true)`) are trivial |\n| Ignoring framework differences | Each framework has distinct assertion APIs — always read the matching language extension first. MSTest's `Assert.AreEqual`, xUnit's `Assert.Equal`, NUnit's `Is.EqualTo`, pytest's bare `assert ==`, Jest's `expect().toBe()`, Go's `if … { t.Error… }` all map to the **Equality** category |\n| Treating bare assertion forms as missing-framework | Bare `assert` (pytest), `if got != want { t.Error... }` (Go), and `assert!()` (Rust) are canonical — count them in the right category |\n| Treating mock-call verifications as assertion-free | `verify(mock).method(...)`, `expect(mock).toHaveBeenCalledWith(...)`, `Should -Invoke` are State\u002FSide-effect assertions |\n| Recommending diversity for diversity's sake | Only suggest adding assertion types that would catch real bugs in the code under test |\n| Missing implicit assertions | Exception assertions are both Exception and Negative; snapshot\u002Fproperty-based tests are real assertions with implicit structure |\n| Async tests with unawaited assertions | TUnit, Jest with `.resolves`\u002F`.rejects`, pytest-asyncio, Swift Testing, and Kotest all silently pass tests where assertions are not `await`ed — treat as assertion-free even when assertion calls are present |\n",{"data":35,"body":36},{"name":4,"description":6,"license":25},{"type":37,"children":38},"root",[39,48,54,117,124,129,291,297,340,346,393,399,462,468,475,517,523,565,571,576,1504,1523,1528,1534,1539,1546,1569,1575,1700,1706,1711,1984,1990,2000,2005,2129,2135,2207,2213],{"type":40,"tag":41,"props":42,"children":44},"element","h1",{"id":43},"assertion-diversity-analysis",[45],{"type":46,"value":47},"text","Assertion Diversity Analysis",{"type":40,"tag":49,"props":50,"children":51},"p",{},[52],{"type":46,"value":53},"Analyze test code in any supported language to measure how varied and meaningful the assertions are. Produce a metrics report that reveals whether tests verify different facets of correctness — not just \"output equals X\" but also structure, exceptions, state transitions, side effects, and invariants.",{"type":40,"tag":55,"props":56,"children":57},"blockquote",{},[58],{"type":40,"tag":49,"props":59,"children":60},{},[61,67,69,76,78,84,86,92,94,100,102,108,110,115],{"type":40,"tag":62,"props":63,"children":64},"strong",{},[65],{"type":46,"value":66},"Language-specific guidance",{"type":46,"value":68},": Call the ",{"type":40,"tag":70,"props":71,"children":73},"code",{"className":72},[],[74],{"type":46,"value":75},"test-analysis-extensions",{"type":46,"value":77}," skill to discover available extension files, then read the file matching the target codebase's language and framework (e.g., ",{"type":40,"tag":70,"props":79,"children":81},{"className":80},[],[82],{"type":46,"value":83},"dotnet.md",{"type":46,"value":85}," for .NET, ",{"type":40,"tag":70,"props":87,"children":89},{"className":88},[],[90],{"type":46,"value":91},"python.md",{"type":46,"value":93}," for pytest, ",{"type":40,"tag":70,"props":95,"children":97},{"className":96},[],[98],{"type":46,"value":99},"typescript.md",{"type":46,"value":101}," for Jest, ",{"type":40,"tag":70,"props":103,"children":105},{"className":104},[],[106],{"type":46,"value":107},"go.md",{"type":46,"value":109}," for the standard ",{"type":40,"tag":70,"props":111,"children":113},{"className":112},[],[114],{"type":46,"value":21},{"type":46,"value":116}," package). You MUST read the relevant extension file before classifying assertions, because assertion APIs differ significantly across frameworks.",{"type":40,"tag":118,"props":119,"children":121},"h2",{"id":120},"why-assertion-diversity-matters",[122],{"type":46,"value":123},"Why Assertion Diversity Matters",{"type":40,"tag":49,"props":125,"children":126},{},[127],{"type":46,"value":128},"Low assertion diversity signals shallow testing. Tests may pass while bugs hide in unasserted logic. Common symptoms:",{"type":40,"tag":130,"props":131,"children":132},"table",{},[133,157],{"type":40,"tag":134,"props":135,"children":136},"thead",{},[137],{"type":40,"tag":138,"props":139,"children":140},"tr",{},[141,147,152],{"type":40,"tag":142,"props":143,"children":144},"th",{},[145],{"type":46,"value":146},"Problem",{"type":40,"tag":142,"props":148,"children":149},{},[150],{"type":46,"value":151},"Symptom",{"type":40,"tag":142,"props":153,"children":154},{},[155],{"type":46,"value":156},"Consequence",{"type":40,"tag":158,"props":159,"children":160},"tbody",{},[161,201,219,237,255,273],{"type":40,"tag":138,"props":162,"children":163},{},[164,170,196],{"type":40,"tag":165,"props":166,"children":167},"td",{},[168],{"type":46,"value":169},"Trivial assertions",{"type":40,"tag":165,"props":171,"children":172},{},[173,175,181,183,189,190],{"type":46,"value":174},"Test contains only ",{"type":40,"tag":70,"props":176,"children":178},{"className":177},[],[179],{"type":46,"value":180},"Assert.IsNotNull(result)",{"type":46,"value":182}," \u002F ",{"type":40,"tag":70,"props":184,"children":186},{"className":185},[],[187],{"type":46,"value":188},"assert result is not None",{"type":46,"value":182},{"type":40,"tag":70,"props":191,"children":193},{"className":192},[],[194],{"type":46,"value":195},"expect(x).toBeDefined()",{"type":40,"tag":165,"props":197,"children":198},{},[199],{"type":46,"value":200},"Test passes but doesn't verify correctness",{"type":40,"tag":138,"props":202,"children":203},{},[204,209,214],{"type":40,"tag":165,"props":205,"children":206},{},[207],{"type":46,"value":208},"Single-value obsession",{"type":40,"tag":165,"props":210,"children":211},{},[212],{"type":46,"value":213},"Always check one field or return value",{"type":40,"tag":165,"props":215,"children":216},{},[217],{"type":46,"value":218},"Bugs in unasserted logic slip through",{"type":40,"tag":138,"props":220,"children":221},{},[222,227,232],{"type":40,"tag":165,"props":223,"children":224},{},[225],{"type":46,"value":226},"No negative assertions",{"type":40,"tag":165,"props":228,"children":229},{},[230],{"type":46,"value":231},"Never check what shouldn't happen",{"type":40,"tag":165,"props":233,"children":234},{},[235],{"type":46,"value":236},"Regressions sneak in through false positives",{"type":40,"tag":138,"props":238,"children":239},{},[240,245,250],{"type":40,"tag":165,"props":241,"children":242},{},[243],{"type":46,"value":244},"No state checks",{"type":40,"tag":165,"props":246,"children":247},{},[248],{"type":46,"value":249},"Don't verify object state changes",{"type":40,"tag":165,"props":251,"children":252},{},[253],{"type":46,"value":254},"Missed side-effects or lifecycle issues",{"type":40,"tag":138,"props":256,"children":257},{},[258,263,268],{"type":40,"tag":165,"props":259,"children":260},{},[261],{"type":46,"value":262},"No structural checks",{"type":40,"tag":165,"props":264,"children":265},{},[266],{"type":46,"value":267},"Only assert top-level value",{"type":40,"tag":165,"props":269,"children":270},{},[271],{"type":46,"value":272},"Bugs in nested objects go unnoticed",{"type":40,"tag":138,"props":274,"children":275},{},[276,281,286],{"type":40,"tag":165,"props":277,"children":278},{},[279],{"type":46,"value":280},"Assertion-free tests",{"type":40,"tag":165,"props":282,"children":283},{},[284],{"type":46,"value":285},"Tests that call but don't verify",{"type":40,"tag":165,"props":287,"children":288},{},[289],{"type":46,"value":290},"Code coverage lies; false security",{"type":40,"tag":118,"props":292,"children":294},{"id":293},"when-to-use",[295],{"type":46,"value":296},"When to Use",{"type":40,"tag":298,"props":299,"children":300},"ul",{},[301,307,312,317,322,327],{"type":40,"tag":302,"props":303,"children":304},"li",{},[305],{"type":46,"value":306},"User asks to evaluate assertion quality or depth",{"type":40,"tag":302,"props":308,"children":309},{},[310],{"type":46,"value":311},"User asks \"are my tests actually testing anything meaningful?\"",{"type":40,"tag":302,"props":313,"children":314},{},[315],{"type":46,"value":316},"User wants to know if test assertions are too shallow or trivial",{"type":40,"tag":302,"props":318,"children":319},{},[320],{"type":46,"value":321},"User asks for assertion coverage metrics or diversity analysis",{"type":40,"tag":302,"props":323,"children":324},{},[325],{"type":46,"value":326},"User suspects tests give false confidence despite passing",{"type":40,"tag":302,"props":328,"children":329},{},[330,332,338],{"type":46,"value":331},"The ",{"type":40,"tag":70,"props":333,"children":335},{"className":334},[],[336],{"type":46,"value":337},"code-testing-generator",{"type":46,"value":339}," agent (or any test-generation workflow) calls this skill as a pre-completion self-review step on freshly generated tests, before declaring the run finished",{"type":40,"tag":118,"props":341,"children":343},{"id":342},"when-not-to-use",[344],{"type":46,"value":345},"When Not to Use",{"type":40,"tag":298,"props":347,"children":348},{},[349,370,383,388],{"type":40,"tag":302,"props":350,"children":351},{},[352,354,360,362,368],{"type":46,"value":353},"User wants to write new tests (use ",{"type":40,"tag":70,"props":355,"children":357},{"className":356},[],[358],{"type":46,"value":359},"code-testing-agent",{"type":46,"value":361}," for any language, or ",{"type":40,"tag":70,"props":363,"children":365},{"className":364},[],[366],{"type":46,"value":367},"writing-mstest-tests",{"type":46,"value":369}," for MSTest specifically)",{"type":40,"tag":302,"props":371,"children":372},{},[373,375,381],{"type":46,"value":374},"User wants to detect anti-patterns beyond assertions (use ",{"type":40,"tag":70,"props":376,"children":378},{"className":377},[],[379],{"type":46,"value":380},"test-anti-patterns",{"type":46,"value":382},")",{"type":40,"tag":302,"props":384,"children":385},{},[386],{"type":46,"value":387},"User wants to fix or rewrite assertions (help them directly)",{"type":40,"tag":302,"props":389,"children":390},{},[391],{"type":46,"value":392},"User asks about code coverage percentages (out of scope — this analyzes assertion quality, not line coverage)",{"type":40,"tag":118,"props":394,"children":396},{"id":395},"inputs",[397],{"type":46,"value":398},"Inputs",{"type":40,"tag":130,"props":400,"children":401},{},[402,423],{"type":40,"tag":134,"props":403,"children":404},{},[405],{"type":40,"tag":138,"props":406,"children":407},{},[408,413,418],{"type":40,"tag":142,"props":409,"children":410},{},[411],{"type":46,"value":412},"Input",{"type":40,"tag":142,"props":414,"children":415},{},[416],{"type":46,"value":417},"Required",{"type":40,"tag":142,"props":419,"children":420},{},[421],{"type":46,"value":422},"Description",{"type":40,"tag":158,"props":424,"children":425},{},[426,444],{"type":40,"tag":138,"props":427,"children":428},{},[429,434,439],{"type":40,"tag":165,"props":430,"children":431},{},[432],{"type":46,"value":433},"Test code",{"type":40,"tag":165,"props":435,"children":436},{},[437],{"type":46,"value":438},"Yes",{"type":40,"tag":165,"props":440,"children":441},{},[442],{"type":46,"value":443},"One or more test files or a test project directory to analyze",{"type":40,"tag":138,"props":445,"children":446},{},[447,452,457],{"type":40,"tag":165,"props":448,"children":449},{},[450],{"type":46,"value":451},"Production code",{"type":40,"tag":165,"props":453,"children":454},{},[455],{"type":46,"value":456},"No",{"type":40,"tag":165,"props":458,"children":459},{},[460],{"type":46,"value":461},"The code under test, to evaluate whether assertions cover the important behaviors",{"type":40,"tag":118,"props":463,"children":465},{"id":464},"workflow",[466],{"type":46,"value":467},"Workflow",{"type":40,"tag":469,"props":470,"children":472},"h3",{"id":471},"step-1-detect-language-and-load-extension",[473],{"type":46,"value":474},"Step 1: Detect language and load extension",{"type":40,"tag":49,"props":476,"children":477},{},[478,480,485,487,493,494,500,501,507,509,515],{"type":46,"value":479},"Identify the target codebase's language and test framework. Call the ",{"type":40,"tag":70,"props":481,"children":483},{"className":482},[],[484],{"type":46,"value":75},{"type":46,"value":486}," skill and read the matching extension file (e.g., ",{"type":40,"tag":70,"props":488,"children":490},{"className":489},[],[491],{"type":46,"value":492},"extensions\u002Fdotnet.md",{"type":46,"value":85},{"type":40,"tag":70,"props":495,"children":497},{"className":496},[],[498],{"type":46,"value":499},"extensions\u002Fpython.md",{"type":46,"value":93},{"type":40,"tag":70,"props":502,"children":504},{"className":503},[],[505],{"type":46,"value":506},"extensions\u002Ftypescript.md",{"type":46,"value":508}," for Jest\u002FVitest, ",{"type":40,"tag":70,"props":510,"children":512},{"className":511},[],[513],{"type":46,"value":514},"extensions\u002Fgo.md",{"type":46,"value":516}," for Go). The extension file lists the framework-specific assertion APIs you will classify in Step 3.",{"type":40,"tag":469,"props":518,"children":520},{"id":519},"step-2-gather-the-test-code",[521],{"type":46,"value":522},"Step 2: Gather the test code",{"type":40,"tag":49,"props":524,"children":525},{},[526,528,534,536,542,543,549,550,556,557,563],{"type":46,"value":527},"Read all test files the user provides. If the user points to a directory or project, scan for all test files using the markers in the language extension file (e.g., ",{"type":40,"tag":70,"props":529,"children":531},{"className":530},[],[532],{"type":46,"value":533},"[TestMethod]",{"type":46,"value":535}," for MSTest, ",{"type":40,"tag":70,"props":537,"children":539},{"className":538},[],[540],{"type":46,"value":541},"def test_*",{"type":46,"value":93},{"type":40,"tag":70,"props":544,"children":546},{"className":545},[],[547],{"type":46,"value":548},"it()",{"type":46,"value":182},{"type":40,"tag":70,"props":551,"children":553},{"className":552},[],[554],{"type":46,"value":555},"test()",{"type":46,"value":101},{"type":40,"tag":70,"props":558,"children":560},{"className":559},[],[561],{"type":46,"value":562},"func TestXxx",{"type":46,"value":564}," for Go).",{"type":40,"tag":469,"props":566,"children":568},{"id":567},"step-3-classify-every-assertion",[569],{"type":46,"value":570},"Step 3: Classify every assertion",{"type":40,"tag":49,"props":572,"children":573},{},[574],{"type":46,"value":575},"For each test method, identify all assertions and classify them into these language-neutral categories:",{"type":40,"tag":130,"props":577,"children":578},{},[579,600],{"type":40,"tag":134,"props":580,"children":581},{},[582],{"type":40,"tag":138,"props":583,"children":584},{},[585,590,595],{"type":40,"tag":142,"props":586,"children":587},{},[588],{"type":46,"value":589},"Category",{"type":40,"tag":142,"props":591,"children":592},{},[593],{"type":46,"value":594},"What it verifies",{"type":40,"tag":142,"props":596,"children":597},{},[598],{"type":46,"value":599},"Examples across languages",{"type":40,"tag":158,"props":601,"children":602},{},[603,701,778,849,938,1005,1079,1153,1215,1282,1350,1425],{"type":40,"tag":138,"props":604,"children":605},{},[606,614,619],{"type":40,"tag":165,"props":607,"children":608},{},[609],{"type":40,"tag":62,"props":610,"children":611},{},[612],{"type":46,"value":613},"Equality",{"type":40,"tag":165,"props":615,"children":616},{},[617],{"type":46,"value":618},"Return value matches expected",{"type":40,"tag":165,"props":620,"children":621},{},[622,628,630,636,638,644,646,652,654,660,662,668,669,675,677,683,685,691,693,699],{"type":40,"tag":70,"props":623,"children":625},{"className":624},[],[626],{"type":46,"value":627},"Assert.AreEqual",{"type":46,"value":629}," (MSTest), ",{"type":40,"tag":70,"props":631,"children":633},{"className":632},[],[634],{"type":46,"value":635},"Assert.Equal",{"type":46,"value":637}," (xUnit), ",{"type":40,"tag":70,"props":639,"children":641},{"className":640},[],[642],{"type":46,"value":643},"assert x == y",{"type":46,"value":645}," (pytest), ",{"type":40,"tag":70,"props":647,"children":649},{"className":648},[],[650],{"type":46,"value":651},"expect(x).toBe(y)",{"type":46,"value":653}," (Jest), ",{"type":40,"tag":70,"props":655,"children":657},{"className":656},[],[658],{"type":46,"value":659},"assertEquals",{"type":46,"value":661}," (JUnit), ",{"type":40,"tag":70,"props":663,"children":665},{"className":664},[],[666],{"type":46,"value":667},"if got != want { t.Error... }",{"type":46,"value":182},{"type":40,"tag":70,"props":670,"children":672},{"className":671},[],[673],{"type":46,"value":674},"assert.Equal(t, want, got)",{"type":46,"value":676}," (Go), ",{"type":40,"tag":70,"props":678,"children":680},{"className":679},[],[681],{"type":46,"value":682},"x shouldBe y",{"type":46,"value":684}," (Kotest), ",{"type":40,"tag":70,"props":686,"children":688},{"className":687},[],[689],{"type":46,"value":690},"Should -Be",{"type":46,"value":692}," (Pester), ",{"type":40,"tag":70,"props":694,"children":696},{"className":695},[],[697],{"type":46,"value":698},"EXPECT_EQ",{"type":46,"value":700}," (GoogleTest)",{"type":40,"tag":138,"props":702,"children":703},{},[704,712,717],{"type":40,"tag":165,"props":705,"children":706},{},[707],{"type":40,"tag":62,"props":708,"children":709},{},[710],{"type":46,"value":711},"Boolean",{"type":40,"tag":165,"props":713,"children":714},{},[715],{"type":46,"value":716},"Condition holds",{"type":40,"tag":165,"props":718,"children":719},{},[720,726,728,734,736,742,743,749,750,756,758,764,765,771,772],{"type":40,"tag":70,"props":721,"children":723},{"className":722},[],[724],{"type":46,"value":725},"Assert.IsTrue",{"type":46,"value":727},", ",{"type":40,"tag":70,"props":729,"children":731},{"className":730},[],[732],{"type":46,"value":733},"assert flag",{"type":46,"value":735}," (Python), ",{"type":40,"tag":70,"props":737,"children":739},{"className":738},[],[740],{"type":46,"value":741},"expect(x).toBeTruthy()",{"type":46,"value":653},{"type":40,"tag":70,"props":744,"children":746},{"className":745},[],[747],{"type":46,"value":748},"assertTrue",{"type":46,"value":661},{"type":40,"tag":70,"props":751,"children":753},{"className":752},[],[754],{"type":46,"value":755},"assert.True(t, ok)",{"type":46,"value":757}," (testify), ",{"type":40,"tag":70,"props":759,"children":761},{"className":760},[],[762],{"type":46,"value":763},"x.shouldBeTrue()",{"type":46,"value":684},{"type":40,"tag":70,"props":766,"children":768},{"className":767},[],[769],{"type":46,"value":770},"Should -BeTrue",{"type":46,"value":692},{"type":40,"tag":70,"props":773,"children":775},{"className":774},[],[776],{"type":46,"value":777},"EXPECT_TRUE",{"type":40,"tag":138,"props":779,"children":780},{},[781,789,794],{"type":40,"tag":165,"props":782,"children":783},{},[784],{"type":40,"tag":62,"props":785,"children":786},{},[787],{"type":46,"value":788},"Null \u002F None \u002F Nil",{"type":40,"tag":165,"props":790,"children":791},{},[792],{"type":46,"value":793},"Presence\u002Fabsence of value",{"type":40,"tag":165,"props":795,"children":796},{},[797,803,805,811,812,818,819,825,826,832,833,839,841,847],{"type":40,"tag":70,"props":798,"children":800},{"className":799},[],[801],{"type":46,"value":802},"Assert.IsNull",{"type":46,"value":804}," (.NET), ",{"type":40,"tag":70,"props":806,"children":808},{"className":807},[],[809],{"type":46,"value":810},"assert x is None",{"type":46,"value":645},{"type":40,"tag":70,"props":813,"children":815},{"className":814},[],[816],{"type":46,"value":817},"expect(x).toBeNull()",{"type":46,"value":653},{"type":40,"tag":70,"props":820,"children":822},{"className":821},[],[823],{"type":46,"value":824},"assertNull",{"type":46,"value":661},{"type":40,"tag":70,"props":827,"children":829},{"className":828},[],[830],{"type":46,"value":831},"assert.Nil(t, v)",{"type":46,"value":757},{"type":40,"tag":70,"props":834,"children":836},{"className":835},[],[837],{"type":46,"value":838},"XCTAssertNil",{"type":46,"value":840}," (XCTest), ",{"type":40,"tag":70,"props":842,"children":844},{"className":843},[],[845],{"type":46,"value":846},"Should -BeNullOrEmpty",{"type":46,"value":848}," (Pester)",{"type":40,"tag":138,"props":850,"children":851},{},[852,860,865],{"type":40,"tag":165,"props":853,"children":854},{},[855],{"type":40,"tag":62,"props":856,"children":857},{},[858],{"type":46,"value":859},"Exception \u002F Error",{"type":40,"tag":165,"props":861,"children":862},{},[863],{"type":46,"value":864},"Error handling behavior",{"type":40,"tag":165,"props":866,"children":867},{},[868,874,875,881,882,888,889,895,896,902,903,909,910,916,918,924,925,931,932],{"type":40,"tag":70,"props":869,"children":871},{"className":870},[],[872],{"type":46,"value":873},"Assert.Throws\u003CT>()",{"type":46,"value":727},{"type":40,"tag":70,"props":876,"children":878},{"className":877},[],[879],{"type":46,"value":880},"pytest.raises(E)",{"type":46,"value":727},{"type":40,"tag":70,"props":883,"children":885},{"className":884},[],[886],{"type":46,"value":887},"expect(fn).toThrow(E)",{"type":46,"value":727},{"type":40,"tag":70,"props":890,"children":892},{"className":891},[],[893],{"type":46,"value":894},"assertThrows\u003CE>",{"type":46,"value":727},{"type":40,"tag":70,"props":897,"children":899},{"className":898},[],[900],{"type":46,"value":901},"assert.Error(t, err)",{"type":46,"value":182},{"type":40,"tag":70,"props":904,"children":906},{"className":905},[],[907],{"type":46,"value":908},"assert.ErrorIs",{"type":46,"value":727},{"type":40,"tag":70,"props":911,"children":913},{"className":912},[],[914],{"type":46,"value":915},"#[should_panic]",{"type":46,"value":917}," (Rust), ",{"type":40,"tag":70,"props":919,"children":921},{"className":920},[],[922],{"type":46,"value":923},"XCTAssertThrowsError",{"type":46,"value":727},{"type":40,"tag":70,"props":926,"children":928},{"className":927},[],[929],{"type":46,"value":930},"Should -Throw",{"type":46,"value":727},{"type":40,"tag":70,"props":933,"children":935},{"className":934},[],[936],{"type":46,"value":937},"EXPECT_THROW",{"type":40,"tag":138,"props":939,"children":940},{},[941,949,954],{"type":40,"tag":165,"props":942,"children":943},{},[944],{"type":40,"tag":62,"props":945,"children":946},{},[947],{"type":46,"value":948},"Type checks",{"type":40,"tag":165,"props":950,"children":951},{},[952],{"type":46,"value":953},"Runtime type correctness",{"type":40,"tag":165,"props":955,"children":956},{},[957,963,964,970,971,977,978,984,985,991,992,998,999],{"type":40,"tag":70,"props":958,"children":960},{"className":959},[],[961],{"type":46,"value":962},"Assert.IsInstanceOfType",{"type":46,"value":727},{"type":40,"tag":70,"props":965,"children":967},{"className":966},[],[968],{"type":46,"value":969},"assert isinstance(x, T)",{"type":46,"value":727},{"type":40,"tag":70,"props":972,"children":974},{"className":973},[],[975],{"type":46,"value":976},"expect(x).toBeInstanceOf(T)",{"type":46,"value":727},{"type":40,"tag":70,"props":979,"children":981},{"className":980},[],[982],{"type":46,"value":983},"assertInstanceOf",{"type":46,"value":727},{"type":40,"tag":70,"props":986,"children":988},{"className":987},[],[989],{"type":46,"value":990},"assert.IsType(t, T{}, v)",{"type":46,"value":727},{"type":40,"tag":70,"props":993,"children":995},{"className":994},[],[996],{"type":46,"value":997},"assert!(matches!(value, Pattern))",{"type":46,"value":917},{"type":40,"tag":70,"props":1000,"children":1002},{"className":1001},[],[1003],{"type":46,"value":1004},"Should -BeOfType",{"type":40,"tag":138,"props":1006,"children":1007},{},[1008,1016,1021],{"type":40,"tag":165,"props":1009,"children":1010},{},[1011],{"type":40,"tag":62,"props":1012,"children":1013},{},[1014],{"type":46,"value":1015},"String",{"type":40,"tag":165,"props":1017,"children":1018},{},[1019],{"type":46,"value":1020},"Text content and format",{"type":40,"tag":165,"props":1022,"children":1023},{},[1024,1030,1031,1037,1038,1044,1045,1051,1052,1058,1059,1065,1066,1072,1073],{"type":40,"tag":70,"props":1025,"children":1027},{"className":1026},[],[1028],{"type":46,"value":1029},"StringAssert.Contains",{"type":46,"value":727},{"type":40,"tag":70,"props":1032,"children":1034},{"className":1033},[],[1035],{"type":46,"value":1036},"assert sub in s",{"type":46,"value":727},{"type":40,"tag":70,"props":1039,"children":1041},{"className":1040},[],[1042],{"type":46,"value":1043},"expect(s).toMatch(\u002Fx\u002F)",{"type":46,"value":727},{"type":40,"tag":70,"props":1046,"children":1048},{"className":1047},[],[1049],{"type":46,"value":1050},"assertTrue(s.contains(...))",{"type":46,"value":727},{"type":40,"tag":70,"props":1053,"children":1055},{"className":1054},[],[1056],{"type":46,"value":1057},"assert.Contains(t, s, sub)",{"type":46,"value":727},{"type":40,"tag":70,"props":1060,"children":1062},{"className":1061},[],[1063],{"type":46,"value":1064},"s shouldContain sub",{"type":46,"value":727},{"type":40,"tag":70,"props":1067,"children":1069},{"className":1068},[],[1070],{"type":46,"value":1071},"Should -Match",{"type":46,"value":727},{"type":40,"tag":70,"props":1074,"children":1076},{"className":1075},[],[1077],{"type":46,"value":1078},"EXPECT_THAT(s, HasSubstr(...))",{"type":40,"tag":138,"props":1080,"children":1081},{},[1082,1090,1095],{"type":40,"tag":165,"props":1083,"children":1084},{},[1085],{"type":40,"tag":62,"props":1086,"children":1087},{},[1088],{"type":46,"value":1089},"Collection",{"type":40,"tag":165,"props":1091,"children":1092},{},[1093],{"type":46,"value":1094},"Collection contents and structure",{"type":40,"tag":165,"props":1096,"children":1097},{},[1098,1104,1105,1111,1112,1118,1119,1125,1126,1132,1133,1139,1140,1146,1147],{"type":40,"tag":70,"props":1099,"children":1101},{"className":1100},[],[1102],{"type":46,"value":1103},"CollectionAssert.Contains",{"type":46,"value":727},{"type":40,"tag":70,"props":1106,"children":1108},{"className":1107},[],[1109],{"type":46,"value":1110},"assert item in collection",{"type":46,"value":727},{"type":40,"tag":70,"props":1113,"children":1115},{"className":1114},[],[1116],{"type":46,"value":1117},"expect(arr).toContain(x)",{"type":46,"value":727},{"type":40,"tag":70,"props":1120,"children":1122},{"className":1121},[],[1123],{"type":46,"value":1124},"assertIterableEquals",{"type":46,"value":727},{"type":40,"tag":70,"props":1127,"children":1129},{"className":1128},[],[1130],{"type":46,"value":1131},"assert.Contains(t, slice, item)",{"type":46,"value":727},{"type":40,"tag":70,"props":1134,"children":1136},{"className":1135},[],[1137],{"type":46,"value":1138},"col shouldContainExactly listOf(...)",{"type":46,"value":727},{"type":40,"tag":70,"props":1141,"children":1143},{"className":1142},[],[1144],{"type":46,"value":1145},"Should -Contain",{"type":46,"value":727},{"type":40,"tag":70,"props":1148,"children":1150},{"className":1149},[],[1151],{"type":46,"value":1152},"EXPECT_THAT(c, ElementsAre(...))",{"type":40,"tag":138,"props":1154,"children":1155},{},[1156,1164,1169],{"type":40,"tag":165,"props":1157,"children":1158},{},[1159],{"type":40,"tag":62,"props":1160,"children":1161},{},[1162],{"type":46,"value":1163},"Comparison",{"type":40,"tag":165,"props":1165,"children":1166},{},[1167],{"type":46,"value":1168},"Ordering and magnitude",{"type":40,"tag":165,"props":1170,"children":1171},{},[1172,1178,1179,1185,1186,1192,1193,1199,1200,1206,1207,1213],{"type":40,"tag":70,"props":1173,"children":1175},{"className":1174},[],[1176],{"type":46,"value":1177},"Assert.IsTrue(x > y)",{"type":46,"value":727},{"type":40,"tag":70,"props":1180,"children":1182},{"className":1181},[],[1183],{"type":46,"value":1184},"Is.GreaterThan",{"type":46,"value":727},{"type":40,"tag":70,"props":1187,"children":1189},{"className":1188},[],[1190],{"type":46,"value":1191},"assert x > y",{"type":46,"value":727},{"type":40,"tag":70,"props":1194,"children":1196},{"className":1195},[],[1197],{"type":46,"value":1198},"expect(x).toBeGreaterThan(y)",{"type":46,"value":727},{"type":40,"tag":70,"props":1201,"children":1203},{"className":1202},[],[1204],{"type":46,"value":1205},"assertTrue(x > y)",{"type":46,"value":727},{"type":40,"tag":70,"props":1208,"children":1210},{"className":1209},[],[1211],{"type":46,"value":1212},"assert.Greater(t, x, y)",{"type":46,"value":1214}," (testify)",{"type":40,"tag":138,"props":1216,"children":1217},{},[1218,1226,1231],{"type":40,"tag":165,"props":1219,"children":1220},{},[1221],{"type":40,"tag":62,"props":1222,"children":1223},{},[1224],{"type":46,"value":1225},"Approximate",{"type":40,"tag":165,"props":1227,"children":1228},{},[1229],{"type":46,"value":1230},"Floating-point or tolerance-based",{"type":40,"tag":165,"props":1232,"children":1233},{},[1234,1240,1241,1247,1248,1254,1255,1261,1262,1268,1269,1275,1276],{"type":40,"tag":70,"props":1235,"children":1237},{"className":1236},[],[1238],{"type":46,"value":1239},"Assert.AreEqual(expected, actual, delta)",{"type":46,"value":727},{"type":40,"tag":70,"props":1242,"children":1244},{"className":1243},[],[1245],{"type":46,"value":1246},"pytest.approx(y)",{"type":46,"value":727},{"type":40,"tag":70,"props":1249,"children":1251},{"className":1250},[],[1252],{"type":46,"value":1253},"expect(x).toBeCloseTo(y)",{"type":46,"value":727},{"type":40,"tag":70,"props":1256,"children":1258},{"className":1257},[],[1259],{"type":46,"value":1260},"assertEquals(x, y, delta)",{"type":46,"value":727},{"type":40,"tag":70,"props":1263,"children":1265},{"className":1264},[],[1266],{"type":46,"value":1267},"assert.InDelta(t, x, y, delta)",{"type":46,"value":727},{"type":40,"tag":70,"props":1270,"children":1272},{"className":1271},[],[1273],{"type":46,"value":1274},"EXPECT_NEAR",{"type":46,"value":727},{"type":40,"tag":70,"props":1277,"children":1279},{"className":1278},[],[1280],{"type":46,"value":1281},"EXPECT_DOUBLE_EQ",{"type":40,"tag":138,"props":1283,"children":1284},{},[1285,1293,1298],{"type":40,"tag":165,"props":1286,"children":1287},{},[1288],{"type":40,"tag":62,"props":1289,"children":1290},{},[1291],{"type":46,"value":1292},"Negative",{"type":40,"tag":165,"props":1294,"children":1295},{},[1296],{"type":46,"value":1297},"What should NOT happen",{"type":40,"tag":165,"props":1299,"children":1300},{},[1301,1307,1308,1314,1315,1321,1322,1328,1329,1335,1336,1342,1344],{"type":40,"tag":70,"props":1302,"children":1304},{"className":1303},[],[1305],{"type":46,"value":1306},"Assert.AreNotEqual",{"type":46,"value":727},{"type":40,"tag":70,"props":1309,"children":1311},{"className":1310},[],[1312],{"type":46,"value":1313},"assert x != y",{"type":46,"value":727},{"type":40,"tag":70,"props":1316,"children":1318},{"className":1317},[],[1319],{"type":46,"value":1320},"expect(x).not.toBe(y)",{"type":46,"value":727},{"type":40,"tag":70,"props":1323,"children":1325},{"className":1324},[],[1326],{"type":46,"value":1327},"assertNotEquals",{"type":46,"value":727},{"type":40,"tag":70,"props":1330,"children":1332},{"className":1331},[],[1333],{"type":46,"value":1334},"assert.NotEqual(t, x, y)",{"type":46,"value":727},{"type":40,"tag":70,"props":1337,"children":1339},{"className":1338},[],[1340],{"type":46,"value":1341},"refute",{"type":46,"value":1343}," (Minitest \u002F Ruby), ",{"type":40,"tag":70,"props":1345,"children":1347},{"className":1346},[],[1348],{"type":46,"value":1349},"Should -Not -Be",{"type":40,"tag":138,"props":1351,"children":1352},{},[1353,1361,1366],{"type":40,"tag":165,"props":1354,"children":1355},{},[1356],{"type":40,"tag":62,"props":1357,"children":1358},{},[1359],{"type":46,"value":1360},"State \u002F Side-effect",{"type":40,"tag":165,"props":1362,"children":1363},{},[1364],{"type":46,"value":1365},"State transitions and side effects",{"type":40,"tag":165,"props":1367,"children":1368},{},[1369,1371,1377,1379,1385,1387,1393,1395,1401,1402,1408,1410,1416,1417,1423],{"type":46,"value":1370},"Assertions on object properties after mutation; mock-call verifications: ",{"type":40,"tag":70,"props":1372,"children":1374},{"className":1373},[],[1375],{"type":46,"value":1376},"mock.Verify(...)",{"type":46,"value":1378}," (Moq), ",{"type":40,"tag":70,"props":1380,"children":1382},{"className":1381},[],[1383],{"type":46,"value":1384},"mock_method.assert_called_with(...)",{"type":46,"value":1386}," (Python ",{"type":40,"tag":70,"props":1388,"children":1390},{"className":1389},[],[1391],{"type":46,"value":1392},"unittest.mock",{"type":46,"value":1394},"), ",{"type":40,"tag":70,"props":1396,"children":1398},{"className":1397},[],[1399],{"type":46,"value":1400},"expect(mock).toHaveBeenCalledWith(...)",{"type":46,"value":653},{"type":40,"tag":70,"props":1403,"children":1405},{"className":1404},[],[1406],{"type":46,"value":1407},"verify(mock).method(...)",{"type":46,"value":1409}," (Mockito), ",{"type":40,"tag":70,"props":1411,"children":1413},{"className":1412},[],[1414],{"type":46,"value":1415},"Should -Invoke",{"type":46,"value":692},{"type":40,"tag":70,"props":1418,"children":1420},{"className":1419},[],[1421],{"type":46,"value":1422},"expect { code }.to change(obj, :attr)",{"type":46,"value":1424}," (RSpec)",{"type":40,"tag":138,"props":1426,"children":1427},{},[1428,1436,1441],{"type":40,"tag":165,"props":1429,"children":1430},{},[1431],{"type":40,"tag":62,"props":1432,"children":1433},{},[1434],{"type":46,"value":1435},"Structural \u002F Deep",{"type":40,"tag":165,"props":1437,"children":1438},{},[1439],{"type":46,"value":1440},"Deep object correctness",{"type":40,"tag":165,"props":1442,"children":1443},{},[1444,1449,1451,1457,1459,1465,1467,1473,1475,1481,1482,1488,1489,1495,1496,1502],{"type":40,"tag":70,"props":1445,"children":1447},{"className":1446},[],[1448],{"type":46,"value":627},{"type":46,"value":1450}," with rich-equality types, ",{"type":40,"tag":70,"props":1452,"children":1454},{"className":1453},[],[1455],{"type":46,"value":1456},"assertThat(obj).usingRecursiveComparison()",{"type":46,"value":1458}," (AssertJ), ",{"type":40,"tag":70,"props":1460,"children":1462},{"className":1461},[],[1463],{"type":46,"value":1464},".toEqual({...})",{"type":46,"value":1466}," (Jest deep equality), ",{"type":40,"tag":70,"props":1468,"children":1470},{"className":1469},[],[1471],{"type":46,"value":1472},"cmp.Diff",{"type":46,"value":1474}," (Go go-cmp), snapshot tests (",{"type":40,"tag":70,"props":1476,"children":1478},{"className":1477},[],[1479],{"type":46,"value":1480},".toMatchSnapshot()",{"type":46,"value":727},{"type":40,"tag":70,"props":1483,"children":1485},{"className":1484},[],[1486],{"type":46,"value":1487},"syrupy",{"type":46,"value":727},{"type":40,"tag":70,"props":1490,"children":1492},{"className":1491},[],[1493],{"type":46,"value":1494},"SnapshotTesting",{"type":46,"value":1394},{"type":40,"tag":70,"props":1497,"children":1499},{"className":1498},[],[1500],{"type":46,"value":1501},"assertThat(col).extracting(...)",{"type":46,"value":1503}," (AssertJ chains)",{"type":40,"tag":49,"props":1505,"children":1506},{},[1507,1509,1514,1516,1521],{"type":46,"value":1508},"A single assertion can belong to multiple categories (e.g., ",{"type":40,"tag":70,"props":1510,"children":1512},{"className":1511},[],[1513],{"type":46,"value":1306},{"type":46,"value":1515}," is both Equality and Negative; ",{"type":40,"tag":70,"props":1517,"children":1519},{"className":1518},[],[1520],{"type":46,"value":1400},{"type":46,"value":1522}," is both State\u002FSide-effect and a specific-call assertion).",{"type":40,"tag":49,"props":1524,"children":1525},{},[1526],{"type":46,"value":1527},"Read the loaded language extension file for the exact framework-specific list of assertion APIs.",{"type":40,"tag":469,"props":1529,"children":1531},{"id":1530},"step-4-compute-metrics",[1532],{"type":46,"value":1533},"Step 4: Compute metrics",{"type":40,"tag":49,"props":1535,"children":1536},{},[1537],{"type":46,"value":1538},"Calculate these metrics for the test suite:",{"type":40,"tag":1540,"props":1541,"children":1543},"h4",{"id":1542},"per-test-metrics",[1544],{"type":46,"value":1545},"Per-test metrics",{"type":40,"tag":298,"props":1547,"children":1548},{},[1549,1559],{"type":40,"tag":302,"props":1550,"children":1551},{},[1552,1557],{"type":40,"tag":62,"props":1553,"children":1554},{},[1555],{"type":46,"value":1556},"Assertion count",{"type":46,"value":1558},": Number of assertions in each test method",{"type":40,"tag":302,"props":1560,"children":1561},{},[1562,1567],{"type":40,"tag":62,"props":1563,"children":1564},{},[1565],{"type":46,"value":1566},"Assertion categories",{"type":46,"value":1568},": Which categories each test uses",{"type":40,"tag":1540,"props":1570,"children":1572},{"id":1571},"suite-wide-metrics",[1573],{"type":46,"value":1574},"Suite-wide metrics",{"type":40,"tag":298,"props":1576,"children":1577},{},[1578,1588,1598,1608,1626,1652,1662,1672,1681,1690],{"type":40,"tag":302,"props":1579,"children":1580},{},[1581,1586],{"type":40,"tag":62,"props":1582,"children":1583},{},[1584],{"type":46,"value":1585},"Average assertions per test",{"type":46,"value":1587},": Total assertions \u002F total test methods",{"type":40,"tag":302,"props":1589,"children":1590},{},[1591,1596],{"type":40,"tag":62,"props":1592,"children":1593},{},[1594],{"type":46,"value":1595},"Assertion type spread",{"type":46,"value":1597},": Number of distinct assertion categories used across the suite (out of 12)",{"type":40,"tag":302,"props":1599,"children":1600},{},[1601,1606],{"type":40,"tag":62,"props":1602,"children":1603},{},[1604],{"type":46,"value":1605},"Tests with zero assertions",{"type":46,"value":1607},": Count and percentage of test methods with no assertions at all",{"type":40,"tag":302,"props":1609,"children":1610},{},[1611,1616,1618,1624],{"type":40,"tag":62,"props":1612,"children":1613},{},[1614],{"type":46,"value":1615},"Tests with only trivial assertions",{"type":46,"value":1617},": Count and percentage of tests where every assertion is only a null check or ",{"type":40,"tag":70,"props":1619,"children":1621},{"className":1620},[],[1622],{"type":46,"value":1623},"Assert.IsTrue(true)",{"type":46,"value":1625}," — trivial means no meaningful value verification",{"type":40,"tag":302,"props":1627,"children":1628},{},[1629,1634,1636,1642,1644,1650],{"type":40,"tag":62,"props":1630,"children":1631},{},[1632],{"type":46,"value":1633},"Tests with self-referential assertions",{"type":46,"value":1635},": Count and percentage of tests whose assertions compare an input to a round-tripped or identity-transformed version of itself (e.g., ",{"type":40,"tag":70,"props":1637,"children":1639},{"className":1638},[],[1640],{"type":46,"value":1641},"Assert.AreEqual(input, Parse(input.ToString()))",{"type":46,"value":1643},") or assert a field against itself (",{"type":40,"tag":70,"props":1645,"children":1647},{"className":1646},[],[1648],{"type":46,"value":1649},"Assert.AreEqual(dto.Name, dto.Name)",{"type":46,"value":1651},"). These are tautological — they verify the plumbing, not the behavior.",{"type":40,"tag":302,"props":1653,"children":1654},{},[1655,1660],{"type":40,"tag":62,"props":1656,"children":1657},{},[1658],{"type":46,"value":1659},"Tests with negative assertions",{"type":46,"value":1661},": Count and percentage (target: at least 10% of tests should verify what should NOT happen)",{"type":40,"tag":302,"props":1663,"children":1664},{},[1665,1670],{"type":40,"tag":62,"props":1666,"children":1667},{},[1668],{"type":46,"value":1669},"Tests with exception assertions",{"type":46,"value":1671},": Count and percentage",{"type":40,"tag":302,"props":1673,"children":1674},{},[1675,1680],{"type":40,"tag":62,"props":1676,"children":1677},{},[1678],{"type":46,"value":1679},"Tests with state\u002Fside-effect assertions",{"type":46,"value":1671},{"type":40,"tag":302,"props":1682,"children":1683},{},[1684,1689],{"type":40,"tag":62,"props":1685,"children":1686},{},[1687],{"type":46,"value":1688},"Tests with structural\u002Fdeep assertions",{"type":46,"value":1671},{"type":40,"tag":302,"props":1691,"children":1692},{},[1693,1698],{"type":40,"tag":62,"props":1694,"children":1695},{},[1696],{"type":46,"value":1697},"Single-category tests",{"type":46,"value":1699},": Count and percentage of tests that use only one assertion category",{"type":40,"tag":469,"props":1701,"children":1703},{"id":1702},"step-5-apply-calibration-rules",[1704],{"type":46,"value":1705},"Step 5: Apply calibration rules",{"type":40,"tag":49,"props":1707,"children":1708},{},[1709],{"type":46,"value":1710},"Before reporting, calibrate findings:",{"type":40,"tag":298,"props":1712,"children":1713},{},[1714,1743,1796,1806,1842,1885,1914,1946,1956,1974],{"type":40,"tag":302,"props":1715,"children":1716},{},[1717,1722,1724,1729,1730,1735,1736,1741],{"type":40,"tag":62,"props":1718,"children":1719},{},[1720],{"type":46,"value":1721},"Trivial means truly trivial.",{"type":46,"value":1723}," A null\u002FNone\u002Fnil check alone is trivial (",{"type":40,"tag":70,"props":1725,"children":1727},{"className":1726},[],[1728],{"type":46,"value":180},{"type":46,"value":727},{"type":40,"tag":70,"props":1731,"children":1733},{"className":1732},[],[1734],{"type":46,"value":188},{"type":46,"value":727},{"type":40,"tag":70,"props":1737,"children":1739},{"className":1738},[],[1740],{"type":46,"value":195},{"type":46,"value":1742},"). But a null check followed by a meaningful value assertion is not trivial — the null check is a guard before the real assertion. Only flag a test as \"trivial\" if it has no meaningful value assertions.",{"type":40,"tag":302,"props":1744,"children":1745},{},[1746,1751,1753,1759,1760,1766,1767,1773,1775,1780,1781,1787,1788,1794],{"type":40,"tag":62,"props":1747,"children":1748},{},[1749],{"type":46,"value":1750},"Boolean assertions checking meaningful conditions are not trivial.",{"type":46,"value":1752}," ",{"type":40,"tag":70,"props":1754,"children":1756},{"className":1755},[],[1757],{"type":46,"value":1758},"Assert.IsTrue(result.IsValid)",{"type":46,"value":182},{"type":40,"tag":70,"props":1761,"children":1763},{"className":1762},[],[1764],{"type":46,"value":1765},"assert result.is_valid",{"type":46,"value":182},{"type":40,"tag":70,"props":1768,"children":1770},{"className":1769},[],[1771],{"type":46,"value":1772},"expect(result.isValid).toBe(true)",{"type":46,"value":1774}," check a specific property — these are Boolean assertions, not trivial ones. Always-true assertions (",{"type":40,"tag":70,"props":1776,"children":1778},{"className":1777},[],[1779],{"type":46,"value":1623},{"type":46,"value":727},{"type":40,"tag":70,"props":1782,"children":1784},{"className":1783},[],[1785],{"type":46,"value":1786},"assert True",{"type":46,"value":727},{"type":40,"tag":70,"props":1789,"children":1791},{"className":1790},[],[1792],{"type":46,"value":1793},"expect(true).toBe(true)",{"type":46,"value":1795},") are trivial.",{"type":40,"tag":302,"props":1797,"children":1798},{},[1799,1804],{"type":40,"tag":62,"props":1800,"children":1801},{},[1802],{"type":46,"value":1803},"Consider the test's intent.",{"type":46,"value":1805}," A test for a void method that verifies state change on a dependency is legitimate even if it only uses one Boolean assertion.",{"type":40,"tag":302,"props":1807,"children":1808},{},[1809,1814,1815,1821,1822,1828,1829,1834,1835,1840],{"type":40,"tag":62,"props":1810,"children":1811},{},[1812],{"type":46,"value":1813},"Exception tests are inherently low-assertion-count.",{"type":46,"value":1752},{"type":40,"tag":70,"props":1816,"children":1818},{"className":1817},[],[1819],{"type":46,"value":1820},"Assert.ThrowsException\u003CT>(() => ...)",{"type":46,"value":182},{"type":40,"tag":70,"props":1823,"children":1825},{"className":1824},[],[1826],{"type":46,"value":1827},"with pytest.raises(E): ...",{"type":46,"value":182},{"type":40,"tag":70,"props":1830,"children":1832},{"className":1831},[],[1833],{"type":46,"value":887},{"type":46,"value":182},{"type":40,"tag":70,"props":1836,"children":1838},{"className":1837},[],[1839],{"type":46,"value":915},{"type":46,"value":1841}," may be the only assertion — that's fine for exception-focused tests. Don't penalize them for low assertion count.",{"type":40,"tag":302,"props":1843,"children":1844},{},[1845,1850,1852,1857,1858,1863,1864,1869,1870,1876,1877,1883],{"type":40,"tag":62,"props":1846,"children":1847},{},[1848],{"type":46,"value":1849},"Mock-call verifications and bare assertion forms count.",{"type":46,"value":1851}," Treat ",{"type":40,"tag":70,"props":1853,"children":1855},{"className":1854},[],[1856],{"type":46,"value":1407},{"type":46,"value":1409},{"type":40,"tag":70,"props":1859,"children":1861},{"className":1860},[],[1862],{"type":46,"value":1400},{"type":46,"value":653},{"type":40,"tag":70,"props":1865,"children":1867},{"className":1866},[],[1868],{"type":46,"value":1415},{"type":46,"value":692},{"type":40,"tag":70,"props":1871,"children":1873},{"className":1872},[],[1874],{"type":46,"value":1875},"bare assert",{"type":46,"value":645},{"type":40,"tag":70,"props":1878,"children":1880},{"className":1879},[],[1881],{"type":46,"value":1882},"if got != want { t.Errorf(...) }",{"type":46,"value":1884}," (Go) all as real assertions of the appropriate category. Do not treat them as missing-framework-API smells.",{"type":40,"tag":302,"props":1886,"children":1887},{},[1888,1893,1895,1900,1901,1906,1907,1912],{"type":40,"tag":62,"props":1889,"children":1890},{},[1891],{"type":46,"value":1892},"Snapshot assertions",{"type":46,"value":1894}," (",{"type":40,"tag":70,"props":1896,"children":1898},{"className":1897},[],[1899],{"type":46,"value":1480},{"type":46,"value":727},{"type":40,"tag":70,"props":1902,"children":1904},{"className":1903},[],[1905],{"type":46,"value":1487},{"type":46,"value":727},{"type":40,"tag":70,"props":1908,"children":1910},{"className":1909},[],[1911],{"type":46,"value":1494},{"type":46,"value":1913},") count as Structural\u002FDeep assertions. Flag stale or never-updated snapshots separately.",{"type":40,"tag":302,"props":1915,"children":1916},{},[1917,1922,1923,1929,1931,1937,1938,1944],{"type":40,"tag":62,"props":1918,"children":1919},{},[1920],{"type":46,"value":1921},"Property-based tests",{"type":46,"value":1894},{"type":40,"tag":70,"props":1924,"children":1926},{"className":1925},[],[1927],{"type":46,"value":1928},"@given",{"type":46,"value":1930}," Hypothesis, ",{"type":40,"tag":70,"props":1932,"children":1934},{"className":1933},[],[1935],{"type":46,"value":1936},"proptest!",{"type":46,"value":727},{"type":40,"tag":70,"props":1939,"children":1941},{"className":1940},[],[1942],{"type":46,"value":1943},"forAll",{"type":46,"value":1945}," Kotest) generate assertions implicitly through generated cases — count the inner assertion logic, not the outer scaffold.",{"type":40,"tag":302,"props":1947,"children":1948},{},[1949,1954],{"type":40,"tag":62,"props":1950,"children":1951},{},[1952],{"type":46,"value":1953},"Don't conflate diversity with volume.",{"type":46,"value":1955}," A test with 20 equality assertions has high volume but low diversity. A test with one equality, one null check, and one exception assertion has low volume but good diversity.",{"type":40,"tag":302,"props":1957,"children":1958},{},[1959,1964,1966,1972],{"type":40,"tag":62,"props":1960,"children":1961},{},[1962],{"type":46,"value":1963},"Self-referential assertions are not meaningful equality checks.",{"type":46,"value":1965}," Asserting that an output equals an input round-trip looks like a real equality assertion but is tautological when the operation under test is expected to be identity. Flag these separately from normal equality assertions. If the test's ",{"type":40,"tag":1967,"props":1968,"children":1969},"em",{},[1970],{"type":46,"value":1971},"purpose",{"type":46,"value":1973}," is to verify a round-trip (serialize\u002Fdeserialize, encode\u002Fdecode), the assertion is valid — but it should be accompanied by assertions on non-trivial inputs that exercise the transformation.",{"type":40,"tag":302,"props":1975,"children":1976},{},[1977,1982],{"type":40,"tag":62,"props":1978,"children":1979},{},[1980],{"type":46,"value":1981},"If assertions are well-diversified, say so.",{"type":46,"value":1983}," A report concluding the suite has good diversity is perfectly valid.",{"type":40,"tag":469,"props":1985,"children":1987},{"id":1986},"step-6-report-findings",[1988],{"type":46,"value":1989},"Step 6: Report findings",{"type":40,"tag":49,"props":1991,"children":1992},{},[1993,1998],{"type":40,"tag":62,"props":1994,"children":1995},{},[1996],{"type":46,"value":1997},"Scale the report depth to the size and complexity of the suite.",{"type":46,"value":1999}," The structure below is the full template for a substantial suite (roughly 15+ tests or a multi-file project). For a small or simple input (a single file with only a handful of tests), do not emit every section — a padded multi-section dashboard on a trivial input reads as noise and buries the answer. Instead, answer the user's question directly and concisely: which tests are assertion-free or trivial-only, the overall assertion-quality verdict, and concrete recommendations (still distinguishing intentional smoke tests from tests masquerading as real verification). Use only the sections that carry real signal for the input at hand; a short metric summary plus the assertion-free list and recommendations is often enough. Never omit the rubric-relevant substance (assertion-free\u002Ftrivial identification, the quality verdict, and concrete recommendations) — only trim structural overhead that adds no information.",{"type":40,"tag":49,"props":2001,"children":2002},{},[2003],{"type":46,"value":2004},"Present the analysis in this structure:",{"type":40,"tag":2006,"props":2007,"children":2008},"ol",{},[2009,2031,2059,2092,2120],{"type":40,"tag":302,"props":2010,"children":2011},{},[2012,2017,2019],{"type":40,"tag":62,"props":2013,"children":2014},{},[2015],{"type":46,"value":2016},"Summary Dashboard",{"type":46,"value":2018}," — A quick-reference table of key metrics:",{"type":40,"tag":2020,"props":2021,"children":2025},"pre",{"className":2022,"code":2024,"language":46},[2023],"language-text","| Metric                        | Value  | Assessment |\n|-------------------------------|--------|------------|\n| Total tests                   | 25     | —          |\n| Average assertions per test   | 2.4    | Moderate   |\n| Assertion type spread         | 5\u002F12   | Low        |\n| Tests with zero assertions    | 3 (12%)| Concerning |\n| Tests with only trivial asserts | 4 (16%)| Acceptable |\n| Tests with negative assertions | 2 (8%) | Below target |\n| Single-category tests         | 15 (60%)| High       |\n",[2026],{"type":40,"tag":70,"props":2027,"children":2029},{"__ignoreMap":2028},"",[2030],{"type":46,"value":2024},{"type":40,"tag":302,"props":2032,"children":2033},{},[2034,2039,2041],{"type":40,"tag":62,"props":2035,"children":2036},{},[2037],{"type":46,"value":2038},"Category Breakdown",{"type":46,"value":2040}," — For each assertion category, show:",{"type":40,"tag":298,"props":2042,"children":2043},{},[2044,2049,2054],{"type":40,"tag":302,"props":2045,"children":2046},{},[2047],{"type":46,"value":2048},"How many tests use it",{"type":40,"tag":302,"props":2050,"children":2051},{},[2052],{"type":46,"value":2053},"Representative examples from the code",{"type":40,"tag":302,"props":2055,"children":2056},{},[2057],{"type":46,"value":2058},"Whether it's overused or underused relative to the code under test",{"type":40,"tag":302,"props":2060,"children":2061},{},[2062,2067,2069],{"type":40,"tag":62,"props":2063,"children":2064},{},[2065],{"type":46,"value":2066},"Gap Analysis",{"type":46,"value":2068}," — Based on the production code (if available), identify:",{"type":40,"tag":298,"props":2070,"children":2071},{},[2072,2077,2082,2087],{"type":40,"tag":302,"props":2073,"children":2074},{},[2075],{"type":46,"value":2076},"Behaviors that are tested but only with equality checks",{"type":40,"tag":302,"props":2078,"children":2079},{},[2080],{"type":46,"value":2081},"Error paths with no exception assertions",{"type":40,"tag":302,"props":2083,"children":2084},{},[2085],{"type":46,"value":2086},"State-changing methods with no state verification",{"type":40,"tag":302,"props":2088,"children":2089},{},[2090],{"type":46,"value":2091},"Collections returned but never checked for contents",{"type":40,"tag":302,"props":2093,"children":2094},{},[2095,2100,2102],{"type":40,"tag":62,"props":2096,"children":2097},{},[2098],{"type":46,"value":2099},"Recommendations",{"type":46,"value":2101}," — Prioritized list of improvements:",{"type":40,"tag":298,"props":2103,"children":2104},{},[2105,2110,2115],{"type":40,"tag":302,"props":2106,"children":2107},{},[2108],{"type":46,"value":2109},"Which tests would benefit most from additional assertion types",{"type":40,"tag":302,"props":2111,"children":2112},{},[2113],{"type":46,"value":2114},"Which assertion categories are missing and why they matter",{"type":40,"tag":302,"props":2116,"children":2117},{},[2118],{"type":46,"value":2119},"Concrete examples of assertions that could be added",{"type":40,"tag":302,"props":2121,"children":2122},{},[2123,2127],{"type":40,"tag":62,"props":2124,"children":2125},{},[2126],{"type":46,"value":280},{"type":46,"value":2128}," — If any exist, list each one with its method name and what it appears to be testing, so the user can decide whether to add assertions or mark them as intentional smoke tests.",{"type":40,"tag":118,"props":2130,"children":2132},{"id":2131},"validation",[2133],{"type":46,"value":2134},"Validation",{"type":40,"tag":298,"props":2136,"children":2139},{"className":2137},[2138],"contains-task-list",[2140,2153,2162,2171,2180,2189,2198],{"type":40,"tag":302,"props":2141,"children":2144},{"className":2142},[2143],"task-list-item",[2145,2151],{"type":40,"tag":2146,"props":2147,"children":2150},"input",{"disabled":2148,"type":2149},true,"checkbox",[],{"type":46,"value":2152}," Every assertion in the test suite was classified into at least one category",{"type":40,"tag":302,"props":2154,"children":2156},{"className":2155},[2143],[2157,2160],{"type":40,"tag":2146,"props":2158,"children":2159},{"disabled":2148,"type":2149},[],{"type":46,"value":2161}," Metrics are computed correctly (counts add up)",{"type":40,"tag":302,"props":2163,"children":2165},{"className":2164},[2143],[2166,2169],{"type":40,"tag":2146,"props":2167,"children":2168},{"disabled":2148,"type":2149},[],{"type":46,"value":2170}," Trivial-assertion tests are correctly identified (not over-flagged)",{"type":40,"tag":302,"props":2172,"children":2174},{"className":2173},[2143],[2175,2178],{"type":40,"tag":2146,"props":2176,"children":2177},{"disabled":2148,"type":2149},[],{"type":46,"value":2179}," Exception tests are not penalized for low assertion count",{"type":40,"tag":302,"props":2181,"children":2183},{"className":2182},[2143],[2184,2187],{"type":40,"tag":2146,"props":2185,"children":2186},{"disabled":2148,"type":2149},[],{"type":46,"value":2188}," Boolean assertions on meaningful properties are not classified as trivial",{"type":40,"tag":302,"props":2190,"children":2192},{"className":2191},[2143],[2193,2196],{"type":40,"tag":2146,"props":2194,"children":2195},{"disabled":2148,"type":2149},[],{"type":46,"value":2197}," Recommendations are concrete (name specific test methods and suggest specific assertion types)",{"type":40,"tag":302,"props":2199,"children":2201},{"className":2200},[2143],[2202,2205],{"type":40,"tag":2146,"props":2203,"children":2204},{"disabled":2148,"type":2149},[],{"type":46,"value":2206}," If the suite has good diversity, the report acknowledges this",{"type":40,"tag":118,"props":2208,"children":2210},{"id":2209},"common-pitfalls",[2211],{"type":46,"value":2212},"Common Pitfalls",{"type":40,"tag":130,"props":2214,"children":2215},{},[2216,2232],{"type":40,"tag":134,"props":2217,"children":2218},{},[2219],{"type":40,"tag":138,"props":2220,"children":2221},{},[2222,2227],{"type":40,"tag":142,"props":2223,"children":2224},{},[2225],{"type":46,"value":2226},"Pitfall",{"type":40,"tag":142,"props":2228,"children":2229},{},[2230],{"type":46,"value":2231},"Solution",{"type":40,"tag":158,"props":2233,"children":2234},{},[2235,2248,2261,2293,2358,2393,2423,2436,2449],{"type":40,"tag":138,"props":2236,"children":2237},{},[2238,2243],{"type":40,"tag":165,"props":2239,"children":2240},{},[2241],{"type":46,"value":2242},"Penalizing exception tests for low assertion count",{"type":40,"tag":165,"props":2244,"children":2245},{},[2246],{"type":46,"value":2247},"Exception assertions are complete on their own — skip count warnings for these",{"type":40,"tag":138,"props":2249,"children":2250},{},[2251,2256],{"type":40,"tag":165,"props":2252,"children":2253},{},[2254],{"type":46,"value":2255},"Flagging null\u002FNone\u002Fnil checks before value checks as trivial",{"type":40,"tag":165,"props":2257,"children":2258},{},[2259],{"type":46,"value":2260},"Only flag tests where the null\u002FNone\u002Fnil check is the ONLY assertion",{"type":40,"tag":138,"props":2262,"children":2263},{},[2264,2269],{"type":40,"tag":165,"props":2265,"children":2266},{},[2267],{"type":46,"value":2268},"Counting any Boolean assertion as trivial",{"type":40,"tag":165,"props":2270,"children":2271},{},[2272,2274,2279,2280,2285,2286,2291],{"type":46,"value":2273},"Only always-true assertions (",{"type":40,"tag":70,"props":2275,"children":2277},{"className":2276},[],[2278],{"type":46,"value":1623},{"type":46,"value":727},{"type":40,"tag":70,"props":2281,"children":2283},{"className":2282},[],[2284],{"type":46,"value":1786},{"type":46,"value":727},{"type":40,"tag":70,"props":2287,"children":2289},{"className":2288},[],[2290],{"type":46,"value":1793},{"type":46,"value":2292},") are trivial",{"type":40,"tag":138,"props":2294,"children":2295},{},[2296,2301],{"type":40,"tag":165,"props":2297,"children":2298},{},[2299],{"type":46,"value":2300},"Ignoring framework differences",{"type":40,"tag":165,"props":2302,"children":2303},{},[2304,2306,2311,2313,2318,2320,2326,2328,2334,2336,2342,2344,2350,2352,2356],{"type":46,"value":2305},"Each framework has distinct assertion APIs — always read the matching language extension first. MSTest's ",{"type":40,"tag":70,"props":2307,"children":2309},{"className":2308},[],[2310],{"type":46,"value":627},{"type":46,"value":2312},", xUnit's ",{"type":40,"tag":70,"props":2314,"children":2316},{"className":2315},[],[2317],{"type":46,"value":635},{"type":46,"value":2319},", NUnit's ",{"type":40,"tag":70,"props":2321,"children":2323},{"className":2322},[],[2324],{"type":46,"value":2325},"Is.EqualTo",{"type":46,"value":2327},", pytest's bare ",{"type":40,"tag":70,"props":2329,"children":2331},{"className":2330},[],[2332],{"type":46,"value":2333},"assert ==",{"type":46,"value":2335},", Jest's ",{"type":40,"tag":70,"props":2337,"children":2339},{"className":2338},[],[2340],{"type":46,"value":2341},"expect().toBe()",{"type":46,"value":2343},", Go's ",{"type":40,"tag":70,"props":2345,"children":2347},{"className":2346},[],[2348],{"type":46,"value":2349},"if … { t.Error… }",{"type":46,"value":2351}," all map to the ",{"type":40,"tag":62,"props":2353,"children":2354},{},[2355],{"type":46,"value":613},{"type":46,"value":2357}," category",{"type":40,"tag":138,"props":2359,"children":2360},{},[2361,2366],{"type":40,"tag":165,"props":2362,"children":2363},{},[2364],{"type":46,"value":2365},"Treating bare assertion forms as missing-framework",{"type":40,"tag":165,"props":2367,"children":2368},{},[2369,2371,2377,2378,2383,2385,2391],{"type":46,"value":2370},"Bare ",{"type":40,"tag":70,"props":2372,"children":2374},{"className":2373},[],[2375],{"type":46,"value":2376},"assert",{"type":46,"value":645},{"type":40,"tag":70,"props":2379,"children":2381},{"className":2380},[],[2382],{"type":46,"value":667},{"type":46,"value":2384}," (Go), and ",{"type":40,"tag":70,"props":2386,"children":2388},{"className":2387},[],[2389],{"type":46,"value":2390},"assert!()",{"type":46,"value":2392}," (Rust) are canonical — count them in the right category",{"type":40,"tag":138,"props":2394,"children":2395},{},[2396,2401],{"type":40,"tag":165,"props":2397,"children":2398},{},[2399],{"type":46,"value":2400},"Treating mock-call verifications as assertion-free",{"type":40,"tag":165,"props":2402,"children":2403},{},[2404,2409,2410,2415,2416,2421],{"type":40,"tag":70,"props":2405,"children":2407},{"className":2406},[],[2408],{"type":46,"value":1407},{"type":46,"value":727},{"type":40,"tag":70,"props":2411,"children":2413},{"className":2412},[],[2414],{"type":46,"value":1400},{"type":46,"value":727},{"type":40,"tag":70,"props":2417,"children":2419},{"className":2418},[],[2420],{"type":46,"value":1415},{"type":46,"value":2422}," are State\u002FSide-effect assertions",{"type":40,"tag":138,"props":2424,"children":2425},{},[2426,2431],{"type":40,"tag":165,"props":2427,"children":2428},{},[2429],{"type":46,"value":2430},"Recommending diversity for diversity's sake",{"type":40,"tag":165,"props":2432,"children":2433},{},[2434],{"type":46,"value":2435},"Only suggest adding assertion types that would catch real bugs in the code under test",{"type":40,"tag":138,"props":2437,"children":2438},{},[2439,2444],{"type":40,"tag":165,"props":2440,"children":2441},{},[2442],{"type":46,"value":2443},"Missing implicit assertions",{"type":40,"tag":165,"props":2445,"children":2446},{},[2447],{"type":46,"value":2448},"Exception assertions are both Exception and Negative; snapshot\u002Fproperty-based tests are real assertions with implicit structure",{"type":40,"tag":138,"props":2450,"children":2451},{},[2452,2457],{"type":40,"tag":165,"props":2453,"children":2454},{},[2455],{"type":46,"value":2456},"Async tests with unawaited assertions",{"type":40,"tag":165,"props":2458,"children":2459},{},[2460,2462,2468,2470,2476,2478,2484],{"type":46,"value":2461},"TUnit, Jest with ",{"type":40,"tag":70,"props":2463,"children":2465},{"className":2464},[],[2466],{"type":46,"value":2467},".resolves",{"type":46,"value":2469},"\u002F",{"type":40,"tag":70,"props":2471,"children":2473},{"className":2472},[],[2474],{"type":46,"value":2475},".rejects",{"type":46,"value":2477},", pytest-asyncio, Swift Testing, and Kotest all silently pass tests where assertions are not ",{"type":40,"tag":70,"props":2479,"children":2481},{"className":2480},[],[2482],{"type":46,"value":2483},"await",{"type":46,"value":2485},"ed — treat as assertion-free even when assertion calls are present",{"items":2487,"total":2588},[2488,2505,2520,2538,2544,2564,2574],{"slug":2489,"name":2489,"fn":2490,"description":2491,"org":2492,"tags":2493,"stars":22,"repoUrl":23,"updatedAt":2504},"analyzing-dotnet-performance","analyze .NET code for performance anti-patterns","Scans .NET code for ~50 performance anti-patterns across async, memory, strings, collections, LINQ, regex, serialization, and I\u002FO with tiered severity classification. Use when analyzing .NET code for optimization opportunities, reviewing hot paths, or auditing allocation-heavy patterns.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2494,2497,2498,2501],{"name":2495,"slug":2496,"type":15},".NET","net",{"name":17,"slug":18,"type":15},{"name":2499,"slug":2500,"type":15},"Debugging","debugging",{"name":2502,"slug":2503,"type":15},"Performance","performance","2026-07-12T08:23:25.400375",{"slug":2506,"name":2506,"fn":2507,"description":2508,"org":2509,"tags":2510,"stars":22,"repoUrl":23,"updatedAt":2519},"android-tombstone-symbolication","symbolicate .NET runtime frames in Android tombstones","Symbolicate the .NET runtime frames in an Android tombstone file. Extracts BuildIds and PC offsets from the native backtrace, downloads debug symbols from the Microsoft symbol server, and runs llvm-symbolizer to produce function names with source file and line numbers. USE FOR triaging a .NET MAUI or Mono Android app crash from a tombstone, resolving native backtrace frames in libmonosgen-2.0.so or libcoreclr.so to .NET runtime source code, or investigating SIGABRT, SIGSEGV, or other native signals originating from the .NET runtime on Android. DO NOT USE FOR pure Java\u002FKotlin crashes, managed .NET exceptions that are already captured in logcat, or iOS crash logs. INVOKES Symbolicate-Tombstone.ps1 script, llvm-symbolizer, Microsoft symbol server.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2511,2512,2515,2516],{"name":2495,"slug":2496,"type":15},{"name":2513,"slug":2514,"type":15},"Android","android",{"name":2499,"slug":2500,"type":15},{"name":2517,"slug":2518,"type":15},"Microsoft","microsoft","2026-07-12T08:23:21.595572",{"slug":2521,"name":2521,"fn":2522,"description":2523,"org":2524,"tags":2525,"stars":22,"repoUrl":23,"updatedAt":2537},"apple-crash-symbolication","symbolicate .NET runtime frames in crash logs","Symbolicate .NET runtime frames in Apple platform .ips crash logs (iOS, tvOS, Mac Catalyst, macOS). Extracts UUIDs and addresses from the native backtrace, locates dSYM debug symbols, and runs atos to produce function names with source file and line numbers. Automatically downloads .dwarf symbols from the Microsoft symbol server using Mach-O UUIDs. USE FOR triaging a .NET MAUI or Mono app crash from an .ips file on any Apple platform, resolving native backtrace frames in libcoreclr or libmonosgen-2.0 to .NET runtime source code, retrieving .ips crash logs from a connected iOS device or iPhone, or investigating EXC_CRASH, EXC_BAD_ACCESS, SIGABRT, or SIGSEGV originating from the .NET runtime. DO NOT USE FOR pure Swift\u002FObjective-C crashes with no .NET components, or Android tombstone files. INVOKES Symbolicate-Crash.ps1 script, atos, dwarfdump, idevicecrashreport.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2526,2527,2528,2531,2534],{"name":2495,"slug":2496,"type":15},{"name":2499,"slug":2500,"type":15},{"name":2529,"slug":2530,"type":15},"iOS","ios",{"name":2532,"slug":2533,"type":15},"macOS","macos",{"name":2535,"slug":2536,"type":15},"Observability","observability","2026-07-12T08:23:20.369986",{"slug":4,"name":4,"fn":5,"description":6,"org":2539,"tags":2540,"stars":22,"repoUrl":23,"updatedAt":24},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2541,2542,2543],{"name":17,"slug":18,"type":15},{"name":13,"slug":14,"type":15},{"name":20,"slug":21,"type":15},{"slug":2545,"name":2545,"fn":2546,"description":2547,"org":2548,"tags":2549,"stars":22,"repoUrl":23,"updatedAt":2563},"author-component","create and review Blazor components","Create or review Blazor components (.razor files) with correct architecture. USE FOR: writing new Blazor components that do NOT involve JavaScript interop, implementing parameters and EventCallback, RenderFragment slots, component lifecycle (OnInitializedAsync, OnParametersSet), async patterns, IAsyncDisposable, CancellationToken, CSS isolation, code-behind. DO NOT USE FOR: creating new projects (use create-blazor-project), JavaScript interop or calling browser APIs from Blazor (use use-js-interop), forms and validation (use collect-user-input), prerendering issues (use support-prerendering), HTTP data fetching patterns (use fetch-and-send-data), coordinating state between unrelated components (use coordinate-components).\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2550,2551,2554,2557,2560],{"name":2495,"slug":2496,"type":15},{"name":2552,"slug":2553,"type":15},"Blazor","blazor",{"name":2555,"slug":2556,"type":15},"C#","csharp",{"name":2558,"slug":2559,"type":15},"UI Components","ui-components",{"name":2561,"slug":2562,"type":15},"Web Development","web-development","2026-07-15T06:03:29.216359",{"slug":2565,"name":2565,"fn":2566,"description":2567,"org":2568,"tags":2569,"stars":22,"repoUrl":23,"updatedAt":2573},"binlog-failure-analysis","analyze MSBuild binary logs","Analyze MSBuild binary logs to diagnose build failures. USE FOR: build errors that are unclear from console output, diagnosing cascading failures across multi-project builds, tracing MSBuild target execution order, and generally any MSBuild build issues. Requires an existing .binlog file. DO NOT USE FOR: generating binlogs (use binlog-generation), non-MSBuild build systems.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2570,2571,2572],{"name":17,"slug":18,"type":15},{"name":2499,"slug":2500,"type":15},{"name":2517,"slug":2518,"type":15},"2026-07-12T08:21:34.637923",{"slug":2575,"name":2575,"fn":2576,"description":2577,"org":2578,"tags":2579,"stars":22,"repoUrl":23,"updatedAt":2587},"binlog-generation","generate MSBuild binary logs for diagnostics","Generate MSBuild binary logs (binlogs) for build diagnostics and analysis. USE FOR: adding \u002Fbl:{} to any dotnet build, test, pack, publish, or restore command to capture a full build execution trace, prerequisite for binlog-failure-analysis and build-perf-diagnostics skills, enabling post-build investigation of errors or performance. Requires MSBuild 17.8+ \u002F .NET 8 SDK+ for {} placeholder; PowerShell needs -bl:{{}}. DO NOT USE FOR: non-MSBuild build systems (npm, Maven, CMake), analyzing an existing binlog (use binlog-failure-analysis instead).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2580,2583,2584],{"name":2581,"slug":2582,"type":15},"Build","build",{"name":2499,"slug":2500,"type":15},{"name":2585,"slug":2586,"type":15},"Engineering","engineering","2026-07-19T05:38:19.340791",96,{"items":2590,"total":2695},[2591,2603,2610,2617,2625,2631,2639,2645,2651,2661,2674,2685],{"slug":2592,"name":2592,"fn":2593,"description":2594,"org":2595,"tags":2596,"stars":2600,"repoUrl":2601,"updatedAt":2602},"multithreaded-task-migration","migrate MSBuild tasks to multithreaded mode","Guide for migrating MSBuild tasks to multithreaded mode support, including compatibility red-team review. Use this when converting tasks to thread-safe versions, implementing IMultiThreadableTask, adding TaskEnvironment support, or auditing migrations for behavioral compatibility.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2597,2598,2599],{"name":2495,"slug":2496,"type":15},{"name":2585,"slug":2586,"type":15},{"name":2502,"slug":2503,"type":15},5535,"https:\u002F\u002Fgithub.com\u002Fdotnet\u002Fmsbuild","2026-07-22T05:37:33.965588",{"slug":2489,"name":2489,"fn":2490,"description":2491,"org":2604,"tags":2605,"stars":22,"repoUrl":23,"updatedAt":2504},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2606,2607,2608,2609],{"name":2495,"slug":2496,"type":15},{"name":17,"slug":18,"type":15},{"name":2499,"slug":2500,"type":15},{"name":2502,"slug":2503,"type":15},{"slug":2506,"name":2506,"fn":2507,"description":2508,"org":2611,"tags":2612,"stars":22,"repoUrl":23,"updatedAt":2519},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2613,2614,2615,2616],{"name":2495,"slug":2496,"type":15},{"name":2513,"slug":2514,"type":15},{"name":2499,"slug":2500,"type":15},{"name":2517,"slug":2518,"type":15},{"slug":2521,"name":2521,"fn":2522,"description":2523,"org":2618,"tags":2619,"stars":22,"repoUrl":23,"updatedAt":2537},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2620,2621,2622,2623,2624],{"name":2495,"slug":2496,"type":15},{"name":2499,"slug":2500,"type":15},{"name":2529,"slug":2530,"type":15},{"name":2532,"slug":2533,"type":15},{"name":2535,"slug":2536,"type":15},{"slug":4,"name":4,"fn":5,"description":6,"org":2626,"tags":2627,"stars":22,"repoUrl":23,"updatedAt":24},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2628,2629,2630],{"name":17,"slug":18,"type":15},{"name":13,"slug":14,"type":15},{"name":20,"slug":21,"type":15},{"slug":2545,"name":2545,"fn":2546,"description":2547,"org":2632,"tags":2633,"stars":22,"repoUrl":23,"updatedAt":2563},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2634,2635,2636,2637,2638],{"name":2495,"slug":2496,"type":15},{"name":2552,"slug":2553,"type":15},{"name":2555,"slug":2556,"type":15},{"name":2558,"slug":2559,"type":15},{"name":2561,"slug":2562,"type":15},{"slug":2565,"name":2565,"fn":2566,"description":2567,"org":2640,"tags":2641,"stars":22,"repoUrl":23,"updatedAt":2573},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2642,2643,2644],{"name":17,"slug":18,"type":15},{"name":2499,"slug":2500,"type":15},{"name":2517,"slug":2518,"type":15},{"slug":2575,"name":2575,"fn":2576,"description":2577,"org":2646,"tags":2647,"stars":22,"repoUrl":23,"updatedAt":2587},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2648,2649,2650],{"name":2581,"slug":2582,"type":15},{"name":2499,"slug":2500,"type":15},{"name":2585,"slug":2586,"type":15},{"slug":2652,"name":2652,"fn":2653,"description":2654,"org":2655,"tags":2656,"stars":22,"repoUrl":23,"updatedAt":2660},"build-parallelism","optimize MSBuild build parallelism","Diagnose and fix under-parallelized MSBuild builds. USE WHEN a multi-project solution build is slower than expected, doesn't speed up when you add cores, pegs a single core while others idle, or you want to know why `-m` isn't helping. Note: `\u002Fmaxcpucount` default is 1 (sequential) — always pass `-m` for parallel builds. Covers finding the critical path (longest serial ProjectReference chain), graph build (`\u002Fgraph`), BuildInParallel, and solution filters (`.slnf`). DO NOT USE FOR: single-project builds, incremental issues (use incremental-build), compilation slowness inside one project (use build-perf-diagnostics), non-MSBuild build systems.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2657,2658,2659],{"name":2495,"slug":2496,"type":15},{"name":2585,"slug":2586,"type":15},{"name":2502,"slug":2503,"type":15},"2026-07-19T05:38:18.364937",{"slug":2662,"name":2662,"fn":2663,"description":2664,"org":2665,"tags":2666,"stars":22,"repoUrl":23,"updatedAt":2673},"build-perf-baseline","establish and optimize build performance baselines","Establish build performance baselines and apply systematic optimization techniques. USE FOR: diagnosing slow builds, establishing before\u002Fafter measurements (cold, warm, no-op scenarios), applying optimization strategies like MSBuild Server, static graph builds, artifacts output, and dependency graph trimming. Start here before diving into build-perf-diagnostics, incremental-build, or build-parallelism. DO NOT USE FOR: non-MSBuild build systems, detailed bottleneck analysis (use build-perf-diagnostics after baselining).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2667,2668,2671,2672],{"name":2585,"slug":2586,"type":15},{"name":2669,"slug":2670,"type":15},"Monitoring","monitoring",{"name":2502,"slug":2503,"type":15},{"name":20,"slug":21,"type":15},"2026-07-12T08:21:35.865649",{"slug":2675,"name":2675,"fn":2676,"description":2677,"org":2678,"tags":2679,"stars":22,"repoUrl":23,"updatedAt":2684},"build-perf-diagnostics","diagnose MSBuild build performance bottlenecks","Diagnose MSBuild build performance bottlenecks using binary log analysis. USE FOR: identifying why builds are slow by analyzing binlog performance summaries, detecting ResolveAssemblyReference (RAR) taking >5s, Roslyn analyzers consuming >30% of Csc time, single targets dominating >50% of build time, node utilization below 80%, excessive Copy tasks, NuGet restore running every build. Covers timeline analysis, Target\u002FTask Performance Summary interpretation, and 7 common bottleneck categories. Use after build-perf-baseline has established measurements. DO NOT USE FOR: establishing initial baselines (use build-perf-baseline first), fixing incremental build issues (use incremental-build), parallelism tuning (use build-parallelism), non-MSBuild build systems.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2680,2681,2682,2683],{"name":2495,"slug":2496,"type":15},{"name":2499,"slug":2500,"type":15},{"name":2585,"slug":2586,"type":15},{"name":2502,"slug":2503,"type":15},"2026-07-12T08:21:40.961722",{"slug":2686,"name":2686,"fn":2687,"description":2688,"org":2689,"tags":2690,"stars":22,"repoUrl":23,"updatedAt":2694},"check-bin-obj-clash","detect MSBuild output path conflicts","Detects MSBuild projects with conflicting OutputPath or IntermediateOutputPath. USE FOR: builds failing with 'Cannot create a file when that file already exists', 'The process cannot access the file because it is being used by another process', intermittent build failures that succeed on retry, or missing\u002Foverwritten outputs in multi-project or multi-targeting builds where bin\u002Fobj (or project.assets.json) collide. Common causes: shared OutputPath, missing AppendTargetFrameworkToOutputPath, extra global properties (e.g. PublishReadyToRun), or SetTargetFramework on a ProjectReference to a single-targeting project. DO NOT USE FOR: file access errors unrelated to MSBuild (OS-level locking), single-project single-TFM builds, non-MSBuild build systems.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2691,2692,2693],{"name":2499,"slug":2500,"type":15},{"name":2585,"slug":2586,"type":15},{"name":13,"slug":14,"type":15},"2026-07-19T05:38:14.336279",144]