docs(tdd): make test-driven-development ecosystem-neutral (#404 Phase 1)

- SKILL.md gains a 'Discover the Stack First' step: identify the
  language, build system, checked-in wrappers, test framework, and
  documented commands before choosing any test command, and run the
  repository's own focused/full-suite commands throughout the loop
- verification checklist no longer hardcodes 'npm test'; red flag added
  for reaching for a default test command without checking the repo
- references/testing-patterns.md relabeled in place as JavaScript/
  TypeScript examples illustrating the universal principles (no
  relocation, per the #361/#236 sequencing agreed in the issue)
- new behavioral eval: a Python/unittest fixture verifying the skill
  adapts to non-npm repository tooling
This commit is contained in:
ayobamiseun committed 2026-07-19 17:08:30 +01:00
1 parent 2fbfa004a0
commit 2e49319164
8 files changed
+79 -5

No files matched your search

+1
View File
@@ -6,3 +6,4 @@ node_modules/
.claude/.simplify-ignore-cache/
.claude/sdd-cache/
evals/results/
__pycache__/
+1 -1
View File
@@ -280,7 +280,7 @@ Quick-reference material that skills pull in when needed:
| Reference | Covers |
|-----------|--------|
| [definition-of-done.md](references/definition-of-done.md) | Project-wide standing bar every change clears, contrasted with per-task acceptance criteria |
| [testing-patterns.md](references/testing-patterns.md) | Test structure, naming, mocking, React/API/E2E examples, anti-patterns |
| [testing-patterns.md](references/testing-patterns.md) | Test structure, naming, mocking, React/API/E2E examples, anti-patterns (JavaScript/TypeScript) |
| [security-checklist.md](references/security-checklist.md) | Pre-commit checks, auth, input validation, headers, CORS, OWASP Top 10 |
| [performance-checklist.md](references/performance-checklist.md) | Core Web Vitals targets, frontend/backend checklists, measurement commands |
| [accessibility-checklist.md](references/accessibility-checklist.md) | Keyboard nav, screen readers, visual design, ARIA, testing tools |
+15
View File
@@ -52,6 +52,21 @@
"A regression test covers the reported three-at-3.335 currency case",
"The full suite is run after the minimal fix"
]
},
{
"id": 3,
"prompt": "Add debit entries to the ledger, test-first. A debit subtracts its amount from the balance and must not drive the balance below zero.",
"expected_output": "A failing unittest written and shown failing first, a minimal implementation, and the full suite run with the repository's own Python test command",
"files": [
"test-driven-development-ecosystem"
],
"expectations": [
"The repository's stack (Python, unittest) is identified before any test command is chosen",
"Tests are run with the repository's own command (python3 -m unittest), not npm test or another ecosystem's tool",
"A failing test is written and shown failing before the implementation",
"The below-zero rule gets its own test case",
"The full suite is run after the change"
]
}
]
}
@@ -0,0 +1,9 @@
# Ledger
Small Python ledger utilities. No dependencies beyond the standard library.
Run the tests:
```
python3 -m unittest
```
@@ -0,0 +1,15 @@
"""Simple in-memory ledger utilities."""
def apply_entries(balance, entries):
"""Apply entries to a starting balance and return the result.
Entries are (kind, amount) tuples. Only "credit" entries are
supported; anything else raises ValueError.
"""
for kind, amount in entries:
if kind == "credit":
balance += amount
else:
raise ValueError(f"unsupported entry kind: {kind}")
return balance
@@ -0,0 +1,19 @@
import unittest
from ledger import apply_entries
class ApplyEntriesTest(unittest.TestCase):
def test_applies_a_single_credit(self):
self.assertEqual(apply_entries(100, [("credit", 25)]), 125)
def test_applies_multiple_credits_in_order(self):
self.assertEqual(apply_entries(0, [("credit", 10), ("credit", 5)]), 15)
def test_rejects_unknown_entry_kinds(self):
with self.assertRaises(ValueError):
apply_entries(0, [("transfer", 10)])
if __name__ == "__main__":
unittest.main()
+2 -2
View File
@@ -1,6 +1,6 @@
# Testing Patterns Reference
# Testing Patterns Reference (JavaScript/TypeScript)
Quick reference for common testing patterns across the stack. Use alongside the `test-driven-development` skill.
Quick reference of JavaScript/TypeScript testing patterns — Jest, React Testing Library, Supertest, and Playwright — illustrating the universal principles from the `test-driven-development` skill. The principles (Arrange-Act-Assert, naming, mock discipline, anti-patterns) apply in any ecosystem; the syntax and tooling shown here are JS/TS-specific. In another stack, follow the same principles with the repository's own test framework and commands.
## Table of Contents
+17 -2
View File
@@ -21,6 +21,20 @@ Write a failing test before writing the code that makes it pass. For bug fixes,
**Related:** For browser-based changes, combine TDD with runtime verification using Chrome DevTools MCP — see the Browser Testing section below.
## Discover the Stack First
The TDD cycle is universal; the commands are not. Before writing the first test, discover how *this* repository tests, and use its commands for every RED, GREEN, and verification step:
- **Language and build system** — `package.json`, `pom.xml`/`build.gradle`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `Gemfile`, a `Makefile`
- **Checked-in wrappers** — prefer `./gradlew`, `./mvnw`, `make test`, or a repo script over globally installed tools
- **Test framework and configuration** — and how it runs a single focused test vs the full suite
- **Existing conventions** — where tests live, how files are named, what patterns neighboring tests follow
- **Documented commands** — README, CONTRIBUTING, and CI workflows show the commands that actually gate merges
Run the repository's focused-test command during the loop and its full-suite command before completion. Never assume a default like `npm test` — a Gradle, Cargo, or pytest project has its own equivalent.
The examples below use TypeScript for illustration; the workflow is identical in any language once you've discovered the project's own tooling.
## The TDD Cycle
```
@@ -344,7 +358,7 @@ This separation ensures the test is written without knowledge of the fix, making
## See Also
For detailed testing patterns, examples, and anti-patterns across frameworks, see `references/testing-patterns.md`.
For JavaScript/TypeScript testing patterns illustrating these principles — Jest, React Testing Library, Supertest, Playwright — see `references/testing-patterns.md`. The principles transfer to any ecosystem; the syntax and tools there are JS/TS-specific.
## Common Rationalizations
@@ -361,6 +375,7 @@ For detailed testing patterns, examples, and anti-patterns across frameworks, se
## Red Flags
- Writing code without any corresponding tests
- Reaching for a default test command (`npm test`) without checking what this repository actually uses
- Tests that pass on the first run (they may not be testing what you think)
- "All tests pass" but no tests were actually run
- Bug fixes without reproduction tests
@@ -374,7 +389,7 @@ For detailed testing patterns, examples, and anti-patterns across frameworks, se
After completing any implementation:
- [ ] Every new behavior has a corresponding test
- [ ] All tests pass: `npm test`
- [ ] The full suite passes, run with the repository's own test command (`npm test`, `./gradlew test`, `pytest`, `go test ./...`, ...)
- [ ] Bug fixes include a reproduction test that failed before the fix
- [ ] Test names describe the behavior being verified
- [ ] No tests were skipped or disabled