Test-Driven Development workflow enforcement. Activates when writing new features, fixing bugs, or refactoring code. Enforces RED-GREEN-REFACTOR cycle with 80%+ coverage, edge case coverage, and anti-pattern avoidance.
From sentinelnpx claudepluginhub digistrique-solutions/strique-marketplace --plugin sentinelThis skill uses the workspace's default tool permissions.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Guides agent creation for Claude Code plugins with file templates, frontmatter specs (name, description, model), triggering examples, system prompts, and best practices.
This skill enforces disciplined TDD methodology. Tests are written BEFORE implementation, coverage targets are met, and anti-patterns are avoided.
Write a single test that describes the expected behavior. Run it. It MUST fail.
# This test should FAIL because create_user() does not exist yet
def test_create_user_returns_user_with_hashed_password():
user = create_user(email="test@example.com", password="secret123")
assert user.email == "test@example.com"
assert user.password_hash != "secret123"
assert len(user.password_hash) > 0
Critical: If the test passes before you write the implementation, the test is wrong. It is either testing a mock, asserting nothing meaningful, or the behavior already exists.
# Python
pytest tests/test_users.py::test_create_user_returns_user_with_hashed_password -x -v
# TypeScript
npx vitest run src/users.test.ts -t "create user"
# JavaScript
npm test -- --testPathPattern="users" --testNamePattern="create user"
The test must fail for the right reason -- the function does not exist or does not produce the expected result. Not a setup error, import error, or syntax error.
Write the minimum code to make the test pass. Nothing more.
def create_user(email: str, password: str) -> User:
password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
return User(email=email, password_hash=password_hash)
pytest tests/test_users.py::test_create_user_returns_user_with_hashed_password -x -v
Improve the code without changing behavior. Tests must stay green.
Run the full test suite after refactoring to catch unintended regressions.
Go back to Step 1 with the next test case. One test at a time.
| Metric | Target |
|---|---|
| Line coverage | 80%+ |
| Branch coverage | 80%+ |
| Function coverage | 80%+ |
| Statement coverage | 80%+ |
# Python
pytest --cov=src --cov-report=term-missing tests/
# TypeScript/JavaScript
npx vitest run --coverage
# or
npx jest --coverage
80% is the floor, not the ceiling. Critical paths (auth, payments, data mutations) should approach 100%. Utility code and simple getters can be lower. The average across the module should be 80%+.
Every function should be tested with these categories:
Your Code --> [Mock Boundary] --> External World
- HTTP APIs
- Databases (for unit tests)
- File system
- Time/random
- Third-party SDKs
Mock at the boundary. Never mock your own code.
This defeats the purpose of TDD. Tests written after code tend to test the implementation rather than the behavior. They pass by construction and fail to catch real bugs.
Remedy: Discipline. Write the test first. Run it. Watch it fail. Then implement.
If your test creates a mock, calls the mock, and asserts the mock returned what you told it to, you have tested nothing.
Remedy: Mock only external dependencies. Call the real function under test.
Writing 20 tests before any implementation leads to analysis paralysis and tests that are disconnected from the actual design.
Remedy: One test at a time. RED-GREEN-REFACTOR. Repeat.
If you never see the test fail, you do not know it can fail. A test that cannot fail provides zero value.
Remedy: Always run the test before implementing. Verify it fails for the right reason.
Testing internal state, private methods, or specific function call sequences makes tests brittle. They break on refactoring even when behavior is preserved.
Remedy: Test observable behavior. What goes in, what comes out, what side effects occur.
Skipping refactoring leads to passing but messy code. The refactor step is where code quality improves.
Remedy: After every GREEN, ask: can this be simpler, clearer, or better named? Refactor with confidence because tests protect you.
def test_calculate_discount_applies_percentage():
# Arrange
price = Decimal("100.00")
discount_percent = 20
# Act
result = calculate_discount(price, discount_percent)
# Assert
assert result == Decimal("80.00")
# GOOD -- each test verifies one behavior
def test_login_succeeds_with_valid_credentials(): ...
def test_login_fails_with_wrong_password(): ...
def test_login_fails_with_nonexistent_email(): ...
def test_login_locks_account_after_five_failures(): ...
# BAD -- one test verifies everything
def test_login(): ... # 50 lines checking all cases
Test names should describe the scenario and expected outcome:
test_<function>_<scenario>_<expected_result>
test_create_user_with_duplicate_email_raises_conflict_error
test_calculate_tax_with_zero_amount_returns_zero
test_parse_date_with_invalid_format_raises_value_error
1. Pick the next behavior to implement
2. Write ONE failing test (RED)
3. Run it -- verify it FAILS
4. Write minimal code to pass (GREEN)
5. Run it -- verify it PASSES
6. Refactor -- keep tests green (IMPROVE)
7. Run full suite -- verify no regressions
8. Repeat from step 1
9. Check coverage -- verify 80%+