moai-ref-testing-pyramid
The moai-ref-testing-pyramid skill provides a standardized testing pyramid framework defining optimal ratios and patterns for unit, integration, and end-to-end tests. Use this reference when designing test strategies, establishing coverage targets by code context, implementing test patterns like AAA or table-driven approaches, and balancing test speed against reliability during development cycles.
git clone --depth 1 https://github.com/modu-ai/moai-adk /tmp/moai-ref-testing-pyramid && cp -r /tmp/moai-ref-testing-pyramid/.claude/skills/moai-ref-testing-pyramid ~/.claude/skills/moai-ref-testing-pyramidskill.md
# Testing Pyramid Reference
## Target Agents
- `manager-develop` - Primary: applies patterns during test creation and coverage analysis
- `manager-develop` - Secondary: applies during RED-GREEN-REFACTOR cycles
## Test Pyramid Ratios
```
/ E2E \ 10% — Critical user journeys only
/----------\
/ Integration \ 20% — API endpoints, DB queries, service boundaries
/----------------\
/ Unit Tests \ 70% — Functions, hooks, utilities, pure logic
/--------------------\
```
| Level | Speed | Reliability | Maintenance | Coverage Target |
|-------|-------|-------------|-------------|-----------------|
| Unit | Fast (<100ms) | High | Low | 70% of tests |
| Integration | Medium (1-5s) | Medium | Medium | 20% of tests |
| E2E | Slow (10-60s) | Lower | High | 10% of tests |
## Coverage Targets by Context
| Context | Target | Rationale |
|---------|--------|-----------|
| Critical business logic | 95%+ | Revenue/security impact |
| API endpoints | 90%+ | Contract compliance |
| Utility functions | 85%+ | Reuse reliability |
| UI components | 80%+ | Rendering correctness |
| Configuration/glue code | 60%+ | Low complexity |
| Generated code | 0% | Don't test generated code |
## Test Pattern: AAA (Arrange-Act-Assert)
```
// Arrange: Set up test data and preconditions
input := CreateTestUser("test@example.com")
// Act: Execute the function under test
result, err := service.CreateUser(ctx, input)
// Assert: Verify the outcome
assert.NoError(t, err)
assert.Equal(t, "test@example.com", result.Email)
```
## Unit Test Patterns
| Pattern | When | Example |
|---------|------|---------|
| Table-Driven | Multiple input/output combinations | Go: `tests := []struct{...}` |
| Mock/Stub | External dependencies (DB, API) | Interface injection, mock frameworks |
| Snapshot | Complex output comparison | Jest snapshots, golden files |
| Property-Based | Mathematical properties | quickcheck, hypothesis |
| Boundary Value | Edge cases | 0, -1, MAX_INT, empty string, nil |
## Integration Test Patterns
| Pattern | When | Example |
|---------|------|---------|
| Testcontainers | Real DB needed | Docker-based PostgreSQL for tests |
| HTTP Test Server | API endpoint testing | httptest.NewServer (Go), supertest (Node) |
| In-Memory DB | Fast DB tests | SQLite for development |
| Fixture Loading | Consistent test data | Factory functions, seed files |
## What to Test vs What NOT to Test
### ALWAYS Test
- Business logic and calculations
- Input validation and error handling
- Authentication and authorization flows
- Data transformations and mappings
- Edge cases and boundary conditions
- Race conditions (with -race flag in Go)
### NEVER Test
- Framework internals (React rendering, Express routing)
- Third-party library behavior
- Simple getters/setters with no logic
- Private methods directly (test via public API)
- Generated code (protobuf, swagger)
- CSS styling and layout (use visual regression tools instead)
## Test Quality Metrics
| Metric | Target | Tool |
|--------|--------|------|
| Line Coverage | 85%+ | go test -cover, istanbul, coverage.py |
| Branch Coverage | 75%+ | go test -covermode=count |
| Mutation Score | 70%+ | go-mutesting, Stryker |
| Test Execution Time | <2 min (unit), <10 min (all) | CI timer |
| Flaky Test Rate | <1% | CI history analysis |
## Test File Conventions
| Language | Test File | Location |
|----------|-----------|----------|
| Go | `*_test.go` | Same package |
| TypeScript | `*.test.ts` / `*.spec.ts` | `__tests__/` or co-located |
| Python | `test_*.py` | `tests/` directory |
| Java | `*Test.java` | `src/test/` mirror |
| Rust | `#[cfg(test)] mod tests` | Same file or `tests/` |
## TDD RED-GREEN-REFACTOR Quick Reference
```
RED: Write a failing test that defines expected behavior
GREEN: Write minimal code to make the test pass
REFACTOR: Clean up while keeping tests green
```
Rules:
- Never write production code without a failing test
- Write the smallest test that fails
- Write the simplest code that passes
- Refactor only when all tests are green
- One assertion per test (when practical)
<!-- moai:evolvable-start id="rationalizations" -->
## Common Rationalizations
| Rationalization | Reality |
|---|---|
| "E2E tests cover everything, unit tests are redundant" | E2E tests are slow and flaky. Unit tests provide fast, precise feedback. The pyramid exists because each level serves a different purpose. |
| "Integration tests are more realistic than unit tests" | Realism comes at the cost of speed and isolation. A balanced pyramid gives both fast feedback and realistic validation. |
| "100% code coverage means the code is well tested" | Coverage measures execution, not correctness. A test that executes code without meaningful assertions provides zero value. |
| "Mocking is bad, I prefer real dependencies" | Real dependencies make tests slow and non-deterministic. Mock at boundaries, test business logic in isolation. |
| "This test is flaky, but it catches real bugs sometimes" | Flaky tests erode trust in the entire suite. Fix the flakiness or quarantine the test with a tracking issue. |
**DAMP over DRY**: Test code should be descriptive and self-contained. A reader should understand the test without reading shared fixtures or helper methods.
<!-- moai:evolvable-end -->
<!-- moai:evolvable-start id="red-flags" -->
## Red Flags
- Test pyramid inverted: more E2E tests than unit tests
- Unit tests depend on external services (databases, APIs, file systems)
- Test assertions check implementation details instead of behavior
- No integration tests between unit and E2E layers
- Flaky test present without a quarantine label or tracking issue
<!-- moai:evolvable-end -->
<!-- moai:evolvable-start id="verification" -->
## Verification
- [ ] Test distribution follows the pyramid: unit > integration > E2E (show test counts per category)
- [ ] Unit tests run in under 30 seconds total
- [ ] Integration tests mock external dependencieClaude Code upstream change tracker -> moai-adk update plan + docs sync workflow (dev-only). Tracks new CC release notes, classifies changes by impact tier, cross-references official docs, generates update plan at .moai/research/ or .moai/specs/, and synchronizes docs-site 4-locale + README. NOT distributed to user projects.
GitHub Workflow - Manage issues and review PRs with Agent Teams (dev-only). NOT distributed to user projects.
MoAI-ADK production release via Enhanced GitHub Flow (CLAUDE.local.md §18). Creates release/vX.Y.Z branch, version bump, CHANGELOG (bilingual), PR to main, merge commit (NOT squash), then scripts/release.sh for tag + GoReleaser. Hotfix support via --hotfix flag. All git operations delegated to manager-git. Quality failures escalate to expert-debug. NOT distributed to user projects (dev-only).
Run the 7-phase /moai brain ideation workflow to convert ideas into validated proposals
Identify and safely remove dead code with test verification
Scan codebase and generate architecture documentation in codemaps/
Analyze test coverage, identify gaps, and generate missing tests
Hybrid design workflow — Claude Design import (path A) or code-based brand design (path B)