From hieutrtr-ai1-skills
Test-driven development workflow enforcement for Python and React projects. Use when the user requests TDD, test-first development, or red-green-refactor methodology. Enforces strict cycle: write ONE failing test -> implement minimum code to pass -> refactor while green -> repeat. Applies to both backend (pytest) and frontend (Testing Library). Changes agent behavior to write tests before code. Does NOT provide testing patterns (use pytest-patterns or react-testing-patterns for how to write tests).
npx claudepluginhub joshuarweaver/cascade-code-testing-misc --plugin hieutrtr-ai1-skillsThis skill is limited to using the following tools:
Activate this skill when:
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Activate this skill when:
Do NOT use this skill for:
pytest-patterns or react-testing-patterns for HOW to write tests)┌─────────────────────────────────────────────────────┐
│ │
│ ┌─────┐ ┌───────┐ ┌──────────┐ │
│ │ RED │ ──→ │ GREEN │ ──→ │ REFACTOR │ ──→ ... │
│ └─────┘ └───────┘ └──────────┘ │
│ │
│ Write ONE Write MINIMUM Clean up code │
│ failing code to make while ALL tests │
│ test it pass stay GREEN │
│ │
└─────────────────────────────────────────────────────┘
Backend (pytest):
pytest tests/unit/test_user_service.py::test_create_user_returns_user -x
# Expected: FAILED (function/class does not exist yet)
Frontend (Vitest):
npx vitest run src/hooks/useAuth.test.ts --reporter=verbose
# Expected: FAILED (hook/component does not exist yet)
Rules for RED phase:
# Backend
pytest tests/unit/test_user_service.py -x
# Frontend
npx vitest run src/hooks/useAuth.test.ts
Rules for GREEN phase:
# After each refactoring change
pytest tests/ -x # Must pass
npx vitest run # Must pass
Rules for REFACTOR phase:
After a successful REFACTOR phase:
These rules are non-negotiable when this skill is active:
1. Write test: tests/unit/test_user_service.py::test_create_user_returns_user
2. Run: pytest tests/unit/test_user_service.py::test_create_user_returns_user -x
3. See: FAILED - ImportError or AssertionError
4. Implement: app/services/user_service.py (minimum code)
5. Run: pytest tests/unit/test_user_service.py -x
6. See: PASSED
7. Refactor: Clean up, run tests again
8. Commit: "Add UserService.create_user"
9. Next test: test_create_user_rejects_duplicate_email
1. Write test: src/components/UserCard.test.tsx::renders user name
2. Run: npx vitest run src/components/UserCard.test.tsx
3. See: FAILED - module not found
4. Implement: src/components/UserCard.tsx (minimum code)
5. Run: npx vitest run src/components/UserCard.test.tsx
6. See: PASSED
7. Refactor: Clean up, run tests again
8. Commit: "Add UserCard component"
9. Next test: calls onEdit when button clicked
When fixing a bug, always start with a failing test that reproduces the bug:
1. Reproduce: Understand the bug and its trigger condition
2. Write test: Test that exercises the exact scenario that causes the bug
3. Run: Confirm FAILED (the test reproduces the bug)
4. Fix: Implement the minimum fix
5. Run: Confirm PASSED (bug is fixed)
6. Refactor: Clean up if needed
7. Commit: "Fix: [describe the bug]"
This guarantees the bug cannot regress — the test will catch it.
Cycle 1 — RED: Test that create_user returns a user
async def test_create_user_returns_user(db_session):
service = UserService(db_session)
user = await service.create_user(UserCreate(email="a@b.com", password="12345678", display_name="A"))
assert user.email == "a@b.com"
assert user.id is not None
GREEN: Implement UserService.create_user with basic logic.
REFACTOR: Extract password hashing. Commit.
Cycle 2 — RED: Test that duplicate email raises error
async def test_create_user_rejects_duplicate_email(db_session):
service = UserService(db_session)
await service.create_user(UserCreate(email="a@b.com", password="12345678", display_name="A"))
with pytest.raises(ConflictError):
await service.create_user(UserCreate(email="a@b.com", password="87654321", display_name="B"))
GREEN: Add duplicate check before insert. REFACTOR: Clean up. Commit.
Cycle 3 — RED: Test that password is hashed
async def test_create_user_hashes_password(db_session):
service = UserService(db_session)
user = await service.create_user(UserCreate(email="a@b.com", password="12345678", display_name="A"))
assert user.hashed_password != "12345678"
assert verify_password("12345678", user.hashed_password)
GREEN: Already passing from cycle 1 refactor? Then this test is a verification, not a RED. Write a test for a NEW behavior instead.
When to skip TDD: Configuration files (.env, tsconfig.json), static content, auto-generated code (Alembic migrations), one-off scripts, and exploratory prototyping.
TDD with external dependencies: Mock at the boundary. If testing a service that calls an external API, mock the API client, not the HTTP library. Test the service's behavior, not the mock.
Large features: Break the feature into small, testable behaviors. Each behavior gets its own RED-GREEN-REFACTOR cycle. The sum of all cycles implements the full feature.
Refactoring existing code without tests: First write tests for the existing behavior (characterization tests). Then refactor with those tests as a safety net. This is not strict TDD but is a valid use of the test-first mindset.
Pair with pattern skills: This skill defines the WORKFLOW (when to write tests vs code). Use pytest-patterns or react-testing-patterns for the PATTERNS (how to structure tests, which assertions to use).