agentleFS
mazreanmazrean/agent-skills/skills/creating-test-cases/SKILL.md

creating-test-cases

Skill2 starsChanged 8 months agoMITView on GitHub

Designs comprehensive test cases using systematic techniques (boundary value analysis, equivalence partitioning, mutation testing, property-based testing). Use when writing tests, improving test coverage, finding edge cases, or when user mentions test cases, testing, or test design.

The file

We split this skill into the rules it gives an agent

4 rules. About 0 are common, 4 are distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Follow this systematic process:

    line 57
  2. Distinctive:

    Test at partition boundaries where bugs cluster:

    line 104
  3. Distinctive:

    Verify tests can detect code changes:

    line 199
  4. Distinctive:

    Test invariants across many random inputs:

    line 213

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Creating Test Cases

Design comprehensive test cases that systematically find bugs using proven QA techniques.

Use this skill when writing new tests, improving test coverage, finding edge cases, designing test strategies, or reviewing test quality.

Supporting files: TECHNIQUES.md for detailed techniques, BUG-PATTERNS.md for common bug types, GO-TESTING.md for Go-specific patterns, HEURISTICS.md for testing mnemonics.

Quick Start

Apply systematic techniques to find bugs others miss:

func TestCalculateDiscount(t *testing.T) {
    tests := map[string]struct {
        price    float64
        quantity int
        want     float64
        wantErr  bool
    }{
        // Equivalence Partitions
        "valid small order":  {100, 5, 500, false},
        "valid bulk order":   {100, 100, 9000, false}, // 10% bulk discount

        // Boundary Values
        "quantity zero":      {100, 0, 0, false},
        "quantity one":       {100, 1, 100, false},
        "bulk threshold-1":   {100, 49, 4900, false},
        "bulk threshold":     {100, 50, 4500, false}, // discount kicks in
        "bulk threshold+1":   {100, 51, 4590, false},

        // Error Cases
        "negative quantity":  {100, -1, 0, true},
        "negative price":     {-100, 5, 0, true},
        "zero price":         {0, 5, 0, false},

        // Edge Cases (Error Guessing)
        "max int quantity":   {1, math.MaxInt32, 0, true},
        "float precision":    {0.1, 3, 0.3, false},
    }

    for name, tc := range tests {
        t.Run(name, func(t *testing.T) {
            // test implementation
        })
    }
}

Test Design Workflow

Follow this systematic process:

Test Design Checklist:
- [ ] Step 1: Analyze requirements and identify test conditions
- [ ] Step 2: Apply specification-based techniques (EP, BVA, DT)
- [ ] Step 3: Apply structure-based techniques (coverage analysis)
- [ ] Step 4: Apply experience-based techniques (error guessing)
- [ ] Step 5: Prioritize using RCRCRC heuristic
- [ ] Step 6: Validate test quality (mutation testing)

Step 1: Analyze Requirements

Identify inputs, outputs, preconditions, and invariants:

AspectQuestions to Answer
InputsWhat are valid/invalid ranges? What types?
OutputsWhat should success look like? What errors?
PreconditionsWhat state must exist before the operation?
InvariantsWhat must remain true throughout?
Side EffectsWhat state changes occur?

Step 2: Specification-Based Techniques

Equivalence Partitioning (EP)

Divide input domain into classes where behavior is equivalent:

Input: age (integer)
Partitions:
- Invalid: age < 0
- Minor: 0 <= age < 18
- Adult: 18 <= age < 65
- Senior: age >= 65

Test one value from each partition:
- age = -5 (invalid)
- age = 10 (minor)
- age = 30 (adult)
- age = 70 (senior)

Boundary Value Analysis (BVA)

Test at partition boundaries where bugs cluster:

For partition boundaries at 0, 18, 65:
Test: -1, 0, 1, 17, 18, 19, 64, 65, 66

Decision Table Testing

For complex business logic with multiple conditions:

ConditionsR1R2R3R4
Premium memberYYNN
Order > $100YNYN
Actions
Apply 20% offX
Apply 10% offXX
No discountX

State Transition Testing

For stateful systems:

States: [Idle] -> [Processing] -> [Complete/Failed]

Test transitions:
1. Idle -> Processing (valid: submit order)
2. Processing -> Complete (valid: payment success)
3. Processing -> Failed (valid: payment declined)
4. Idle -> Complete (invalid: should fail)

Step 3: Structure-Based Techniques

Target coverage metrics:

LevelCoverage TargetWhen to Use
Statement80%+Minimum for production code
Branch80%+Conditional logic
MC/DC100%Safety-critical systems

Branch coverage example:

func process(a, b bool) string {
    if a && b {      // Branch 1: both true
        return "both"
    } else if a {    // Branch 2: only a
        return "a"
    } else {         // Branch 3: neither/only b
        return "other"
    }
}

// Tests for 100% branch coverage:
// {true, true} -> "both"   (Branch 1)
// {true, false} -> "a"     (Branch 2)
// {false, true} -> "other" (Branch 3)
// {false, false} -> "other" (Branch 3, redundant)

Step 4: Experience-Based Techniques

Error Guessing

Target common bug patterns:

CategoryExamples to Test
Off-by-oneLoop bounds, array indices, fencepost
Null/Emptynil, "", [], {}
Numeric0, -1, MAX_INT, MIN_INT, NaN, Inf
StringsUnicode, very long, special chars
ConcurrencyRace conditions, deadlocks
ResourcesLeaks, exhaustion, timeouts

RCRCRC Prioritization

Prioritize test areas:

LetterFocusWhat to Test
RecentNew/changed codeFeatures added in current sprint
CoreCritical functionalityMain business flows, payment
RiskHigh-risk areasComplex algorithms, security
ConfigurationEnvironment-dependentDB connections, API keys
RepairedRecently fixed bugsRegression tests for fixes
ChronicFrequently failingAreas with bug history

Step 5: Validate Test Quality

Mutation Testing

Verify tests can detect code changes:

# Go mutation testing
go-mutesting ./...

# Interpret results:
# - Killed mutants: Tests detected the change (good)
# - Survived mutants: Tests missed the change (add tests)
# - Mutation score: killed / total (aim for >80%)

Property-Based Testing

Test invariants across many random inputs:

func TestReverse_Involution(t *testing.T) {
    // Property: reverse(reverse(s)) == s
    rapid.Check(t, func(t *rapid.T) {
        s := rapid.String().Draw(t, "s")
        if reverse(reverse(s)) != s {
            t.Fatalf("involution violated for %q", s)
        }
    })
}

Common Test Structures

Table-Driven Tests (Go)

tests := map[string]struct {
    input    InputType
    want     OutputType
    wantErr  bool
}{
    "descriptive name": {input: x, want: y},
}

for name, tc := range tests {
    t.Run(name, func(t *testing.T) {
        got, err := Function(tc.input)
        if (err != nil) != tc.wantErr {
            t.Errorf("error = %v, wantErr %v", err, tc.wantErr)
            return
        }
        if got != tc.want {
            t.Errorf("got %v, want %v", got, tc.want)
        }
    })
}

Parallel Tests

for name, tc := range tests {
    tc := tc // capture for parallel
    t.Run(name, func(t *testing.T) {
        t.Parallel()
        // test body
    })
}

Quality Checklist

Before finalizing tests:

Test Quality Check:
- [ ] Each test has a clear, descriptive name
- [ ] Tests are independent (no shared mutable state)
- [ ] Error cases are covered
- [ ] Boundary values are tested
- [ ] Tests run quickly (<100ms each)
- [ ] No test smells (duplicate setup, magic numbers)
- [ ] Mutation score >80% for critical code

Detailed Guides

Complete technique reference: See TECHNIQUES.md Common bug patterns: See BUG-PATTERNS.md Go-specific testing: See GO-TESTING.md Testing heuristics: See HEURISTICS.md

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.