Skill test-driven-development
Aplica principios de desarrollo guiado por pruebas para diseñar software mediante pruebas basadas en contratos y la gestión de límites arquitectónicos.
- Estrellas en GitHub
- 9
- Archivos
- 1
- Último commit
- 13 oct 2026
- Licencia
- EPL-2.0
- Herramientas permitidas
- —
¿Qué hace la skill test-driven-development?
test-driven-development es una agent skill. Aplica principios de desarrollo guiado por pruebas para diseñar software mediante pruebas basadas en contratos y la gestión de límites arquitectónicos.
Resumen generado a partir del SKILL.md de la skill.
Sobre la skill test-driven-development
Esta SKILL permite a desarrolladores y agentes de IA aplicar principios de desarrollo guiado por pruebas (TDD) al diseño de software. Trata las pruebas como contratos formales que definen los requisitos de negocio y el comportamiento esperado, en lugar de verlas como un simple pensamiento secundario. Cuando un agente carga esta SKILL, proporciona orientación sobre cómo escribir primero pruebas que fallen, gestionar los límites arquitectónicos y utilizar los test doubles correctos, como stubs, mocks, fakes o spies.
Los usuarios pueden confiar en esta SKILL para mantener una alta calidad de código al centrarse en corregir la implementación en lugar de modificar las pruebas para que coincidan con un código defectuoso. Ayuda a identificar problemas de diseño, como el impulso de hacer mock de métodos privados internos, sugiriendo una refactorización en su lugar. La SKILL cubre una amplia gama de límites arquitectónicos, incluyendo capas, módulos, procesos y límites de sistemas externos. Es particularmente útil al trabajar con frameworks específicos como JUnit, pytest o clojure.test para asegurar que las pruebas unitarias verifiquen la lógica de los componentes, mientras que las pruebas de integración verifiquen el comportamiento real del sistema a través de sus límites.
Lo que un agente puede hacer con ella
- 1Depurar pruebas fallidasUtiliza los fallos en las pruebas como una señal para depurar la implementación en lugar de modificar las aserciones de la prueba.
Escrito a partir del SKILL.md de la skill. Cada caso de uso se verifica con una cita del mismo.
Cómo instalar la skill test-driven-development
Cada comando copia la carpeta de la skill al directorio de skills del cliente. Reinicia el cliente o inicia una nueva sesión para cargarla.Instalar la skill test-driven-development en Plugin
/plugin marketplace add Pyroxin/opinionated-claude-skills /plugin install opinionated-software-engineering@opinionated-claude-skills
Instalar la skill test-driven-development en Claude Code
~/.claude/skills/test-driven-development/SKILL.md
$ npx degit Pyroxin/opinionated-claude-skills/opinionated-software-engineering/skills/test-driven-development ~/.claude/skills/test-driven-developmentInstalar la skill test-driven-development en Claude Code (project)
.claude/skills/test-driven-development/SKILL.md
$ npx degit Pyroxin/opinionated-claude-skills/opinionated-software-engineering/skills/test-driven-development .claude/skills/test-driven-developmentInstalar la skill test-driven-development en Codex
~/.agents/skills/test-driven-development/SKILL.md
$ npx degit Pyroxin/opinionated-claude-skills/opinionated-software-engineering/skills/test-driven-development ~/.agents/skills/test-driven-developmentInstalar la skill test-driven-development en Gemini CLI
~/.gemini/skills/test-driven-development/SKILL.md
$ npx degit Pyroxin/opinionated-claude-skills/opinionated-software-engineering/skills/test-driven-development ~/.gemini/skills/test-driven-developmentInstalar la skill test-driven-development en Claude.ai
npx degit Pyroxin/opinionated-claude-skills/opinionated-software-engineering/skills/test-driven-development test-driven-development && zip -r test-driven-development.zip test-driven-development # claude.ai → Customize → Skills → + → Create skill → Upload a skill → test-driven-development.zip
SKILL.md
Ver en GitHubTest-Driven Development
For system-level design principles and architectural boundaries, see the software-engineer skill.
Core Philosophy
<core_philosophy>
Foundation: TDD is an application of contract-based design. Tests define the contract an implementation must fulfill—they are specifications, not afterthoughts. This connects directly to the abstraction principles in the software-engineer skill.
Tests = Contracts: Tests represent business requirements and expected behavior. They are contracts the implementation must fulfill. Never compromise test integrity to achieve green tests.
Tests are source of truth: When tests fail, fix the implementation. Only change tests when requirements change or test has a verified bug. </core_philosophy>
Testing Approach
Architectural Boundaries and Mocking Strategy
<architectural_boundaries> Identify architectural boundaries in your system:
- Layer boundaries (e.g., data layer, service layer, presentation layer)
- Module boundaries (e.g., namespaces, packages, crates)
- Process boundaries (e.g., Erlang processes, Elixir GenServers)
- External system boundaries (e.g., APIs, databases, third-party services) </architectural_boundaries>
<unit_definition> What constitutes a "unit":
A "unit" is a cohesive component at an architectural boundary:
- Classes (e.g., Java, Python, Swift)
- Namespaces with related functions (e.g., Clojure, Haskell)
- Modules with related predicates (e.g., Prolog)
- Processes/GenServers (e.g., Erlang, Elixir)
- Modules with traits/protocols (e.g., Rust, Swift) </unit_definition>
<mocking_rules> When to mock:
- Mock dependencies across architectural boundaries
- External dependencies injected/passed into system under test get mocked
When NOT to mock:
- Don't mock the system under test itself
- Don't mock within a cohesive unit (e.g., private methods, internal helpers)
- If tempted to mock internals, that's a design smell — refactor instead </mocking_rules>
<test_balance> Balance unit and integration tests:
- Unit tests: Test each component in isolation with mocked dependencies across boundaries
- Integration tests: Test behavior across boundaries with real implementations
- Both are necessary — unit tests verify component logic, integration tests verify system behavior
- Over-mocked tests validate mocks, not real behavior </test_balance>
┌───────────────────────────────────────────────────────┐
│ Application Core │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Domain │ │ Service │ │ Use Case │ │
│ │ Models │ │ Layer │ │ Layer │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
├───────────────────────BOUNDARY────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Database │ │ External │ │ HTTP │ │
│ │ Adapter │ │ API │ │ Client │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└───────────────────────────────────────────────────────┘
- Unit tests: Test domain models and service layer with mocked adapters
- Integration tests: Test adapters with real external systems (DB, APIs)
- Contract tests: Verify adapters fulfill the port interface
- External database gets mocked at adapter boundary, not inside services
Test Doubles Taxonomy
<test_doubles> Understanding test double types aids in communicating test intent. This taxonomy was formalized by Gerard Meszaros in xUnit Test Patterns (2007):1
| Type | Purpose | When to Use |
|---|---|---|
| Stub | Returns predetermined values | When behavior doesn't affect test outcome |
| Mock | Verifies interactions occurred | When the interaction IS the behavior being tested |
| Fake | Working implementation (simplified) | When real implementation too slow/complex |
| Spy | Records calls for later verification | When need to verify after execution |
Key insight: Overuse of mocks often indicates testing implementation rather than behavior. Prefer stubs when possible; use mocks when interactions are the contract.
Test Design Process
<design_steps> When designing tests:
- Identify architectural boundaries in the system
- Determine what constitutes a "unit" (component, layer, module)
- Plan unit tests for each unit with dependencies mocked at boundaries
- Plan integration tests crossing boundaries with real implementations
- Ensure tests verify usage/requirements, not implementation details </design_steps>
<failure_response> When test fails:
- Read test to understand expected behavior
- Debug implementation to find why it doesn't meet expectations
- Fix implementation, never "fix" test to pass </failure_response>
<quality_criteria> Test quality requirements:
- Descriptive names explaining the requirement being checked
- Readable as documentation of system behavior
- Plan test cases based on usage, not implementation details
- Include comprehensive documentation (e.g., Javadoc for JUnit, Sphinx for Python) explaining what test ensures and special considerations
- Tests can have bugs or enforce wrong behaviors—always assess correctness </quality_criteria>
Test-Driven Development Workflow
<tdd_cycle>
- Write failing tests FIRST based on requirements (including desired usage patterns)
- Thoroughly document planned tests to guide implementation
- Stub planned tests with exceptions:
throw new IllegalStateException("Not implemented yet!")
- Implementation makes existing tests pass without test modification
- Tests are source of truth — never change tests to match broken code
- When debugging:
- Understand why test is failing
- Fix implementation to match test expectations
- Only modify tests if requirements changed or test has VERIFIED bug
- Treat test failures as implementation bugs, not test bugs
- Test bugs exist, but assume only after verifying implementation is correct </tdd_cycle>
<debugging_tip> Debug and trace logging: Effective way to probe program function during test execution. </debugging_tip>
Critical Anti-Patterns
<anti_patterns> Never:
- Mock the system under test itself (the component being tested)
- Mock within a cohesive unit (e.g., private methods, internal helpers of the unit under test)
- Change test assertions to match current behavior
- Write tests that mirror implementation rather than requirements
- Over-mock to the point tests don't validate real behavior
- Write tests that don't exercise code in module being tested (e.g., calculating result in test instead of using module-under-test)
- Mock to make tests pass — fix implementation instead </anti_patterns>
<design_smell> If tempted to mock internals of the unit under test: That's a design smell — refactor the code instead. </design_smell>
Framework-Specific Guidance
See language-specific skills for testing framework details:
- java-programmer: JUnit, Mockito, assertion patterns
- python-programmer: pytest, unittest, mocking strategies
- clojure-programmer: clojure.test, test.check
- racket-programmer: RackUnit, testing patterns
General principles across frameworks:
- Use framework's assertion methods instead of custom comparison logic
- Include descriptive assertion messages explaining business/technical reasons
- Organize tests into logical categories/suites
- Maintain consistent assertion styles within codebase
Planning and Scaffolding
<scaffolding_steps> Before implementing:
- Create interfaces, type signatures, abstract classes, and other definitional structures
- Create empty functions with step-by-step comments: "1. Setup data.", "2. Process data.", etc.
- Write tests after defining but NOT implementing code structures to create example API uses
- Examine example code for potential usage problems requiring scaffold refactoring </scaffolding_steps>
<maintainability_principles> Maintainability:
- Assume code maintained by junior engineers and other LLMs
- Prefer strongly defined structures based on idiomatic patterns for the language
- If uncertain, ask — user is senior engineer with answers or resources </maintainability_principles>
Common Mistakes
<common_mistakes>
Mechanical Mistakes
- Planning tests based on implementation instead of usage/requirements
- Creating tests that over-fit to specific implementation
- Removing existing documentation or comments (rephrase for consistency instead)
- Not documenting tests (every test needs comprehensive documentation)
- Using inconsistent assertion/verification styles across tests
- Not explaining business/technical reasons in assertion messages
Judgment Mistakes (Staff-Level Insights)
- Confusing "tests first" with "tests drive design": TDD is about using tests to discover design, not just writing tests before code
- Treating coverage metrics as quality proxies: 100% coverage with bad tests is worse than 70% coverage with good tests
- Not recognizing test difficulty as design feedback: If a unit is hard to test, the design is likely wrong—don't fight to mock, refactor instead
- Writing tests that specify implementation sequence: Tests should specify WHAT behavior occurs, not HOW or in what order
- Testing internal state rather than observable behavior: Tests should verify outputs and side effects, not implementation details
- Over-mocking to achieve isolation: If everything is mocked, the test validates mocks, not system behavior </common_mistakes>
Resources
Key Principles:
- Test Pyramid concept (Mike Cohn, 2009): more unit tests, fewer integration tests, even fewer E2E
- Arrange-Act-Assert pattern (Bill Wake, 2001) for test structure
- Given-When-Then (Dan North and Chris Matts, ~2006) for behavior specification
See also: Language-specific skills for framework-specific testing patterns (JUnit, pytest, clojure.test, RackUnit, PlUnit).
Footnotes
-
Gerard Meszaros. 2007. xUnit Test Patterns: Refactoring Test Code. Addison-Wesley. </test_doubles> ↩
Archivos de esta skill
1Preguntas sobre la skill test-driven-development
¿Cómo instalo la skill test-driven-development en Claude Code?
Ejecuta npx degit Pyroxin/opinionated-claude-skills/opinionated-software-engineering/skills/test-driven-development ~/.claude/skills/test-driven-development. Claude Code carga las skills desde ~/.claude/skills (todos los proyectos) o .claude/skills (un proyecto) y usa una skill cuando su descripción coincide con la tarea.
¿Qué clientes pueden usar la skill test-driven-development?
Cualquier cliente que lea el formato Agent Skills: Claude Code, Codex, Gemini CLI y claude.ai (subir como ZIP). Los scripts de la skill se ejecutan solo donde el cliente permite la ejecución de código.
¿Qué debo hacer cuando una prueba falla?
Debes leer la prueba para entender el comportamiento esperado, depurar la implementación para encontrar por qué falla y corregir la implementación. No cambies la prueba para que pase.
¿Cómo debo responder si una unidad es difícil de probar?
La dificultad para realizar pruebas es una señal de un mal diseño; en lugar de intentar forzar el uso de mocks, deberías refactorizar el código.