Metadata-Version: 2.4
Name: pytest-forger
Version: 0.2.0
Summary: Automatic test scaffolding and mock generation for Python
Author-email: Daryll Lorenzo Alfonso <daryllla77@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/DaryllLorenzo/pytest-forger
Project-URL: Repository, https://github.com/DaryllLorenzo/pytest-forger
Project-URL: Issues, https://github.com/DaryllLorenzo/pytest-forger/issues
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Developers
Classifier: Environment :: Console
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typer>=0.9.0
Requires-Dist: pytest>=7.4.0
Provides-Extra: dev
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

# pytest-forger

![](https://raw.githubusercontent.com/DaryllLorenzo/pytest-forger/main/images/pytest-forger.jpg)

> Version: 0.2.0
> Status: **Fully Functional**

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)

---

## What is pytest-forger?

pytest-forger is a Python tool designed to forge PyTest-ready tests from existing Python source code.

The goal of the project is to reduce the friction and boilerplate involved in writing tests by automatically generating test scaffolding and mocks based on the structure of your code, while keeping the developer fully in control of the final behavior.

**Save up to 60% of test writing time** by automating the mechanical parts while you focus on the actual test logic.

---

## Installation

```bash
pip install pytest-forger
```

For development:

```bash
pip install -e .
```

---

## Quick Start

```bash
# Generate tests for a Python file
ptf forge your_module.py

# Generate tests with verbose output
ptf forge your_module.py --verbose

# Generate tests for a specific function
ptf forge your_module.py --function my_function

# Specify output directory
ptf forge your_module.py --output tests/unit

# Overwrite existing test files
ptf forge your_module.py --overwrite
```

### Example

Given a source file `services.py`:

```python
from datetime import datetime
from typing import Optional, List


def add_numbers(x: int, y: int) -> int:
    """Add two numbers together."""
    return x + y


class UserService:
    def __init__(self, repository=None):
        self.repository = repository

    def get_user(self, user_id: int) -> Optional[dict]:
        """Get a user by ID."""
        if self.repository:
            return self.repository.find(user_id)
        return None

    def process_items(self, items: List[str]) -> int:
        """Process a list of items and return count."""
        return len(items)
```

Running `ptf forge services.py` generates `tests/test_services.py`:

```python
import pytest
from services import *
from unittest.mock import MagicMock, patch

# Tests generated by pytest-forger

def test_add_numbers():
    """Test for add_numbers: Add two numbers together."""
    # Arrange
    x = 0
    y = 0
    # Act
    # result = services.add_numbers(x, y)
    # Assert
    assert True  # TODO: Replace with actual assertion

def test_UserService_get_user():
    """Test for get_user: Get a user by ID."""
    # Arrange
    instance = services.UserService()
    user_id = 0
    # Act
    # result = instance.get_user(user_id)
    # Assert
    assert True  # TODO: Replace with actual assertion

def test_UserService_process_items():
    """Test for process_items: Process a list of items and return count."""
    # Arrange
    instance = services.UserService()
    items = List[str]()
    # Act
    # result = instance.process_items(items)
    # Assert
    assert True  # TODO: Replace with actual assertion
```

---

## CLI Commands

### `ptf version`

Display version information about pytest-forger.

```bash
$ ptf version
pytest-forger v0.2.0
https://github.com/daryll/pytest-forger
MIT License (c) 2025 Daryll Lorenzo Alfonso
```

### `ptf forge <source_file>`

Forge PyTest tests from an existing Python source file.

| Option | Short | Description |
|--------|-------|-------------|
| `--function` | `-f` | Generate tests only for a specific function |
| `--output` | `-o` | Directory where generated tests will be saved (default: `tests/`) |
| `--overwrite` | `-w` | Overwrite existing test files if they already exist |
| `--verbose` | `-v` | Show detailed information about the test generation process |

---

## Features

### ✅ Implemented (v0.2.0)

| Feature | Description |
|---------|-------------|
| **Static code analysis** | Full AST-based parsing of Python source code |
| **Function extraction** | Detects global functions and class methods |
| **Async function support** | Recognizes `async def` functions with pytest-asyncio hints |
| **Type hint awareness** | Generates type-appropriate placeholders (str, int, List, etc.) |
| **External dependency detection** | Identifies third-party imports (non-stdlib) |
| **Mock scaffolding** | Generates mock setup comments for external dependencies |
| **Flexible CLI** | Filter by function, customize output, verbose mode |
| **Comprehensive test suite** | 28+ tests covering all core functionality |
| **Private method exclusion** | Automatically excludes `__` and `_` methods |
| **Docstring extraction** | Includes function docstrings in generated tests |

### 🔮 Planned (Future Versions)

- Call graph analysis for function dependencies
- Automatic mock patching with `@patch` decorators
- Fixture generation for common patterns (database, HTTP, etc.)
- Configuration via `pyproject.toml`
- Support for parametrized test generation
- Integration with popular frameworks (FastAPI, Django, Flask)

---

## Design Principles

pytest-forger is built around a few core principles:

- **Automation without magic**
  Generated tests should be explicit, readable, and predictable.

- **Structure over semantics**
  The tool understands code structure, not business intent.

- **Mocks at the boundaries**
  External dependencies are mocked; internal logic remains real.

- **Developer ownership**
  Generated tests are meant to be edited, extended, and owned by the developer.

---

## Use Cases

pytest-forger is especially useful for:

- **Service layers** calling repositories or other services
- **Legacy codebases** with little or no test coverage
- **Quickly bootstrapping tests** for refactoring
- **Teams** that want consistency in test structure
- **Developers** who want to avoid repetitive PyTest boilerplate

---

## What pytest-forger Is *Not*

To set clear expectations, pytest-forger is not:

- ❌ A replacement for test design
- ❌ A business-logic inference engine
- ❌ A fully autonomous test generator
- ❌ A PyTest plugin (at least initially)

pytest-forger generates **starting points**, not perfect tests.

---

## Development

### Running Tests

```bash
# Run all tests
pytest tests/ -v

# Run with coverage
pytest tests/ --cov=pytest_forger
```

### Project Structure

```
pytest-forger/
├── src/
│   └── pytest_forger/
│       ├── __init__.py
│       ├── __version__.py
│       ├── cli.py          # CLI entry point (Typer)
│       └── core.py         # Code analysis & generation
├── tests/
│   ├── fixtures/           # Sample files for testing
│   ├── test_cli.py         # CLI tests
│   └── test_core.py        # Core functionality tests
├── example_app/            # Practical example application
│   ├── user_service.py     # Sample service with dependencies
│   └── tests/              # Generated and completed tests
├── pyproject.toml
└── README.md
```

---

## Changelog

### [0.2.0] - Current

#### Added
- **Full AST-based code analysis** - Complete implementation of Python source parsing
- **Class method extraction** - Methods are extracted with proper class context
- **Async function detection** - Recognizes `async def` and adds pytest-asyncio hints
- **Type hint extraction** - Extracts and uses type hints for smarter placeholders
- **External dependency detection** - Identifies non-stdlib imports automatically
- **Mock generation scaffolding** - Generates mock setup for external dependencies
- **Comprehensive test suite** - 28 tests covering CLI and core functionality
- **Verbose mode enhancements** - Shows detected external dependencies count
- **Docstring extraction** - Includes function docstrings in generated test descriptions
- **Example application** - Practical example showing real-world usage

#### Fixed
- Class methods now properly extracted with class name context
- Private/protected methods (starting with `_`) are correctly excluded
- Removed placeholder comments from generated imports
- Args now return structured data with type hints instead of plain strings

#### Changed
- `generate_test_content()` now accepts `external_deps` parameter for mock generation
- CLI passes external dependencies from analyzer to content generator
- Test output includes mock setup section for external dependencies

---

### [0.1.2] - 2025-12-26

#### Added
- Initial CLI implementation using Typer framework
- `ptf version` command to display project version and information
- `ptf forge <source_file.py>` command interface for test generation
- Complete argument parsing system with options:
  - `--function` / `-f` - Target specific function for test generation
  - `--output` / `-o` - Custom output directory for generated tests
  - `--overwrite` / `-w` - Overwrite existing test files
  - `--verbose` / `-v` - Enable detailed output for debugging
- Project structure with `src/` layout
- PyPI-ready packaging configuration in `pyproject.toml`
- Dependencies: `pytest>=7.4.0`, `typer>=0.9.0`

#### Notes
- `ptf forge` provided the interface without actual code analysis
- This release established the foundation for test generation

---

## Philosophy

pytest-forger exists to answer one simple question:

> *"How much of testing can we automate without lying to ourselves?"*

The answer is: **a lot of the boring parts.**

---

### Advantages Summary

#### What You Save:
- **No manual imports** - pytest, unittest.mock, your module
- **No structure setup** - Arrange-Act-Assert pattern pre-built
- **No fixture boilerplate** - Class instantiation ready
- **No argument guessing** - Type hints provide placeholders
- **No dependency hunting** - External imports detected automatically

#### What You Focus On:
- **Test logic** - Actual assertions and behavior
- **Edge cases** - Boundary conditions and error handling
- **Mock configuration** - Return values and side effects
- **Business rules** - Domain-specific validation

---

## License

MIT License

---

## Disclaimer

pytest-forger is an early-stage project under active design.
Breaking changes are expected in early versions.

---

*Forge tests, not excuses.*
