A lightweight Python unit testing framework with decorator-based test collection and execution.
Project description
PyForge Testing Framework
A lightweight Python testing framework with decorator-based test collection and automatic discovery—designed for personal projects and learning.
Note: PyForge is designed for personal projects, learning, and small-scale testing. It is not a substitute for production frameworks like pytest.
Features
- 🎯 Simple Decorators — Mark tests with
@test, automatic collection - 🚀 Zero Configuration — Works out of the box
- 📦 Zero Dependencies — Pure Python, nothing to install but PyForge itself
- 🔍 Auto-Discovery — Finds and loads all
test*.pyfiles automatically - ⚡ Fast Execution — Minimal overhead, quick feedback
- 🏷️ Test Markers — Organize tests by priority (
integration,slow) - 📊 Parameterized Tests — Run one test with multiple inputs
- ⊘ Skip Tests — Conditionally skip tests with clear reasons
- ✅ Full Type Hints — PEP 484 type annotations throughout
- 🎨 Clean Output — Color-coded results with minimal internal noise
Installation
pip install pyforge-test
Or from GitHub:
pip install git+https://github.com/ertanturk/pyforge-test.git
Quick Start
1. Create Test File
mkdir -p tests && touch tests/__init__.py
Create tests/test_example.py:
from pyforge_test import test
@test
def test_addition() -> None:
"""Test basic arithmetic."""
assert 2 + 2 == 4
@test
def test_strings() -> None:
"""Test string manipulation."""
assert "hello".upper() == "HELLO"
2. Run Tests
pyforge
Expected output:
Discovering test modules in '/path/to/tests'...
Loaded: test_example.py
Loaded 1 test module(s).
Executing 2 test(s).
PyForge Test Results
------------------------------------------------------------------------
test_example.py
PASSED test_addition (Line 4)
PASSED test_strings (Line 9)
------------------------------------------------------------------------
Summary: PASSED: 2/2 FAILED: 0/2 SKIPPED: 0/2 ERRORS: 0/2
Took 5 ms to execute all tests
------------------------------------------------------------------------
CLI Options
pyforge # Run all tests
pyforge -q # Quiet: only failures
pyforge -v # Verbose: full tracebacks
pyforge --fail-fast # Stop on first failure
pyforge -k api # Filter by test name
pyforge test_api.py # Run specific file
Test Features
Basic Tests
from pyforge_test import test
@test
def test_example() -> None:
"""Test function requirements:
- Starts with 'test_'
- No parameters
- Return type -> None
- Uses @test decorator
"""
assert True
Parameterized Tests
Run the same test with multiple inputs:
from pyforge_test import test_parameterized
@test_parameterized([
(2, 3, 5),
(10, 5, 15),
(100, 200, 300),
])
def test_addition(a: int, b: int, expected: int) -> None:
"""Generates: test_addition_0, test_addition_1, test_addition_2"""
assert a + b == expected
Test Markers
Execution priority: Unmarked (0) → Integration (1) → Slow (2)
from pyforge_test import test, test_marker
# Fast unit test (runs first)
@test
def test_fast() -> None:
assert 2 + 2 == 4
# Integration test (requires external resources)
@test_marker("integration")
@test
def test_database() -> None:
db.connect()
assert db.is_connected()
# Slow test (performance-intensive)
@test_marker("slow")
@test
def test_large_dataset() -> None:
result = process_records(1_000_000)
assert len(result) == 1_000_000
Important:
@test_markermust come before@test
Skip Tests
import sys
from pyforge_test import test, test_skip, test_skipif
@test_skip(reason="Not implemented yet")
def test_future() -> None:
"""Always skipped."""
pass
@test_skipif(sys.platform == "win32", reason="Unix only")
def test_unix() -> None:
"""Skipped on Windows."""
pass
Project Structure
my-project/
├── src/
│ ├── main.py
│ └── utils.py
├── tests/
│ ├── __init__.py # Required (can be empty)
│ ├── test_main.py # Auto-discovered
│ └── test_utils.py # Auto-discovered
├── README.md
└── pyproject.toml
Code Quality
PyForge is fully type-checked and linted:
- Ruff: All checks passing ✅
- Pylint: 9.89/10 score ✅
- Pyright: Strict type checking ✅
- Type Hints: Full PEP 484 compliance ✅
Documentation
- Complete Guide: docs/Documentation.md
- Development Guide: .github/instructions/pyforge.instructions.md
- Examples: tests/test_test.py
- Roadmap: docs/FUTURE_UPDATES.md
Development
Code standards:
- PEP 484 type hints on all functions
- Google-style docstrings
- Exception chaining:
raise ... from e - No bare
exceptstatements
License
MIT — See LICENSE
Contributing
Contributions welcome! Open an issue or PR on GitHub.
Status: Alpha (v0.2.0) | Python: 3.12+ | Type Safe: Yes | Dependencies: 0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyforge_test-0.2.0.tar.gz.
File metadata
- Download URL: pyforge_test-0.2.0.tar.gz
- Upload date:
- Size: 24.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eaed0b11d42aa91e6d7b3b42cdc04accc62db08268875517af2d5e0585245920
|
|
| MD5 |
3e0a8469fe1fa99602114c9dab8c9b58
|
|
| BLAKE2b-256 |
ebeae0f5ae1765065fa8a23e2f4aadf9a22658d3ff98308c77e94209908dab71
|
File details
Details for the file pyforge_test-0.2.0-py3-none-any.whl.
File metadata
- Download URL: pyforge_test-0.2.0-py3-none-any.whl
- Upload date:
- Size: 18.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f89206ac3ee1be49099df6b1332f22117765554a6deb661d8369fce2afedebc
|
|
| MD5 |
ca2239f09ca32ff3ed5d15ed306589d0
|
|
| BLAKE2b-256 |
1a243e2937332a7a3aa12584da83818a10e26c22678689449de26943ffd93fab
|