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.
In this repository29 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- building-lit-componentsSkill
- building-static-site-rss-feedsSkill
- building-templ-componentsSkill
- checking-wsh-vrtSkill
- committing-codeSkill
- creating-agent-skillsSkill
- deploying-with-isucon-ansibleSkill
- designing-isucon-architectureSkill
- frontend-designSkill
- operating-isucon-servers-via-sshSkill
- planning-wsh-improvementsSkill
- porting-isucon-rust-to-goSkill
- releasing-zig-with-goreleaserSkill
- running-isucon-as-an-agentSkill
- sharing-sockets-with-so-reuseport-in-zigSkill
- tuning-isucon-linux-and-nginxSkill
- using-go-tool-directiveSkill
- using-grafana-mcpSkill
- using-unocss-with-templSkill
- winning-isuconSkill
- winning-web-speed-hackathonSkill
- writing-feature-specSkill
- writing-implementation-tasksSkill
- writing-isucon-arch-subagent-tasksSkill
- writing-project-constitutionSkill
- writing-technical-designSkill
- writing-zig-cli-toolsSkill
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
- Distinctive: line 57
Follow this systematic process:
- Distinctive: line 104
Test at partition boundaries where bugs cluster:
- Distinctive: line 199
Verify tests can detect code changes:
- Distinctive: line 213
Test invariants across many random inputs:
≈ “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.
Files
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:
| Aspect | Questions to Answer |
| Inputs | What are valid/invalid ranges? What types? |
| Outputs | What should success look like? What errors? |
| Preconditions | What state must exist before the operation? |
| Invariants | What must remain true throughout? |
| Side Effects | What 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, 66Decision Table Testing
For complex business logic with multiple conditions:
| Conditions | R1 | R2 | R3 | R4 |
| Premium member | Y | Y | N | N |
| Order > $100 | Y | N | Y | N |
| Actions | ||||
| Apply 20% off | X | |||
| Apply 10% off | X | X | ||
| No discount | X |
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:
| Level | Coverage Target | When to Use |
| Statement | 80%+ | Minimum for production code |
| Branch | 80%+ | Conditional logic |
| MC/DC | 100% | 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:
| Category | Examples to Test |
| Off-by-one | Loop bounds, array indices, fencepost |
| Null/Empty | nil, "", [], {} |
| Numeric | 0, -1, MAX_INT, MIN_INT, NaN, Inf |
| Strings | Unicode, very long, special chars |
| Concurrency | Race conditions, deadlocks |
| Resources | Leaks, exhaustion, timeouts |
RCRCRC Prioritization
Prioritize test areas:
| Letter | Focus | What to Test |
| Recent | New/changed code | Features added in current sprint |
| Core | Critical functionality | Main business flows, payment |
| Risk | High-risk areas | Complex algorithms, security |
| Configuration | Environment-dependent | DB connections, API keys |
| Repaired | Recently fixed bugs | Regression tests for fixes |
| Chronic | Frequently failing | Areas 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 codeDetailed 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
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
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.

