---
name: pytest-suite
description: "Generate a pytest module covering happy path, edge cases, and errors for a target function or class, then run it to confirm passing."
allowed-tools: ["Read", "Grep", "Write", "Bash(pytest:*)"]
output: "pytest test module"
runner: "pytest"
---

# Pytest Suite Generator

## Musts

- Read the target function or class and understand its inputs, return values, and raised exceptions before writing any test.
- Cover the happy path, boundary and edge cases, and each documented error path with distinct assertions.
- Use `@pytest.mark.parametrize` for input variations and fixtures for shared setup instead of duplicating bodies.
- Assert observable behavior — return values, side effects, raised exceptions — never private attributes or call internals.
- Run `pytest` on the new module and confirm every test passes before reporting it done.

## Guidelines

- Prefer `pytest.raises(ExceptionType)` over broad try/except for error-path tests.
- Avoid `time.sleep`; if timing matters, use fakes, freezing, or dependency injection rather than real waits.
- Give each test a name that states the scenario, e.g. `test_returns_zero_for_empty_input`.
- Keep one logical behavior per test so a failure names the exact broken case.
- Do not add trivial asserts like `assert result is not None` as a test's only check.

## Output format

```python
import pytest
from mymodule import parse_amount


@pytest.mark.parametrize("raw,expected", [
    ("10.50", 1050),
    ("0", 0),
    ("1000000.00", 100000000),
])
def test_parses_valid_amounts_to_cents(raw, expected):
    assert parse_amount(raw) == expected


def test_rejects_negative_amount():
    with pytest.raises(ValueError):
        parse_amount("-5.00")


def test_rejects_non_numeric_input():
    with pytest.raises(ValueError):
        parse_amount("abc")
```
