Green is a clean, colorful, fast python test runner.
—
Green provides native Django test runner integration, allowing it to be used as the primary test runner in Django projects with full Django-specific features and configuration options.
Django test runner that integrates Green's enhanced output and parallel execution with Django's test framework.
class DjangoRunner(DiscoverRunner):
"""
Django test runner integration for Green.
Extends Django's DiscoverRunner to provide Green's enhanced features
including colorful output, parallel execution, and improved reporting
while maintaining full compatibility with Django's test framework.
"""
def __init__(self, verbose=-1, **kwargs):
"""
Initialize Django test runner with Green integration.
Args:
verbose (int): Verbosity level (-1 uses Green's default behavior)
**kwargs: Additional Django test runner arguments including:
- pattern: Test file pattern
- top_level: Top-level directory for test discovery
- keepdb: Keep test database between runs
- reverse: Reverse test execution order
- debug_mode: Enable Django debug mode during tests
- parallel: Number of parallel processes (Django 1.9+)
Example:
# In Django settings.py
TEST_RUNNER = 'green.djangorunner.DjangoRunner'
# Or programmatically
from green.djangorunner import DjangoRunner
runner = DjangoRunner(verbose=2, keepdb=True)
"""
@classmethod
def add_arguments(cls, parser):
"""
Add Green-specific command-line arguments to Django's test command.
Args:
parser: Django's argument parser
Adds Green-specific options like --green-verbosity to Django's
./manage.py test command while preserving all Django test options.
Example:
# Command line usage
./manage.py test --green-verbosity 3 --keepdb myapp.tests
"""
def run_tests(self, test_labels, extra_tests=None, **kwargs):
"""
Run Django tests using Green's enhanced test runner.
Args:
test_labels (list): List of test labels to run (app names, module names, etc.)
extra_tests (list, optional): Additional test suites to run
**kwargs: Additional test execution arguments
Returns:
int: Number of failed tests (0 if all tests passed)
Example:
runner = DjangoRunner()
failures = runner.run_tests(['myapp.tests', 'anotherapp.tests'])
if failures == 0:
print("All Django tests passed!")
"""settings.py:
# Use Green as Django's test runner
TEST_RUNNER = 'green.djangorunner.DjangoRunner'
# Optional: Configure Green-specific settings
GREEN_VERBOSITY = 2
GREEN_PROCESSES = 4# Basic Django test running with Green
./manage.py test
# Run specific app tests
./manage.py test myapp
# Run specific test modules
./manage.py test myapp.tests.test_models
# Run specific test classes
./manage.py test myapp.tests.test_models.UserModelTest
# Run specific test methods
./manage.py test myapp.tests.test_models.UserModelTest.test_user_creation# Use Green's verbosity levels
./manage.py test --green-verbosity 3
# Combine with Django options
./manage.py test --green-verbosity 2 --keepdb --parallel 4 myapp
# Enable Green's debug output
./manage.py test --green-verbosity 2 --debugGreen's Django integration properly handles Django's test database lifecycle:
# Django settings for test database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'myproject_test',
'USER': 'testuser',
'PASSWORD': 'testpass',
'HOST': 'localhost',
'PORT': '5432',
}
}
# Green respects Django's test database settings
TEST_RUNNER = 'green.djangorunner.DjangoRunner'# In Django app's tests.py or test modules
from django.test import TestCase
from django.contrib.auth.models import User
class UserTestCase(TestCase):
"""Test case that benefits from Green's enhanced output."""
def setUp(self):
"""Set up test data."""
self.user = User.objects.create_user(
username='testuser',
password='testpass123'
)
def test_user_creation(self):
"""Test user creation - Green will show this docstring at high verbosity."""
self.assertTrue(isinstance(self.user, User))
self.assertEqual(self.user.username, 'testuser')
def test_user_authentication(self):
"""Test user authentication."""
from django.contrib.auth import authenticate
user = authenticate(username='testuser', password='testpass123')
self.assertIsNotNone(user)
self.assertEqual(user.username, 'testuser')settings.py with comprehensive Green configuration:
# Django test runner
TEST_RUNNER = 'green.djangorunner.DjangoRunner'
# Green configuration (optional)
GREEN_VERBOSITY = 2 # Verbose output showing test names
GREEN_PROCESSES = 0 # Auto-detect optimal process count
GREEN_RUN_COVERAGE = True # Enable coverage reporting
GREEN_COVERAGE_CONFIG_FILE = '.coveragerc' # Coverage configuration
GREEN_OMIT_PATTERNS = [ # Coverage omit patterns
'*/migrations/*',
'*/venv/*',
'*/node_modules/*',
'manage.py',
'*/settings/*'
]
# Django-specific test settings
TEST_DATABASE_NAME = 'test_myproject'
TEST_DATABASE_CHARSET = 'utf8'Development settings (settings/dev.py):
from .base import *
TEST_RUNNER = 'green.djangorunner.DjangoRunner'
GREEN_VERBOSITY = 3 # Maximum verbosity for development
GREEN_PROCESSES = 2 # Don't overwhelm development machine
GREEN_DEBUG = True # Enable Green debug outputCI/CD settings (settings/ci.py):
from .base import *
TEST_RUNNER = 'green.djangorunner.DjangoRunner'
GREEN_VERBOSITY = 1 # Minimal output for CI logs
GREEN_PROCESSES = 0 # Auto-detect CI environment capabilities
GREEN_RUN_COVERAGE = True
GREEN_JUNIT_REPORT = 'test-results.xml' # JUnit XML for CI integrationfrom green.djangorunner import DjangoRunner
from green.config import get_default_args
class CustomDjangoRunner(DjangoRunner):
"""Custom Django runner with additional Green configuration."""
def __init__(self, **kwargs):
super().__init__(**kwargs)
# Apply custom Green configuration
from django.conf import settings
if hasattr(settings, 'GREEN_CUSTOM_CONFIG'):
self.green_args = get_default_args()
for key, value in settings.GREEN_CUSTOM_CONFIG.items():
setattr(self.green_args, key, value)
def run_tests(self, test_labels, extra_tests=None, **kwargs):
"""Run tests with custom configuration."""
# Custom pre-test setup
self.setup_custom_test_environment()
# Run tests with Green
result = super().run_tests(test_labels, extra_tests, **kwargs)
# Custom post-test cleanup
self.cleanup_custom_test_environment()
return result
def setup_custom_test_environment(self):
"""Custom test environment setup."""
# Initialize test services, mock external APIs, etc.
pass
def cleanup_custom_test_environment(self):
"""Custom test environment cleanup."""
# Clean up test services, reset mocks, etc.
pass
# Usage in settings.py
TEST_RUNNER = 'myproject.test_runner.CustomDjangoRunner'
GREEN_CUSTOM_CONFIG = {
'verbose': 2,
'processes': 4,
'run_coverage': True,
'junit_report': 'django-test-results.xml'
}# myapp/management/commands/test_green.py
from django.core.management.base import BaseCommand
from green.djangorunner import DjangoRunner
class Command(BaseCommand):
"""Custom management command for Green testing."""
help = 'Run tests using Green with custom options'
def add_arguments(self, parser):
parser.add_argument('test_labels', nargs='*', type=str)
parser.add_argument('--coverage', action='store_true',
help='Enable coverage reporting')
parser.add_argument('--processes', type=int, default=0,
help='Number of parallel processes')
parser.add_argument('--verbosity', type=int, default=2,
help='Green verbosity level')
def handle(self, *args, **options):
"""Run tests with Green."""
runner = DjangoRunner(
verbose=options['verbosity'],
keepdb=True, # Keep database for faster subsequent runs
)
# Configure Green-specific options
if options['coverage']:
# Enable coverage in Green configuration
pass
test_labels = options.get('test_labels', [])
failures = runner.run_tests(test_labels)
if failures:
self.stdout.write(
self.style.ERROR(f'{failures} test(s) failed')
)
else:
self.stdout.write(
self.style.SUCCESS('All tests passed!')
)
# Usage:
# python manage.py test_green --coverage --processes 4 myapp# tests/test_api.py
from django.test import TestCase
from django.contrib.auth.models import User
from rest_framework.test import APIClient
from rest_framework import status
class APITestCase(TestCase):
"""API tests that benefit from Green's parallel execution."""
def setUp(self):
"""Set up API test client and user."""
self.client = APIClient()
self.user = User.objects.create_user(
username='testuser',
password='testpass123'
)
def test_api_authentication(self):
"""Test API authentication endpoint."""
response = self.client.post('/api/auth/login/', {
'username': 'testuser',
'password': 'testpass123'
})
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('token', response.data)
def test_api_protected_endpoint(self):
"""Test protected API endpoint."""
# Authenticate
self.client.force_authenticate(user=self.user)
response = self.client.get('/api/protected/')
self.assertEqual(response.status_code, status.HTTP_200_OK)# Required setting
TEST_RUNNER = 'green.djangorunner.DjangoRunner'
# Optional Green-specific settings
GREEN_VERBOSITY = 2 # Verbosity level (0-4)
GREEN_PROCESSES = 0 # Process count (0 = auto-detect)
GREEN_RUN_COVERAGE = False # Enable coverage
GREEN_COVERAGE_CONFIG_FILE = None # Coverage config file
GREEN_OMIT_PATTERNS = [] # Coverage omit patterns
GREEN_DEBUG = False # Green debug output
GREEN_JUNIT_REPORT = None # JUnit XML report file
GREEN_DISABLE_WINDOWS = False # Disable Windows formatting
GREEN_NO_COLOR = False # Disable colored output# Django's built-in test options (still available)
./manage.py test --keepdb --parallel 4 --reverse
# Green-specific options
./manage.py test --green-verbosity 3
# Combined usage
./manage.py test --green-verbosity 2 --keepdb --parallel 4 myapp.teststests/ directories--keepdb during development for faster test runsoverride_settings for test-specific settingsInstall with Tessl CLI
npx tessl i tessl/pypi-green