Generate Tests Skill
Generate high-quality, behavior-driven test files from acceptance criteria or existing source code. This skill auto-detects the project's test framework, loads framework-specific patterns, and spawns test-writer agents to produce runnable test files that follow project conventions.
CRITICAL: Complete ALL 6 phases. The workflow is not complete until Phase 6: Report is finished. After completing each phase, immediately proceed to the next phase without waiting for user prompts.
Core Principles
- Tests before implementation -- Generated tests should initially fail (RED state) when no implementation exists, confirming they test real behavior.
- Behavior over implementation -- Test what the code does, not how it does it. Tests should survive refactoring.
- Follow project conventions -- Match the project's existing test framework, file naming, directory structure, and assertion patterns.
- Standalone operation -- This skill works independently. It does not require the SDD pipeline,
tdd-cycle, or any other skill to function.
AskUserQuestion is MANDATORY
IMPORTANT: You MUST use the AskUserQuestion tool for ALL questions to the user. Never ask questions through regular text output.
- Framework selection questions -> AskUserQuestion
- Clarifying questions about scope -> AskUserQuestion
- Confirmation questions -> AskUserQuestion
Text output should only be used for presenting information, summaries, and progress updates.
Phase 1: Parse Input
Goal: Determine the operating mode and resolve input paths.
Analyze the $ARGUMENTS to determine which mode to use:
Mode Detection
Criteria-Driven Mode -- triggered when input is:
- A spec file path (e.g.,
specs/SPEC-feature.md) - A task ID (e.g.,
5,#5,task-5) - A spec section reference (e.g.,
specs/SPEC-feature.md Section 5.1)
Code-Analysis Mode -- triggered when input is:
- A source file path (e.g.,
src/utils.py,src/services/auth.ts) - A directory path (e.g.,
src/services/)
Ambiguous input: If the input could be either mode (e.g., a path that could be a spec or source file), check the file content. If it contains **Acceptance Criteria:** or is a markdown file in a specs/ directory, use criteria-driven mode. Otherwise, use code-analysis mode.
Path Resolution
- Resolve relative paths against the project root
- For task IDs: use
TaskGetto retrieve the task description, then extract acceptance criteria - For spec section references: read the spec file and locate the referenced section
- For directories: glob for source files (exclude test files, node_modules, pycache, .git)
- Validate that all resolved paths exist; if not, proceed to error handling (Phase 1 error cases below)
Error Cases
Invalid spec path:
ERROR: Spec file not found: {path}
Did you mean one of these?
{List matching files from Glob search for similar names}
Usage: /generate-tests <spec-path|task-id|file-path>
Invalid task ID:
ERROR: Task #{id} not found.
Available tasks:
{List first 5 pending/in-progress tasks from TaskList}
Usage: /generate-tests <task-id>
Empty directory:
ERROR: No source files found in {path}.
The directory exists but contains no files matching supported extensions (.py, .ts, .tsx, .js, .jsx).
Phase 2: Detect Framework
Goal: Auto-detect the project's test framework using the detection chain.
Load Detection Chain
Read the framework detection reference for the full detection algorithm:
Read: ${CLAUDE_PLUGIN_ROOT}/skills/generate-tests/references/framework-templates.md
Follow the detection chain in priority order:
Step 1: Config-File Detection (High Confidence)
Check for framework configuration files:
Python:
pyproject.tomlwith[tool.pytest.ini_options]or[tool.pytest]-> pytestsetup.cfgwith[tool:pytest]-> pytestpytest.iniexists -> pytestconftest.pyat project root or intests/-> pytest
TypeScript/JavaScript:
vitest.config.*exists -> Vitest (takes priority)jest.config.*exists -> Jestpackage.jsonwithvitestin dependencies/devDependencies -> Vitestpackage.jsonwithjestin dependencies/devDependencies -> Jestpackage.jsonwith"jest": {}config section -> Jest
Step 2: Existing Test File Detection (Medium Confidence)
If no config files found, scan for existing test files:
test_*.pyor*_test.py-> pytest*.test.ts/*.spec.tswithvitestimports -> Vitest*.test.ts/*.spec.tswithjestimports or no explicit imports -> Jest
Step 3: Settings Fallback (Low Confidence)
If detection is still ambiguous, check .claude/agent-alchemy.local.md for:
tdd:
framework: pytest # or jest, vitest, auto
If tdd.framework is set to a recognized value (pytest, jest, vitest), use it. If set to auto or an unrecognized value, continue to Step 4.
Step 4: User Prompt Fallback
If all detection methods fail, prompt the user:
AskUserQuestion:
questions:
- header: "Test Framework"
question: "No test framework was detected in this project. Which framework should be used for test generation?"
options:
- label: "pytest"
description: "Python testing framework (recommended for Python projects)"
- label: "Jest"
description: "JavaScript/TypeScript testing framework"
- label: "Vitest"
description: "Vite-native testing framework (modern alternative to Jest)"
- label: "Other"
description: "A different framework (tests may need manual adjustment)"
multiSelect: false
Detection Result
After detection, record:
- Framework: pytest | Jest | Vitest
- Test directory: Path to test root (e.g.,
tests/,__tests__/,src/) - Naming pattern: File naming convention (e.g.,
test_*.py,*.test.ts) - Assertion library: Default or extended (e.g.,
@testing-library/jest-dom) - Existing fixtures: Notable fixtures or test utilities found
- Confidence: High | Medium | Low
Monorepo Handling
In monorepos, detect framework per-directory by walking up from the target source file to find the nearest config file. Different directories may use different frameworks.
Phase 3: Load References
Goal: Load framework-specific patterns and project conventions.
Load Test Patterns
Read the test patterns reference for framework-specific guidance:
Read: ${CLAUDE_PLUGIN_ROOT}/skills/generate-tests/references/test-patterns.md
This provides:
- Arrange-Act-Assert and Given-When-Then patterns
- Behavior-driven vs implementation-detail test guidance
- Framework-specific naming conventions
- Anti-patterns to avoid
Load Framework Templates
Read the framework templates reference for boilerplate structure:
Read: ${CLAUDE_PLUGIN_ROOT}/skills/generate-tests/references/framework-templates.md
This provides:
- Boilerplate templates for pytest, Jest, and Vitest
- Configuration reference for each framework
- Fixture and test utility patterns
Load Cross-Plugin Skills
Load language-specific patterns and project conventions for the target project:
Read: ${CLAUDE_PLUGIN_ROOT}/../core-tools/skills/language-patterns/SKILL.md
Read: ${CLAUDE_PLUGIN_ROOT}/../core-tools/skills/project-conventions/SKILL.md
Apply these skills' guidance when generating tests to ensure:
- Language idioms are followed (TypeScript strict typing, Python type hints)
- Project naming conventions are matched
- Import patterns are consistent with the codebase
Scan Existing Tests
If the project has existing test files:
- Read 2-3 representative test files to understand the project's test style
- Note patterns: fixture usage, test grouping, assertion style, mock patterns
- Match these patterns in generated tests for consistency
Phase 4: Generate Tests
Goal: Produce test files by