Test-driven development methodology with four test types - unit, integration, property, and e2e. Use when writing tests, planning test strategy, implementing features test-first, or verifying test coverage. Triggers when tests are mentioned, test files are being created, or test-first approach is needed.
From disciplined-processnpx claudepluginhub rand/disciplined-process-plugin --plugin disciplined-processThis skill uses the workspace's default tool permissions.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Tests verify specifications are met. Write tests BEFORE implementation. Tests reference spec paragraph IDs for traceability.
┌──────────────────┐
│ 1. RED │ Write a failing test for spec requirement
├──────────────────┤
│ 2. GREEN │ Write minimal code to pass
├──────────────────┤
│ 3. REFACTOR │ Improve code, keep tests green
└──────────────────┘
Purpose: Test individual functions/methods in isolation
Location: tests/unit/
Characteristics:
Pattern:
test_<function>_<scenario>_<expected>
Example (Rust):
#[test]
// @trace SPEC-03.07
fn test_validate_length_exceeds_max_returns_error() {
let input = "x".repeat(1025);
assert!(validate_length(&input).is_err());
}
Example (TypeScript):
describe('validateLength', () => {
// @trace SPEC-03.07
it('returns error when input exceeds max length', () => {
const input = 'x'.repeat(1025);
expect(() => validateLength(input)).toThrow();
});
});
Example (Python):
def test_validate_length_exceeds_max_returns_error():
"""@trace SPEC-03.07"""
input_str = 'x' * 1025
with pytest.raises(ValidationError):
validate_length(input_str)
Purpose: Test component interactions, real dependencies
Location: tests/integration/
Characteristics:
Pattern:
test_<component>_<integration>_<scenario>
Example (Rust):
#[tokio::test]
// @trace SPEC-05.12
async fn test_auth_service_validates_against_database() {
let db = TestDb::new().await;
let auth = AuthService::new(db.pool());
let result = auth.authenticate(valid_credentials()).await;
assert!(result.is_ok());
}
Purpose: Test invariants hold across generated inputs
Location: tests/property/
Characteristics:
Properties to test:
decode(encode(x)) == xf(f(x)) == f(x)len(result) <= MAX_SIZEf(a, b) == f(b, a)Example (Rust with proptest):
proptest! {
#[test]
// @trace SPEC-02.01 - Encoding roundtrip
fn test_encode_decode_roundtrip(input: String) {
let encoded = encode(&input);
let decoded = decode(&encoded)?;
prop_assert_eq!(decoded, input);
}
}
Example (Python with Hypothesis):
from hypothesis import given, strategies as st
@given(st.text())
def test_encode_decode_roundtrip(input_str):
"""@trace SPEC-02.01"""
encoded = encode(input_str)
decoded = decode(encoded)
assert decoded == input_str
Example (TypeScript with fast-check):
import fc from 'fast-check';
// @trace SPEC-02.01
test('encode/decode roundtrip', () => {
fc.assert(fc.property(fc.string(), (input) => {
const encoded = encode(input);
const decoded = decode(encoded);
return decoded === input;
}));
});
Purpose: Test complete user workflows
Location: tests/e2e/
Characteristics:
Pattern:
test_<user_journey>_<expected_outcome>
Example:
// @trace SPEC-01.01 - Complete user registration flow
test('user can register and receive confirmation email', async () => {
await page.goto('/register');
await page.fill('#email', 'test@example.com');
await page.fill('#password', 'SecurePass123!');
await page.click('button[type="submit"]');
await expect(page).toHaveURL('/welcome');
await expect(emailServer).toHaveReceivedEmail({
to: 'test@example.com',
subject: /Welcome/
});
});
╱╲
╱ ╲ E2E (few)
╱────╲ Critical user journeys
╱ ╲
╱────────╲ Property (some)
╱ ╲ Invariants, edge cases
╱────────────╲ Integration (more)
╱ ╲ Component boundaries
╱────────────────╲ Unit (many)
Individual functions
tests/
├── unit/
│ ├── test_<module>.{ext}
│ └── ...
├── integration/
│ ├── test_<component>_<integration>.{ext}
│ └── ...
├── property/
│ ├── test_<invariant>.{ext}
│ └── ...
├── e2e/
│ ├── test_<journey>.{ext}
│ └── ...
├── fixtures/ # Shared test data
│ ├── valid_inputs.json
│ └── ...
└── conftest.{ext} # Shared setup (pytest) or similar
| Language | Unit | Property | Integration | E2E |
|---|---|---|---|---|
| Rust | #[test], cargo test | proptest, quickcheck | tokio::test | - |
| TypeScript | Jest, Vitest | fast-check | Supertest | Playwright |
| Python | pytest | Hypothesis | pytest + fixtures | Playwright |
| Go | testing | gopter | testcontainers | - |
| Zig | std.testing | - | - | - |
| Level | Minimum Coverage | Measured By |
|---|---|---|
| Spec | 100% normative paragraphs | Trace marker presence |
| Unit | 80% line coverage | Coverage tools |
| Integration | Critical paths | Manual review |
| E2E | Happy paths | Journey checklist |
@trace SPEC-XX.YYtest_<what>_<scenario>_<expected>