writing-tests
$
npx mdskill add rileyhilliard/claude-essentials/writing-testsGenerate behavior-focused tests using real dependencies.
- Creates integration tests that survive code refactoring.
- Prioritizes integration over unit or end-to-end tests.
- Avoids mocking internal modules and business logic.
- Outputs test code ready for immediate execution.
SKILL.md
.github/skills/writing-testsView on GitHub ↗
--- name: writing-tests description: Writes behavior-focused tests using Testing Trophy model with real dependencies. Use when writing tests, choosing test types, or avoiding anti-patterns like testing mocks. --- # Writing Tests **Core principle:** Test user-observable behavior with real dependencies. Tests should survive refactoring. > "The more your tests resemble the way your software is used, the more confidence they can give you." — Kent C. Dodds **Why this matters:** Tests exist to give you confidence. The Testing Trophy prioritizes integration tests because they test real behavior across real modules — giving maximum confidence per test written. Unit tests in isolation often just test mocks, not your actual system. ## Testing Trophy Model | Priority | Type | When | | -------- | ----------- | ----------------------------------------------- | | 1st | Integration | Default - multiple units with real dependencies | | 2nd | E2E | Complete user workflows | | 3rd | Unit | Pure functions only (no dependencies) | ## Mocking Guidelines **Default: Don't mock. Use real dependencies.** **Only mock:** - External HTTP/API calls - Time/randomness - Third-party services (payments, email) **Never mock:** - Internal modules - Database queries (use test DB) - Business logic - Your own code calling your own code **Before mocking, ask:** "What side effects does this have? Does my test need those?" If unsure, run with real implementation first, then add minimal mocking only where needed. ## Test Type Decision ``` Complete user workflow? → E2E test Pure function (no side effects)? → Unit test Everything else → Integration test ``` ## Assertion Strategy | Context | Assert On | Avoid | | ------- | --------------------- | --------------------------- | | UI | Visible text, roles | CSS classes, internal state | | API | Response body, status | Internal DB state | | Library | Return values | Private methods | ## Anti-Patterns | Pattern | Fix | | ------------------------------- | --------------------------- | | Testing mock calls | Test actual outcome | | Test-only methods in production | Move to test utilities | | `sleep(500)` | Use condition-based waiting | | Asserting on internal state | Assert on observable output | | Incomplete mocks | Mirror real API completely | ## Quality Checklist - [ ] Happy path covered - [ ] Error conditions handled - [ ] Real dependencies used (minimal mocking) - [ ] Tests survive refactoring - [ ] Test names describe behavior ## Language-Specific Patterns - **JavaScript/Typescript/React**: See [references/typescript-react.md](references/typescript-react.md) - **Python**: See [references/python.md](references/python.md) - **Go**: See [references/go.md](references/go.md) For flaky tests with timing issues, use `Skill(ce:condition-based-waiting)`. --- **Remember:** Behavior over implementation. Real over mocked. Outputs over internals.
More from rileyhilliard/claude-essentials
- architecting-systemsGuides clean, scalable system architecture during the build phase. Use when designing modules, defining boundaries, structuring projects, managing dependencies, or preventing tight coupling and brittleness as systems grow.
- configuring-claudeBest practices for writing Claude Code skills, rules, and CLAUDE.md instructions. Use when creating SKILL.md files, authoring .claude/rules, writing CLAUDE.md project or user instructions, or configuring Claude behavior for a project or team.
- fixing-flaky-testsDiagnose and fix tests that pass in isolation but fail when run concurrently. Covers shared state isolation and resource conflicts. References condition-based-waiting for timing issues.
- handling-errorsPrevents silent failures and context loss in error handling. Use when writing try-catch blocks, designing error propagation, reviewing catch blocks, or implementing Result patterns.
- managing-databasesGuides database architecture decisions for PostgreSQL, DuckDB, Parquet, PGVector, and Neo4j. Use when designing schemas, choosing storage strategies, optimizing queries, tuning maintenance, configuring vector search, modeling graph data, or diagnosing performance issues across OLTP, OLAP, similarity search, and graph workloads.
- managing-pipelinesGuides CI/CD pipeline architecture, security hardening, and deployment strategies for GitHub Actions. Use when designing workflows, securing supply chains, optimizing build performance, configuring deployments, managing infrastructure as code pipelines, or setting up pipeline observability.
- migrating-codeSafe code migrations with backward compatibility and reversibility. Use when upgrading dependencies, changing database schemas, API versioning, or transitioning between technologies.
- optimizing-performanceMeasure-first performance optimization that balances gains against complexity. Use when addressing slow code, profiling issues, or evaluating optimization trade-offs.
- planning-productsDefines product features from a PM perspective before technical planning begins. Use when scoping new features, writing product specs, defining user problems, choosing what to build, researching existing patterns, or bridging the gap between strategy and implementation. Covers JTBD analysis, competitive research, UX/DX experience definition, and scope negotiation for consumer, B2B, and developer tool products.
- preflight-checksDetect and run project linters, formatters, and type checkers before committing or claiming completion. Auto-detects tools from project config files.