> unit-test-starter
Generate thorough Python 3 pytest unit tests across a repo by scanning every *.py file and each function, writing one test module per source file while skipping IO/network behavior and documenting gaps.
curl "https://skillshub.wtf/vosslab/vosslab-skills/unit-test-starter?format=md"Unit test starter (Python3 + pytest)
Overview
Create thorough, deterministic Python 3 unit tests with pytest by scanning the repo for Python files, then iterating file-by-file and function-by-function to add tests where behavior is testable without filesystem IO or network access.
This skill can be slow and may take hours on large repos.
Hard constraints
- No filesystem IO in tests (no reading/writing real files, no
tmp_path). - No network access in tests (no HTTP, sockets, internet APIs).
- Deterministic tests only (no time/randomness unless fully mocked).
- Avoid brittle tests that assert unstable logging/printing unless clearly part of the function contract.
Inputs to request
- Whether to scan the entire repo or exclude known folders (for example generated code,
vendored code, or
old/archives). - Whether there are modules that must never be imported during tests (side effects).
- Any existing pytest config (
pytest.ini,pyproject.toml) and whether tests already exist undertests/.
Workflow
- Confirm pytest baseline
- Prefer pytest for Python 3 repos unless the repo clearly uses something else.
- Check for an existing
tests/folder and any pytest config. - If
tests/does not exist, create it.
- Determine repo root and discovery command
- Define
REPO_ROOTas the current git/workspace root. - Discover Python files using
find(repo-rooted) and iterate in a stable order:find "${REPO_ROOT}" -name "*.py" -type f | sort - Apply reasonable exclusions when needed (but keep using
find), for example:.git/,__pycache__/,.venv/,venv/,build/,dist/,node_modules/.
- Define
- Choose a one-to-one test file mapping
- Create one pytest file per source file to keep mapping straightforward.
- Naming rule (repo-relative path to ASCII-safe filename):
- Source:
pkg/sub/mod.py - Test:
tests/test_pkg__sub__mod.py
- Source:
- If a source file is untestable under constraints, still create the test module
with a single
pytest.skip(..., allow_module_level=True)explaining why.
- Make imports work (create
tests/conftest.pywhen needed)- Prefer importing modules the same way the repo imports them.
- If tests cannot import local modules (no installed package, no package layout),
create
tests/conftest.pyto addREPO_ROOT(and optionallytests/) tosys.path:#!/usr/bin/env python3 """ Pytest config to ensure local imports work without installation. """ from __future__ import annotations # Standard Library import os import sys #============================================ REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) if REPO_ROOT not in sys.path: sys.path.insert(0, REPO_ROOT) TESTS_DIR = os.path.abspath(os.path.dirname(__file__)) if TESTS_DIR not in sys.path: sys.path.insert(0, TESTS_DIR) - Keep
conftest.pyminimal and repo-wide; do not add per-test hacks. - If imports trigger libraries that write caches/config under the user's home
directory (for example matplotlib), set environment variables early in
conftest.pyto redirect them to a temp location (avoid asserting on these side effects in tests; this is only to keep the test environment clean).
- For each Python file: decide whether it is safe to import
- Prefer importable modules over scripts with side effects.
- If import triggers work (CLI execution, network, file reads, subprocess), avoid importing at module import-time and mark the test module skipped with a reason.
- When possible, test by importing specific functions/classes from the module rather than executing the script entrypoint.
- For each function/method: triage testability
- Enumerate functions and methods (top-level
def, and simple class methods). - Skip and document functions that:
- read/write files or depend on the filesystem (
open,pathlib.Path(...).read_*,os.listdir,glob, etc.) - call network/internet (
requests,urllib,http.client,socket, etc.) - spawn processes (
subprocess,os.system) - depend on real time or randomness and cannot be safely mocked
- require complex external services or heavyweight frameworks
- read/write files or depend on the filesystem (
- Enumerate functions and methods (top-level
- Write tests for testable functions (table-driven first)
- Prefer
@pytest.mark.parametrizefor input/output grids. - Cover, at minimum:
- 1 to 3 "core" cases (typical inputs)
- 1 edge case (empty, None, boundary, unusual whitespace, extremes)
- 1 negative case when the function explicitly rejects inputs or raises
- Assertions:
- Use plain
assertfor values/invariants. - Use
pytest.raises(ExpectedError)for exceptions. - Use
match=only when the message is stable and part of the contract.
- Use plain
- Avoid duplicating the full function logic in the test; assert observable results and key branches.
- Prefer
- Keep tests deterministic
- Do not let tests depend on the local machine environment.
- If the module reads environment variables, use
monkeypatchto set them. - If a function depends on
time.time()orrandom.*, monkeypatch those calls so results are stable.
- Run tests incrementally (long-running allowed)
- Prefer targeted runs while generating tests:
/opt/homebrew/opt/python@3.12/bin/python3.12 -m pytest tests/test_pkg__sub__mod.py - Expect this process to be long on large repos; keep a simple progress log of: file -> functions tested -> functions skipped (with reasons).
- Prefer targeted runs while generating tests:
- Record changes
- If files were created or changed, record the change in docs/CHANGELOG.md when the file exists.
Output
- A per-file summary (tested functions, skipped functions, and why).
- New
tests/test_*.pyfiles (one per source file) that match repo style. - A
tests/conftest.pyonly when needed for local imports. - Commands to run a single test module and the full suite with
python3 -m pytest.
Quality bar
- Deterministic, small, and readable tests per source file.
- No filesystem IO or network access in tests.
- No speculation: only write tests for behavior you can justify from the code; if unclear, skip with a precise reason in the test module.
> related_skills --same-repo
> webwork-writer
Create, edit, and lint WeBWorK PG/PGML questions following docs/webwork guidance, HTML whitelist constraints, and renderer-based lint checks. Use for tasks like authoring new PGML problems, adjusting randomization or grading, fixing PGML rendering issues, and running renderer API linting.
> skill-writing-guide
Guide for authoring Agent Skills (SKILL.md). Covers the open standard format, required frontmatter, directory layout, progressive disclosure, description writing, and best practices. Use when creating a new skill, improving an existing skill, or learning how skills work.
> readme-fix
Standardize README.md to match repo conventions. Brief purpose, quick start, and links to docs/. Keep content verifiable, concise, and ASCII. Use when README.md drifted or is missing key pointers.
> read-repo-rules
Read specified repo rule files (AGENTS.md, docs/REPO_STYLE.md, docs/PYTHON_STYLE.md, docs/CHANGELOG.md) and return one-sentence summaries in a strict four-line format, including missing-file handling and no recursive listings. For docs/CHANGELOG.md, summarize only the latest dated entry instead of the full file. Use when a prompt asks for structured summaries of repo instruction files with exact output lines or similar constraints.