{"id":"eb996877-eb5e-4816-896e-4d8f8e458fa9","shortId":"7a6GSa","kind":"skill","title":"tdd","tagline":"Test-driven development with the red-green-refactor loop. Vertical-slice tracer bullets,\nnot horizontal slicing. Tests verify behavior through public interfaces, not implementation\ndetails, so they survive refactors. Sub-docs cover deep modules, interface design,\nmocking, refacto","description":"## Preamble\n\n```bash\neval \"$(~/.vibestack/bin/vibe-slug 2>/dev/null)\" 2>/dev/null || SLUG=\"unknown\"\n_LEARN_FILE=\"${VIBESTACK_HOME:-$HOME/.vibestack}/projects/${SLUG:-unknown}/learnings.jsonl\"\nif [ -f \"$_LEARN_FILE\" ]; then\n  _LEARN_COUNT=$(wc -l < \"$_LEARN_FILE\" 2>/dev/null | tr -d ' ')\n  echo \"LEARNINGS: $_LEARN_COUNT entries loaded\"\n  if [ \"$_LEARN_COUNT\" -gt 5 ] 2>/dev/null; then\n    ~/.vibestack/bin/vibe-learnings-search --limit 5 2>/dev/null || true\n  fi\nelse\n  echo \"LEARNINGS: none yet\"\nfi\n```\n\n# Test-Driven Development\n\n## Philosophy\n\n**Core principle**: Tests should verify behavior through public interfaces, not implementation details. Code can change entirely; tests shouldn't.\n\n**Good tests** are integration-style: they exercise real code paths through public APIs. They describe _what_ the system does, not _how_ it does it. A good test reads like a specification - \"user can checkout with valid cart\" tells you exactly what capability exists. These tests survive refactors because they don't care about internal structure.\n\n**Bad tests** are coupled to implementation. They mock internal collaborators, test private methods, or verify through external means (like querying a database directly instead of using the interface). The warning sign: your test breaks when you refactor, but behavior hasn't changed. If you rename an internal function and tests fail, those tests were testing implementation, not behavior.\n\nSee [tests.md](tests.md) for examples and [mocking.md](mocking.md) for mocking guidelines.\n\n## Anti-Pattern: Horizontal Slices\n\n**DO NOT write all tests first, then all implementation.** This is \"horizontal slicing\" - treating RED as \"write all tests\" and GREEN as \"write all code.\"\n\nThis produces **crap tests**:\n\n- Tests written in bulk test _imagined_ behavior, not _actual_ behavior\n- You end up testing the _shape_ of things (data structures, function signatures) rather than user-facing behavior\n- Tests become insensitive to real changes - they pass when behavior breaks, fail when behavior is fine\n- You outrun your headlights, committing to test structure before understanding the implementation\n\n**Correct approach**: Vertical slices via tracer bullets. One test → one implementation → repeat. Each test responds to what you learned from the previous cycle. Because you just wrote the code, you know exactly what behavior matters and how to verify it.\n\n```\nWRONG (horizontal):\n  RED:   test1, test2, test3, test4, test5\n  GREEN: impl1, impl2, impl3, impl4, impl5\n\nRIGHT (vertical):\n  RED→GREEN: test1→impl1\n  RED→GREEN: test2→impl2\n  RED→GREEN: test3→impl3\n  ...\n```\n\n## Workflow\n\n### 1. Planning\n\nWhen exploring the codebase, use the project's domain glossary if one exists (e.g. `CONTEXT.md`) and respect any ADRs in the area you're touching, so test names and interface vocabulary match the project's language.\n\nBefore writing any code:\n\n- [ ] Confirm with user what interface changes are needed\n- [ ] Confirm with user which behaviors to test (prioritize)\n- [ ] Identify opportunities for [deep modules](deep-modules.md) (small interface, deep implementation)\n- [ ] Design interfaces for [testability](interface-design.md)\n- [ ] List the behaviors to test (not implementation steps)\n- [ ] Get user approval on the plan\n\nAsk: \"What should the public interface look like? Which behaviors are most important to test?\"\n\n**You can't test everything.** Confirm with the user exactly which behaviors matter most. Focus testing effort on critical paths and complex logic, not every possible edge case.\n\n### 2. Tracer Bullet\n\nWrite ONE test that confirms ONE thing about the system:\n\n```\nRED:   Write test for first behavior → test fails\nGREEN: Write minimal code to pass → test passes\n```\n\nThis is your tracer bullet - proves the path works end-to-end.\n\n### 3. Incremental Loop\n\nFor each remaining behavior:\n\n```\nRED:   Write next test → fails\nGREEN: Minimal code to pass → passes\n```\n\nRules:\n\n- One test at a time\n- Only enough code to pass current test\n- Don't anticipate future tests\n- Keep tests focused on observable behavior\n\n### 4. Refactor\n\nAfter all tests pass, look for [refactor candidates](refactoring.md):\n\n- [ ] Extract duplication\n- [ ] Deepen modules (move complexity behind simple interfaces)\n- [ ] Apply SOLID principles where natural\n- [ ] Consider what new code reveals about existing code\n- [ ] Run tests after each refactor step\n\n**Never refactor while RED.** Get to GREEN first.\n\n## Checklist Per Cycle\n\n```\n[ ] Test describes behavior, not implementation\n[ ] Test uses public interface only\n[ ] Test would survive internal refactor\n[ ] Code is minimal for this test\n[ ] No speculative features added\n```","tags":["tdd","vibestack","timurgaleev","agent-skills","ai-agents","claude-code","cursor-ide","developer-tools","kiro","mcp","prompt-engineering","slash-commands"],"capabilities":["skill","source-timurgaleev","skill-tdd","topic-agent-skills","topic-ai-agents","topic-claude-code","topic-cursor-ide","topic-developer-tools","topic-kiro","topic-mcp","topic-prompt-engineering","topic-slash-commands"],"categories":["vibestack"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/timurgaleev/vibestack/tdd","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add timurgaleev/vibestack","source_repo":"https://github.com/timurgaleev/vibestack","install_from":"skills.sh"}},"qualityScore":"0.457","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 15 github stars · SKILL.md body (4,670 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:06:24.219Z","embedding":null,"createdAt":"2026-05-18T19:06:24.219Z","updatedAt":"2026-05-18T19:06:24.219Z","lastSeenAt":"2026-05-18T19:06:24.219Z","tsv":"'/.vibestack/bin/vibe-learnings-search':92 '/.vibestack/bin/vibe-slug':47 '/dev/null':49,51,75,90,96 '/learnings.jsonl':62 '/projects':59 '1':413 '2':48,50,74,89,95,543 '3':585 '4':627 '5':88,94 'actual':296 'ad':701 'adr':433 'anti':255 'anti-pattern':254 'anticip':618 'api':142 'appli':647 'approach':345 'approv':496 'area':436 'ask':500 'bad':185 'bash':45 'becom':317 'behavior':23,115,223,242,294,297,315,325,329,377,467,488,509,526,561,591,626,679 'behind':644 'break':218,326 'bulk':291 'bullet':17,350,545,576 'candid':636 'capabl':171 'care':181 'cart':166 'case':542 'chang':124,226,321,460 'checklist':674 'checkout':163 'code':122,138,283,372,454,567,599,611,655,659,692 'codebas':418 'collabor':194 'commit':336 'complex':536,643 'confirm':455,463,520,550 'consid':652 'context.md':429 'core':110 'correct':344 'count':69,81,86 'coupl':188 'cover':37 'crap':286 'critic':533 'current':614 'cycl':366,676 'd':77 'data':306 'databas':206 'deep':38,474,479 'deep-modules.md':476 'deepen':640 'describ':144,678 'design':41,481 'detail':29,121 'develop':5,108 'direct':207 'doc':36 'domain':423 'driven':4,107 'duplic':639 'e.g':428 'echo':78,100 'edg':541 'effort':531 'els':99 'end':299,582,584 'end-to-end':581 'enough':610 'entir':125 'entri':82 'eval':46 'everi':539 'everyth':519 'exact':169,375,524 'exampl':247 'exercis':136 'exist':172,427,658 'explor':416 'extern':201 'extract':638 'f':64 'face':314 'fail':235,327,563,596 'featur':700 'fi':98,104 'file':55,66,73 'fine':331 'first':264,560,673 'focus':529,623 'function':232,308 'futur':619 'get':494,670 'glossari':424 'good':129,155 'green':10,279,392,401,405,409,564,597,672 'gt':87 'guidelin':253 'hasn':224 'headlight':335 'home':57 'home/.vibestack':58 'horizont':19,257,270,385 'identifi':471 'imagin':293 'impl1':393,403 'impl2':394,407 'impl3':395,411 'impl4':396 'impl5':397 'implement':28,120,190,240,267,343,354,480,492,681 'import':512 'increment':586 'insensit':318 'instead':208 'integr':133 'integration-styl':132 'interfac':26,40,118,212,444,459,478,482,505,646,685 'interface-design.md':485 'intern':183,193,231,690 'keep':621 'know':374 'l':71 'languag':450 'learn':54,65,68,72,79,80,85,101,362 'like':158,203,507 'limit':93 'list':486 'load':83 'logic':537 'look':506,633 'loop':12,587 'match':446 'matter':378,527 'mean':202 'method':197 'minim':566,598,694 'mock':42,192,252 'mocking.md':249,250 'modul':39,475,641 'move':642 'name':442 'natur':651 'need':462 'never':666 'new':654 'next':594 'none':102 'observ':625 'one':351,353,426,547,551,604 'opportun':472 'outrun':333 'pass':323,569,571,601,602,613,632 'path':139,534,579 'pattern':256 'per':675 'philosophi':109 'plan':414,499 'possibl':540 'preambl':44 'previous':365 'principl':111,649 'priorit':470 'privat':196 'produc':285 'project':421,448 'prove':577 'public':25,117,141,504,684 'queri':204 'rather':310 're':438 'read':157 'real':137,320 'red':9,273,386,400,404,408,556,592,669 'red-green-refactor':8 'refacto':43 'refactor':11,33,176,221,628,635,664,667,691 'refactoring.md':637 'remain':590 'renam':229 'repeat':355 'respect':431 'respond':358 'reveal':656 'right':398 'rule':603 'run':660 'see':243 'shape':303 'shouldn':127 'sign':215 'signatur':309 'simpl':645 'skill' 'skill-tdd' 'slice':15,20,258,271,347 'slug':52,60 'small':477 'solid':648 'source-timurgaleev' 'specif':160 'specul':699 'step':493,665 'structur':184,307,339 'style':134 'sub':35 'sub-doc':34 'surviv':32,175,689 'system':147,555 'tdd':1 'tell':167 'test':3,21,106,112,126,130,156,174,186,195,217,234,237,239,263,277,287,288,292,301,316,338,352,357,441,469,490,514,518,530,548,558,562,570,595,605,615,620,622,631,661,677,682,687,697 'test-driven':2,105 'test1':387,402 'test2':388,406 'test3':389,410 'test4':390 'test5':391 'testabl':484 'tests.md':244,245 'thing':305,552 'time':608 'topic-agent-skills' 'topic-ai-agents' 'topic-claude-code' 'topic-cursor-ide' 'topic-developer-tools' 'topic-kiro' 'topic-mcp' 'topic-prompt-engineering' 'topic-slash-commands' 'touch':439 'tr':76 'tracer':16,349,544,575 'treat':272 'true':97 'understand':341 'unknown':53,61 'use':210,419,683 'user':161,313,457,465,495,523 'user-fac':312 'valid':165 'verifi':22,114,199,382 'vertic':14,346,399 'vertical-slic':13 'via':348 'vibestack':56 'vocabulari':445 'warn':214 'wc':70 'work':580 'workflow':412 'would':688 'write':261,275,281,452,546,557,565,593 'written':289 'wrong':384 'wrote':370 'yet':103","prices":[{"id":"e45d6fbe-387b-4692-904d-87987a2b8fca","listingId":"eb996877-eb5e-4816-896e-4d8f8e458fa9","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"timurgaleev","category":"vibestack","install_from":"skills.sh"},"createdAt":"2026-05-18T19:06:24.219Z"}],"sources":[{"listingId":"eb996877-eb5e-4816-896e-4d8f8e458fa9","source":"github","sourceId":"timurgaleev/vibestack/tdd","sourceUrl":"https://github.com/timurgaleev/vibestack/tree/main/skills/tdd","isPrimary":false,"firstSeenAt":"2026-05-18T19:06:24.219Z","lastSeenAt":"2026-05-18T19:06:24.219Z"}],"details":{"listingId":"eb996877-eb5e-4816-896e-4d8f8e458fa9","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"timurgaleev","slug":"tdd","github":{"repo":"timurgaleev/vibestack","stars":15,"topics":["agent-skills","ai-agents","claude-code","cursor-ide","developer-tools","kiro","mcp","prompt-engineering","slash-commands"],"license":"mit","html_url":"https://github.com/timurgaleev/vibestack","pushed_at":"2026-05-18T18:19:05Z","description":"vibestack is a portable skill pack for AI coding agents. Slash commands like /office-hours, /ship, /investigate, /tdd, /review install once and work across every agent that supports the Agent Skills open standard — Claude Code, Cursor, Kiro, and a growing list of others. ","skill_md_sha":"5e5043016bc393232b2886195d9f0b2abb0d5ce1","skill_md_path":"skills/tdd/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/timurgaleev/vibestack/tree/main/skills/tdd"},"layout":"multi","source":"github","category":"vibestack","frontmatter":{"name":"tdd","description":"Test-driven development with the red-green-refactor loop. Vertical-slice tracer bullets,\nnot horizontal slicing. Tests verify behavior through public interfaces, not implementation\ndetails, so they survive refactors. Sub-docs cover deep modules, interface design,\nmocking, refactoring, and what makes a good test.\nUse when asked to \"do tdd\", \"red-green-refactor\", \"test-first development\",\n\"build with tdd\", or you want integration-style tests that survive refactors.\nProactively suggest when starting a new feature or bug fix where the behavior is\ntestable through a public interface."},"skills_sh_url":"https://skills.sh/timurgaleev/vibestack/tdd"},"updatedAt":"2026-05-18T19:06:24.219Z"}}