test-driven-development Skill
Wende Prinzipien der testgetriebenen Entwicklung an, um Software durch vertragsbasierte Tests und das Management von Architektur-Grenzen zu entwerfen.
- GitHub Stars
- 9
- Dateien
- 1
- Letzter Commit
- 13. Okt. 2026
- Lizenz
- EPL-2.0
- Erlaubte Tools
- —
Was macht der test-driven-development Skill?
test-driven-development ist ein Agent Skill. Wende Prinzipien der testgetriebenen Entwicklung an, um Software durch vertragsbasierte Tests und das Management von Architektur-Grenzen zu entwerfen.
Zusammenfassung erzeugt aus der SKILL.md des Skills.
Über den test-driven-development skill
Dieses Skill ermöglicht es Entwicklern und KI-Agenten, Prinzipien der testgetriebenen Entwicklung auf das Software-Design anzuwenden. Dabei werden Tests als formale Verträge behandelt, die geschäftliche Anforderungen und das erwartete Verhalten definieren, anstatt sie nur als nachträglichen Gedanken zu betrachten. Wenn ein Agent dieses Skill lädt, erhält er Anleitung dazu, zuerst fehlschlagende Tests zu schreiben, Architektur-Grenzen zu verwalten und die richtigen Test-Doubles wie Stubs, Mocks, Fakes oder Spies zu verwenden.
Nutzer können sich auf dieses Skill verlassen, um eine hohe Code-Qualität aufrechtzuerhalten, indem sie sich auf Korrekturen der Implementierung konzentrieren, anstatt Tests anzupassen, damit sie zu fehlerhaftem Code passen. Es hilft dabei, Design-Smells zu identifizieren – wie etwa den Drang, interne private Methoden zu mocken – und schlägt stattdessen ein Refactoring vor. Das Skill deckt ein breites Spektrum an Architektur-Grenzen ab, einschließlich Layer-, Modul-, Prozess- und externen Systemgrenzen. Es ist besonders nützlich bei der Arbeit mit spezifischen Frameworks wie JUnit, pytest oder clojure.test, um sicherzustellen, dass Unit-Tests die Komponentenlogik verifizieren, während Integrationstests das tatsächliche Systemverhalten über die Grenzen hinweg prüfen.
Was ein agent damit machen kann
- 1Fehlschlagende Tests debuggenNutze Testfehler als Signal, um die Implementierung zu debuggen, anstatt die Test-Assertions zu modifizieren.
Geschrieben basierend auf dem SKILL.md des skills. Jeder use case wurde gegen ein zitat daraus geprüft.
So installierst du den test-driven-development Skill
Jeder Befehl kopiert den Skill-Ordner in das Skills-Verzeichnis des Clients. Starte den Client neu oder beginne eine neue Session, um ihn zu laden.Den test-driven-development Skill in Plugin installieren
/plugin marketplace add Pyroxin/opinionated-claude-skills /plugin install opinionated-software-engineering@opinionated-claude-skills
Den test-driven-development Skill in Claude Code installieren
~/.claude/skills/test-driven-development/SKILL.md
$ npx degit Pyroxin/opinionated-claude-skills/opinionated-software-engineering/skills/test-driven-development ~/.claude/skills/test-driven-developmentDen test-driven-development Skill in Claude Code (project) installieren
.claude/skills/test-driven-development/SKILL.md
$ npx degit Pyroxin/opinionated-claude-skills/opinionated-software-engineering/skills/test-driven-development .claude/skills/test-driven-developmentDen test-driven-development Skill in Codex installieren
~/.agents/skills/test-driven-development/SKILL.md
$ npx degit Pyroxin/opinionated-claude-skills/opinionated-software-engineering/skills/test-driven-development ~/.agents/skills/test-driven-developmentDen test-driven-development Skill in Gemini CLI installieren
~/.gemini/skills/test-driven-development/SKILL.md
$ npx degit Pyroxin/opinionated-claude-skills/opinionated-software-engineering/skills/test-driven-development ~/.gemini/skills/test-driven-developmentDen test-driven-development Skill in Claude.ai installieren
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
Auf GitHub ansehenTest-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> ↩
Dateien in diesem Skill
1test-driven-development Skill-Fragen
Wie installiere ich den test-driven-development Skill in Claude Code?
Führe npx degit Pyroxin/opinionated-claude-skills/opinionated-software-engineering/skills/test-driven-development ~/.claude/skills/test-driven-development aus. Claude Code lädt Skills aus ~/.claude/skills (alle Projekte) oder .claude/skills (ein Projekt) und nutzt einen Skill, wenn seine Beschreibung zur Aufgabe passt.
Welche Clients können den test-driven-development Skill nutzen?
Jeder Client, der das Agent Skills-Format liest: Claude Code, Codex, Gemini CLI und claude.ai (als ZIP hochladen). Skripte im Skill laufen nur dort, wo der Client Codeausführung erlaubt.
Was soll ich tun, wenn ein Test fehlschlägt?
Du solltest den Test lesen, um das erwartete Verhalten zu verstehen, die Implementierung debuggen, um den Grund für das Scheitern zu finden, und dann die Implementierung korrigieren. Ändere nicht den Test, nur damit er besteht.
Wie soll ich reagieren, wenn eine Einheit schwer zu testen ist?
Schwierigkeiten beim Testen sind ein Zeichen für ein schlechtes Design; anstatt zu versuchen, Mocks zu erzwingen, solltest du den Code refactoren.