Installs into .claude/skills of the current project.
Are you the author of Testgen?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/pillip-testgen)
---
name: testgen
description: Scan the codebase for missing or hollow tests, generate unit/integration/E2E tests, and create a PR.
argument-hint: '[file or directory path, or omit for full scan]'
disable-model-invocation: false
allowed-tools: Read, Glob, Grep, Write, Edit, Bash(bash scripts/checkpoint.sh *), Bash(bash scripts/wt_setup.sh *), Bash(bash scripts/wt_cleanup.sh *), Bash(bash scripts/registry_edit.sh *), Bash(bash scripts/flock_edit.sh *), Bash(bash scripts/worktree.sh *), Bash(python3 scripts/*), Bash(git *), Bash(gh *), Bash(pytest *), Bash(npm *), Bash(bash ${CLAUDE_PLUGIN_ROOT}/scripts/*), Bash(python3 ${CLAUDE_PLUGIN_ROOT}/scripts/*)
---
<!-- AUTO-GENERATED by scripts/gen_skills.py — DO NOT EDIT. Edit SKILL.md.tmpl instead. -->
## Kit Preamble — testgen
### Kit Script Root
Kit root: `${CLAUDE_PLUGIN_ROOT}`
- Absolute path above → plugin install (substituted at load time; no project
`scripts/` dir): prefix every kit script command with it, e.g.
`bash <kit-root>/scripts/checkpoint.sh …`. Absolute paths also work from worktrees.
- Literal `${…}` placeholder above → standalone layout: run commands as written.
### Project Context Detection
Run these checks silently at the start. Use results to adapt behavior:
- `[ -f issues.md ]` — if true, this project uses the sprint system. Respect issue numbering and STATUS.md.
- `[ -f docs/sprint_state.md ]` — if true and Status shows `running`, a sprint is active. Be aware of parallel work in worktrees.
- `[ -f docs/prd_digest.md ]` — if true, read it for quick project context before starting.
### Kit Rules
- Verify `gh auth status` before any GitHub operation.
## Checkpoint Rules — MANDATORY
Every phase in this skill that has a CHECKPOINT block must be verified. Run the verification command after completing each phase. Blocking gates exit non-zero on failure: STOP immediately, report, do NOT proceed. Advisory gates always exit 0 and print an `ADVISORY:` line on failure: report the gap, self-correct, then continue (ISSUE-031). Never skip running either tier.
**Slug convention**: After creating the worktree, store the branch slug (e.g., `testgen/add-missing-tests`) for use in checkpoint commands.
## Argument Validation (run before anything else)
1) If `$ARGUMENTS` is provided, verify it exists as a file or directory using Glob or Read.
- If the path does not exist: stop with "Target path not found: `<path>`. Please provide a valid file or directory path."
2) If `$ARGUMENTS` is empty: scan the entire project (all source files).
Algorithm:
1) Ensure `gh` authenticated (`gh auth status`).
2) Gather context — read the following docs (if they exist, skip silently if not).
**Read all applicable documents via parallel Read tool calls in a single message.**
- `docs/test_plan.md` — test strategy, risk matrix, critical flows for E2E prioritization
- `docs/architecture.md` — tech stack, modules, dependencies
- recalled **review lessons** (native memory) — known recurring quality issues
3) **Scan phase — Identify test gaps**:
a) Detect project language(s):
- **Python**: Look for `pyproject.toml`, `setup.py`, or `*.py` source files. Test convention: `tests/test_*.py`.
- **JS/TS**: Look for `package.json`. Test convention: `*.test.ts`, `*.spec.ts`, `__tests__/`.
b) For the target path (or entire project), find all source files excluding:
- Test files themselves (`test_*`, `*_test.*`, `*.spec.*`, `*.test.*`)
- Config files (`.json`, `.toml`, `.yaml`, `.yml`, `.md`, `.css`, `.html`, `.lock`)
- Generated files, `node_modules/`, `__pycache__/`, `.git/`, `dist/`, `build/`
- `__init__.py` files that are empty or import-only
c) For each source file, check if a corresponding test file exists:
- Python `src/module.py` → `tests/test_module.py`
- JS/TS `src/component.ts` → `src/component.test.ts` or `src/component.spec.ts` or `__tests__/component.test.ts`
d) For source files that have test files, check for **hollow tests**:
- Python: test file must contain `def test_` functions with `assert`/`mock`/`raises`
- JS/TS: test file must contain `it(`/`test(` with `expect`/`toBe`/`toEqual`
e) **E2E gap analysis** (if `docs/test_plan.md` exists):
- Read the Critical Flows from the Risk Matrix
- Check if `tests/e2e/` or `e2e/` directory has test files covering those flows
- Identify High-risk flows without E2E coverage
4) **Present gap report** to the user:
```
## Test Coverage Gap Report
### Missing Unit Tests (N files)
| Source File | Expected Test | Priority |
|-------------|--------------|----------|
| src/auth.py | tests/test_auth.py | High (auth = critical) |
### Hollow Tests (N files)
| Test File | Issue |
|-----------|-------|
| tests/test_utils.py | No assertions found |
### Missing E2E Tests (N flows)
| Critical Flow | Risk | Status |
|--------------|------|--------|
| User login | High | No E2E test |
```
Ask user to confirm which gaps to fill (all, or a subset).
5) After user approval, create worktree + auto-freeze in one step:
```bash
WT="$(bash scripts/wt_setup.sh testgen/add-missing-tests)"
```
`wt_setup.sh` creates the worktree and writes the freeze marker inside
`.claude-kit/freeze-dir.txt` atomically. All subsequent file operations
happen inside `$WT/`.
> **CHECKPOINT — ADVISORY (report & continue)**
> Run: `bash scripts/checkpoint.sh --skill testgen --phase worktree --issue "$SLUG"`
> Advisory: exits 0 even on failure, printing an `ADVISORY:` line — report the gap, self-correct, then continue.
6) **Generate tests** inside `$WT/`:
For each approved gap, ask test-generator subagent to:
a) Read the source file thoroughly — understand all public functions, classes, methods
b) Read existing tests in the project to match style and patterns
c) Write test file with:
- **Unit tests**: happy path + at least one edge case per public function
- **Integration tests**: if the source involves API endpoints or DB queries
- **E2E tests**: for Critical Flows from test_plan.md (Playwright for web, Maestro for mobile)
d) Use descriptive test names: `test_login_with_expired_token_returns_401`
e) Mock external dependencies — no real HTTP calls or DB connections in unit tests
f) Each test must have real assertions (not `pass` or empty bodies)
7) **Run all generated tests** inside `$WT/`:
- Python: `pytest tests/ -q --tb=short`
- JS/TS: `npm test`
- If any test fails: fix the test (not the source code). Re-run until all pass.
- If a test cannot be fixed after 2 attempts: remove it and log a warning.
> **CHECKPOINT — MANDATORY — NEVER SKIP**
> Run: `bash scripts/checkpoint.sh --skill testgen --phase test --issue "$SLUG"`
> If exit code ≠ 0: STOP immediately and report the failure. Do NOT proceed.
8) Create GH Issue:
- `gh issue create --title "test: add missing tests for [scope]" --body "<body>"`
- Body must include: gap report summary, number of tests generated, coverage improvement.
9) Commit + push (from `$WT/`).
> **CHECKPOINT — ADVISORY (report & continue)**
> Run: `bash scripts/checkpoint.sh --skill testgen --phase push --issue "$SLUG"`
> Advisory: exits 0 even on failure, printing an `ADVISORY:` line — report the gap, self-correct, then continue.
10) Create PR:
- `gh pr create --title "test: add missing tests for [scope]" --body "Closes #<issue_number>\n\n<gap report summary>"`
11) Report the PR URL to the user.
## Sprint Integration (optional)
If `issues.md` exists in the project root, register this work in the sprint ecosystem:
1) Read `issues.md` to find the next available ISSUE-NNN number.
2) Append a new issue entry via the registry wrapper:
```bash
bash scripts/registry_edit.sh issues.md -- bash -c '<append issue entry>'
```
Issue fields:
- Title: same as GH Issue title
- Track: platform
- Priority: P2
- Status: done (PR already created)
- GH-Issue: `<number>`
- PR: `<pr_url>`
- Depends-On: none
3) This allows team-lead to track standalone skill work in sprint_state.md.
If `issues.md` does not exist, skip this step silently.
## Error Handling
- If `gh auth status` fails: stop and instruct the user to run `gh auth login`.
- If no test gaps found: report "All source files have corresponding tests with real assertions. No action needed." and stop.
- If tests fail after generation: attempt to fix the test (2 tries max). If still failing, remove the test and report.
- If `git push` fails: check for upstream conflicts; report and stop.
## Rollback
- Use `bash scripts/wt_cleanup.sh <branch>` for safe worktree removal —
the wrapper cd's to main root and removes the worktree in a single subshell.
- If failure occurs after worktree creation but before PR:
1. `bash scripts/wt_cleanup.sh <branch>`
2. `git push origin --delete <branch>` (remote cleanup, if pushed)
- If failure occurs after PR creation: `gh pr close <pr_number>` then clean up as above.
## Shared Registry Files
**IMPORTANT**: Never commit `issues.md`, `STATUS.md`, or `CHANGELOG.md` to the feature branch.
These are registry files managed only on main. Always use `bash scripts/registry_edit.sh <file> -- bash -c '<update command>'` — the wrapper resolves the main repo root internally.
## Guidelines
- Prioritize by risk: test critical paths first (auth, payments, data mutations).
- Match existing test style — read at least 2 existing test files before writing new ones.
- Don't generate tests for trivial code (empty `__init__.py`, pure config, type-only files).
- E2E tests should focus on critical user journeys, not duplicate unit test coverage.
- If `docs/test_plan.md` exists, use its framework recommendations (Playwright, Maestro, pytest).
- Keep generated tests independent — no shared mutable state between tests.