Skip to main content

Django Test Enforcer 🛡️

PyPI version Python Versions Django Versions License Tests Coverage

Comprehensive Django testing enforcement library that ensures 100% test coverage across views, UI elements, and functions.

Django Test Enforcer automatically scans your Django project and enforces test coverage for:

  • ✅ Backend Views (function-based, class-based, generic views)
  • ✅ UI Elements (buttons, forms, links, inputs)
  • ✅ Functions & Utilities (business logic, helpers)
  • ✅ API Endpoints (Django REST Framework)

🚀 Features

  • Automatic Discovery: Scans your entire Django project to find all testable components
  • Coverage Enforcement: Fails your CI/CD build if coverage requirements aren't met
  • Test Generation: Auto-generates test stubs for missing coverage
  • Pytest Integration: Seamless pytest plugin with custom markers and hooks
  • Rich Reports: Beautiful console and HTML reports showing coverage gaps
  • Django Commands: Management commands for quick checks and test generation
  • Configurable Rules: Fine-grained control over coverage requirements
  • UI Testing Support: Playwright and Selenium integration for UI tests

📦 Installation

# Basic installation
pip install django-test-enforcer

# With UI testing support (Playwright)
pip install django-test-enforcer[ui]

# With API testing support (DRF)
pip install django-test-enforcer[api]

# Full installation
pip install django-test-enforcer[all]

⚡ Quick Start

1. Add to Django Settings

INSTALLED_APPS = [
    ...
    'django_test_enforcer',
]

2. Configure pytest (optional)

# pyproject.toml
[tool.django_test_enforcer]
enforcement_level = "strict"  # "strict", "warning", or "off"
min_view_coverage = 100
min_ui_coverage = 90
min_function_coverage = 80

3. Run Tests with Enforcement

# Check coverage without failing
pytest --check-coverage

# Enforce coverage (fails build if not met)
pytest --enforce-coverage

# Generate missing test stubs
pytest --generate-tests

# Show detailed coverage report
pytest --coverage-report

📊 Django Management Commands

# Check current test coverage
python manage.py check_coverage

# Check specific categories
python manage.py check_coverage --views
python manage.py check_coverage --ui
python manage.py check_coverage --functions

# Generate missing tests
python manage.py generate_tests
python manage.py generate_tests --output tests/auto_generated/

# Enforce tests (for CI/CD)
python manage.py enforce_tests --fail-on-missing

🎯 Example Output

════════════════════════════════════════════════════════════════
Django Test Enforcer Report
════════════════════════════════════════════════════════════════

View Coverage:        85% (34/40 views tested) ⚠️
UI Coverage:          92% (115/125 elements tested) ✅
Function Coverage:    78% (156/200 functions tested) ❌
API Coverage:         100% (20/20 endpoints tested) ✅

════════════════════════════════════════════════════════════════
Missing Tests (20 items):
════════════════════════════════════════════════════════════════

VIEWS (6):
  ✗ myapp.views.send_notification
  ✗ myapp.views.publish_event
  ✗ myapp.views.dashboard

UI ELEMENTS (10):
  ✗ Button: "Submit" (templates/form.html:45)
  ✗ Form: notification_form (templates/send.html:23)
  ✗ Link: /dashboard/ (templates/home.html:67)

FUNCTIONS (4):
  ✗ utils.helpers.calculate_stats
  ✗ services.notification.process_queue

════════════════════════════════════════════════════════════════
Generate missing tests with:
  pytest --generate-tests
  or
  python manage.py generate_tests
════════════════════════════════════════════════════════════════

📖 Configuration

Full Configuration Example

[tool.django_test_enforcer]
# Enforcement level: "strict" (fail build), "warning" (show warnings), "off"
enforcement_level = "strict"

# Minimum coverage percentages
min_view_coverage = 100
min_ui_coverage = 90
min_function_coverage = 80
min_api_coverage = 100

# What to scan
scan_views = true
scan_templates = true
scan_functions = true
scan_apis = true

# Excluded paths (glob patterns)
exclude_paths = [
    "*/migrations/*",
    "*/tests/*",
    "*/admin.py",
    "*/apps.py",
]

# Test generation
auto_generate_stubs = true
test_output_dir = "tests/auto_generated"
ui_framework = "playwright"  # or "selenium"

# Custom rules
[tool.django_test_enforcer.rules]
require_authenticated_tests = true
require_permission_tests = true
require_form_validation_tests = true
require_error_handling_tests = true
require_api_pagination_tests = true

🔌 CI/CD Integration

GitHub Actions

name: Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      
      - name: Install dependencies
        run: |
          pip install -r requirements.txt
          pip install django-test-enforcer[all]
      
      - name: Run tests with enforcement
        run: pytest --enforce-coverage --cov

Jenkins

stage('Test Coverage Enforcement') {
    steps {
        sh 'pytest --enforce-coverage --junitxml=results.xml'
    }
    post {
        always {
            junit 'results.xml'
        }
        failure {
            echo 'Test coverage requirements not met!'
        }
    }
}

🎨 Generated Test Examples

View Test (Auto-generated)

def test_send_notification_view_get(client, authenticated_user):
    """Test send_notification view GET request"""
    client.force_login(authenticated_user)
    response = client.get('/messaging/send/')
    assert response.status_code == 200
    assert 'form' in response.context

def test_send_notification_view_post(client, authenticated_user):
    """Test send_notification view POST request"""
    client.force_login(authenticated_user)
    data = {
        'title': 'Test Notification',
        'message': 'Test message',
        'priority': 'high'
    }
    response = client.post('/messaging/send/', data)
    assert response.status_code == 302  # Redirect after success

UI Test (Auto-generated)

def test_submit_button_notification_form(page, authenticated_page):
    """Test Submit button in notification form"""
    page.goto('/messaging/send/')
    page.fill('input[name="title"]', 'Test')
    page.fill('textarea[name="message"]', 'Test message')
    page.click('button[type="submit"]')
    page.wait_for_url('**/dashboard/')
    assert 'success' in page.content().lower()

📚 Documentation

Full documentation available at django-test-enforcer.readthedocs.io

🤝 Contributing

Contributions are welcome! Please read our Contributing Guide for details.

# Clone repository
git clone https://github.com/arpansahu/django-test-enforcer.git
cd django-test-enforcer

# Create virtual environment
python -m venv venv
source venv/bin/activate

# Install in development mode
pip install -e ".[dev,all]"

# Run tests
pytest

# Run linters
black .
isort .
flake8
mypy django_test_enforcer

📄 License

MIT License - see LICENSE file for details

🌟 Star History

Star History Chart

💬 Support

🙏 Acknowledgments

Built with ❤️ by Arpan Sahu

Inspired by the Django and pytest communities.

Metadata

Release files for django-test-enforcer 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-test-enforcer 0.1.0
File Size Uploaded Provenance
django_test_enforcer-0.1.0.tar.gz 36.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for django-test-enforcer 0.1.0
File Interpreter ABI Platform
django_test_enforcer-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 75.1 kB

Release files / django_test_enforcer-0.1.0.tar.gz

Download URL django_test_enforcer-0.1.0.tar.gz
Size 36.5 kB
Tags Source
SHA-256 checksum
How to use checksums
bd7dae32aac06a761b83bf73632dde6f37eeafbe9cceb816d5f3dc6d3b519271
BLAKE2b-256 checksum
How to use checksums
a5db453be188a899cd499f4a34d3ff383fd72db4bc45077cb2ea1b6e319cfa14
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release files / django_test_enforcer-0.1.0-py3-none-any.whl

Download URL django_test_enforcer-0.1.0-py3-none-any.whl
Size 38.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
573da42975893391d67671439d5bae9f96bcd63dceba18ac9c9416d57ec07ca0
BLAKE2b-256 checksum
How to use checksums
303b92e927b480ede9a43be8dacd0e7288ff26154ac801923a785332f039cae0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Security for django-test-enforcer 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page