Install
openclaw skills install @heroinyan-stack/pytest-generator-proGenerates pytest tests that follow your project’s conventions, covering edge cases, fixtures, mocks, parametrization, and reports coverage gaps.
openclaw skills install @heroinyan-stack/pytest-generator-proFramework-aware pytest test generation that matches your team's conventions. Auto-detects fixtures, mocking patterns, naming conventions, and test structure from existing tests — generates comprehensive tests with edge cases, parametrization, and coverage gaps.
Generic AI test generation produces tests that don't match your project's conventions, miss edge cases, and fail to use existing fixtures. This skill reads your existing test suite, learns your patterns, and generates tests that look like your team wrote them.
Activate when the user:
Scan existing test files to learn:
test_* vs *_test, class-based vs function-basedunittest.mock, pytest-mock (mocker fixture), responses, httpx-mockassert vs pytest.raises vs assertthat@pytest.mark.parametrize@pytest.mark.slow, @pytest.mark.integration).coveragerc, pytest.ini, pyproject.toml [tool.pytest]from app import vs from src.app importOutput: Convention summary (stored for this session)
For each function/class to test:
async def requires pytest-asyncioFor each function, generate:
def test_create_user_creates_user_with_valid_data(db_session):
"""Creating a user with valid data returns a User object."""
user = create_user(email="test@example.com", name="Test User")
assert user.id is not None
assert user.email == "test@example.com"
assert user.name == "Test User"
assert user.created_at is not None
@pytest.mark.parametrize("email,expected_valid", [
("user@example.com", True),
("user.name+tag@example.com", True),
("", False),
(None, False),
("not-an-email", False),
("a" * 500 + "@example.com", False), # Too long
("user@example.com", True),
("用户@例子.com", True), # Unicode
])
def test_validate_email_handles_edge_cases(email, expected_valid):
assert validate_email(email) == expected_valid
def test_create_user_raises_on_duplicate_email(db_session):
"""Creating a user with existing email raises DuplicateEmailError."""
create_user(email="test@example.com", name="First User")
with pytest.raises(DuplicateEmailError) as exc_info:
create_user(email="test@example.com", name="Second User")
assert "already exists" in str(exc_info.value)
def test_send_welcome_email_calls_email_service(mocker):
"""send_welcome_email calls EmailService.send with correct params."""
mock_send = mocker.patch("app.services.email.EmailService.send")
send_welcome_email(user_id=123, email="test@example.com", name="Test")
mock_send.assert_called_once_with(
to="test@example.com",
template="welcome",
context={"name": "Test", "user_id": 123},
)
@pytest.fixture
def sample_user(db_session):
"""Create a test user for tests that need an existing user."""
return create_user(email="fixture@example.com", name="Fixture User")
@pytest.fixture
def auth_client(client, sample_user):
"""API client with authentication headers for sample_user."""
token = generate_token(sample_user.id)
client.headers.update({"Authorization": f"Bearer {token}"})
return client
After generating tests, identify:
Output:
## Coverage Analysis
| Function | Branches | Covered | Gaps |
|----------|----------|---------|------|
| create_user | 8 | 7 | Error path when DB connection fails (integration) |
| validate_email | 12 | 12 | ✅ Fully covered |
| send_welcome_email | 5 | 4 | Retry logic on timeout (needs async mock) |
If new shared fixtures are needed:
# conftest.py additions
import pytest
from app.test_factories import UserFactory, ProductFactory
@pytest.fixture
def db_session():
"""Rollback-only DB session for test isolation."""
session = create_test_session()
yield session
session.rollback()
session.close()
@pytest.fixture
def factory():
"""Access to test data factories."""
return FactoryContainer(UserFactory, ProductFactory)
mocker (pytest-mock) if project uses it, otherwise use unittest.mock@pytest.mark.asynciosrc/app/users.py → tests/app/test_users.py