# Python Pytest Creator Skill

> Generate comprehensive pytest test files for Python using the test-generator-framework Use when this capability is needed.

- Skill: `tomevault-io/python-pytest-creator-skill` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/python-pytest-creator-skill`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/python-pytest-creator-skill/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/python-pytest-creator-skill

---


## What I do

I implement a complete Python pytest test generation workflow by extending the `test-generator-framework`:

1. **Analyze Python Codebase**: Scan Python application to identify functions, classes, and modules
2. **Detect Python Testing Setup**: Identify pytest version and Poetry availability
3. **Generate Python-Specific Scenarios**: Create comprehensive test scenarios covering:
   - Happy paths, edge cases, and error handling
   - Python-specific patterns (decorators, context managers, async functions)
4. **Delegate to Framework**: Use `test-generator-framework` for core test generation workflow
5. **Ensure Executability**: Verify tests run with `poetry run pytest` or `pytest`

## When to use me

Use this workflow when:
- You need to create comprehensive pytest test files for a Python application
- You want to ensure all edge cases and error conditions are covered
- You need tests that integrate with Poetry environments
- You prefer a systematic approach to test generation with user confirmation
- You want to ensure tests run correctly with your project's pytest version

**Framework**: This skill extends `test-generator-framework` for core test generation workflow, adding Python-specific functionality.

## Prerequisites

- Python project with Poetry (`pyproject.toml`) or pip (`requirements.txt`)
- Pytest installed and configured in project
- Python source code to test
- Appropriate file permissions to create test files

Note: Poetry is optional. If Poetry is installed and `pyproject.toml` exists, tests will use `poetry run pytest`. Otherwise, tests will use `pytest` directly.

## Steps

### Step 1: Analyze Python Codebase
- Use glob patterns to find Python files: `**/*.py`
- Exclude test files: `**/test_*.py`, `**/*_test.py`, `**/tests/**/*.py`
- Read each Python file to identify:
   - Functions: `def function_name(parameters):`
   - Classes: `class ClassName:`
   - Methods: `def method_name(self, parameters):`
   - Async functions: `async def async_function():`
   - Decorators: `@decorator_name`
   - Context managers: `with context_manager():`
- Identify import statements to understand dependencies

### Step 2: Detect Python Testing Setup
- Check for `pyproject.toml` or `requirements.txt`
- Determine pytest version and plugins
- Check for Poetry installation: `poetry --version`

### Step 3: Generate Python-Specific Test Scenarios

#### Function Scenarios (Python-specific)
- **Happy Path**: Normal inputs with expected outputs
- **Edge Cases**: Empty strings, empty lists, `None`, `0`, `-1`
- **Error Cases**: Invalid types, out of range values, missing parameters
- **Python Features**: Decorators, type hints, default arguments, *args/**kwargs

#### Class Scenarios
- **Initialization**: `__init__` with valid/invalid parameters
- **Method Behavior**: Public/private method testing
- **Special Methods**: `__str__`, `__repr__`, `__eq__`, `__hash__`
- **Class Methods**: `@classmethod`, `@staticmethod`
- **Property**: Properties defined with `@property`
- **Context Managers**: `__enter__` and `__exit__` methods

#### Async Function Scenarios
- **Awaitable Results**: Normal async execution
- **Concurrency**: Multiple async calls with asyncio.gather()
- **Error Handling**: Async exceptions with pytest.raises()
- **Timeout**: Tests that should timeout

### Step 4: Delegate to Test Generator Framework

**Note**: Core test generation workflow is provided by `test-generator-framework`. This skill focuses only on Python-specific aspects.

Refer to `test-generator-framework` for:
- Generic test file creation structure
- Framework detection and command determination
- User confirmation workflow
- Executability verification

Python-specific test file templates below extend the framework structure.

### Step 5: Create Test Files (Python-specific)

```python
"""
Test suite for <module_name>.py
Generated by python-pytest-creator skill
"""

import pytest
from <module_path> import <function_name>, <ClassName>

@pytest.fixture
def sample_instance():
    """Create a sample instance for testing"""
    return ClassName(param1, param2)

def test_function_name_happy_path(sample_instance):
    """Test that function_name works with valid inputs"""
    result = function_name(valid_input)
    assert result == expected_output

def test_function_name_edge_case_empty():
    """Test that function_name handles empty input"""
    result = function_name("")
    assert result is None

def test_function_name_error_invalid_type():
    """Test that function_name raises ValueError for invalid type"""
    with pytest.raises(ValueError):
        function_name(invalid_input)

@pytest.mark.parametrize("input,expected", [
    (1, "one"),
    (2, "two"),
])
def test_function_name_parametrized(input, expected):
    """Test function_name with multiple inputs"""
    result = function_name(input)
    assert result == expected

class TestClassName:
    """Test suite for ClassName"""
    
    def test_initialization(self):
        """Test that ClassName initializes correctly"""
        instance = ClassName(param1, param2)
        assert instance.attribute == expected_value
    
    def test_method_behavior(self, sample_instance):
        """Test that ClassName.method_name works correctly"""
        result = sample_instance.method_name(param)
        assert result == expected_result

@pytest.mark.asyncio
async def test_async_function_happy_path():
    """Test successful async execution"""
    result = await async_function(valid_input)
    assert result["status"] == "success"
```

### Step 6: Verify Executability

Refer to `test-generator-framework` for core executability verification.

### Step 7: Display Summary

```
✅ Python test files created successfully!

**Test Files Created:**
- tests/test_<module_name>.py (<number> tests)

**Total Tests Generated:** <number>
**Test Framework:** Pytest

**Python-Specific Categories:**
- Decorator tests: <number>
- Context manager tests: <number>
- Special method tests: <number>
- Async function tests: <number>
```

**To run tests:**
```bash
# If Poetry is installed:
poetry run pytest tests/test_<module_name>.py -v
poetry run pytest --cov=<module_name> tests/

# Otherwise:
pytest tests/test_<module_name>.py -v
pytest --cov=<module_name> tests/
```

## Python-Specific Scenario Generation

Python-specific patterns to focus on:

### Decorator Testing
- **Decorator Execution**: Decorator modifies function behavior correctly
- **Decorator Chaining**: Multiple decorators apply correctly
- **Decorator Arguments**: Decorator with parameters works
- **Class Decorators**: Decorator classes properly

### Context Manager Testing
- **`__enter__`**: Returns context manager correctly
- **`__exit__`**: Cleans up resources properly
- **Exception Handling**: Exceptions in context are handled
- **Nested Context**: Multiple context managers work together

### Special Method Testing
- **`__str__`**: String representation is correct
- **`__repr__`**: Developer representation is correct
- **`__eq__`**: Equality comparison works
- **`__hash__`**: Hash allows use in sets/dicts
- **`__len__`**: Length function returns correct value
- **`__getitem__`**: Item access works
- **`__setitem__`**: Item assignment works

### Property Testing
- **Getter**: Property returns correct value
- **Setter**: Property sets value correctly
- **Deleter**: Property deletion works
- **Cached Properties**: Cached behavior is correct

## Best Practices

Refer to `test-generator-framework` for general best practices.

Python-specific best practices:
- **Pytest Features**: Use fixtures, parametrization, marks
- **Async Testing**: Use pytest-asyncio for async functions
- **Type Hints**: Include type hints for better test coverage
- **Mocking**: Use pytest-mock or unittest.mock appropriately
- **Integration Tests**: Always include at least one integration test with real database sessions — mock-only tests mask session boundary bugs

## Common Issues

Refer to `test-generator-framework` for general issues.

Python-specific issues:

### Poetry Not Installed
**Issue**: `poetry run pytest` command not found

**Solution**: Use `pytest` directly instead:
```bash
pytest tests/
```

### pytest-asyncio Not Installed
**Issue**: Async tests fail or don't run

**Solution**: Install pytest-asyncio:
```bash
poetry add --group dev pytest-asyncio
# or
pip install pytest-asyncio
```

### Module Not Found
**Issue**: Import errors for modules to test

**Solution**: Add source to PYTHONPATH:
```bash
export PYTHONPATH="${PYTHONPATH}:$(pwd)"
```

### MagicMock Truthy Headers
**Issue**: `MagicMock` for `response.headers` creates truthy auto-created mocks, causing false positives in header-checking code.

```python
# WRONG — MagicMock auto-creates `response.headers.get()` as truthy
mock_response = MagicMock()
mock_response.headers.get.return_value = "Bearer test-token"
assert mock_response.headers.get("Authorization") == "Bearer test-token"  # passes
# But also: mock_response.headers.get("X-Missing") returns a MagicMock (truthy!)

# CORRECT — use a real dict for headers
mock_response = MagicMock()
mock_response.headers = {"Authorization": "Bearer test-token"}  # real dict
assert mock_response.headers.get("Authorization") == "Bearer test-token"
assert mock_response.headers.get("X-Missing") is None  # correctly returns None
```

### Detached ORM Across Sessions (Mocking Pitfall)
**Issue**: Mock-only tests mask session boundary bugs. When an ORM object is fetched in one session and mutated in another, mocks won't catch the detached state.

```python
# WRONG — mock hides the bug: test passes but production fails
mock_session = MagicMock()
mock_session.get.return_value = User(id="u1", name="old")
repo = UserRepository(mock_session)
repo.update_name("u1", "new")
mock_session.commit.assert_called_once()  # passes, but nothing actually flushed

# CORRECT — include at least one integration test with real sessions
@pytest.mark.asyncio
async def test_update_user_real_session(test_db_session):
    user = User(id="u1", name="old")
    test_db_session.add(user)
    await test_db_session.commit()

    # fetch and update in the SAME session
    fetched = await test_db_session.get(User, "u1")
    fetched.name = "new"
    await test_db_session.commit()

    result = await test_db_session.get(User, "u1")
    assert result.name == "new"
```

## Troubleshooting Checklist

Refer to `test-generator-framework` for general checklist.

Python-specific additions:
Before generating tests:
- [ ] Python files exist and are syntactically correct
- [ ] `pyproject.toml` or `requirements.txt` exists
- [ ] Pytest is installed
- [ ] Poetry is installed (if using Poetry)

## Related Commands

```bash
# Poetry commands
poetry run pytest -v
poetry run pytest --cov=<module> tests/
poetry install --group dev pytest-asyncio

# Direct pytest commands
pytest -v
pytest tests/test_module.py -v
pytest --cov=<module> tests/
pytest -k "test_name"

# Python commands
python -m pytest
export PYTHONPATH="${PYTHONPATH}:$(pwd)"
```

---
> Source: [darellchua2/opencode-config-template](https://github.com/darellchua2/opencode-config-template) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-06-16 -->

