Green is a clean, colorful, fast python test runner.
—
Green's test execution system provides multi-process parallel test running with process pool management, worker initialization, and comprehensive test orchestration for improved performance.
The core function that orchestrates test execution with Green's enhanced features including parallel processing, coverage integration, and result aggregation.
def run(suite, stream, args, testing=False):
"""
Run tests with Green's enhanced features.
Args:
suite: Test suite to run (GreenTestSuite or unittest.TestSuite)
stream: Output stream, will be wrapped in GreenStream if not already
args: Configuration namespace containing execution parameters:
- processes: Number of parallel processes (0 = auto-detect)
- run_coverage: Enable coverage reporting
- initializer: Worker process initializer function
- finalizer: Worker process finalizer function
- debug: Debug level for execution details
testing (bool): Enable testing mode behavior (affects coverage and output)
Returns:
GreenTestResult: Comprehensive test execution results with:
- Individual test outcomes
- Timing information
- Coverage data (if enabled)
- Process execution statistics
Example:
from green.runner import run
from green.loader import GreenTestLoader
from green.output import GreenStream
from green.config import get_default_args
import sys
# Load tests
loader = GreenTestLoader()
suite = loader.loadTargets(['tests/'])
# Configure execution
args = get_default_args()
args.processes = 4
args.run_coverage = True
# Run tests
stream = GreenStream(sys.stdout)
result = run(suite, stream, args)
print(f"Tests run: {result.testsRun}")
print(f"Success: {result.wasSuccessful()}")
"""Helper class for managing worker process initialization and cleanup functions.
class InitializerOrFinalizer:
"""
Manages worker process setup and teardown functions.
Allows specifying custom initialization and cleanup code that runs
in each worker process before and after test execution.
"""
def __init__(self, dotted_function):
"""
Initialize with a dotted function name.
Args:
dotted_function (str): Fully qualified function name like
'mymodule.setup_function' or
'mypackage.tests.init_worker'
Example:
initializer = InitializerOrFinalizer('tests.setup.init_database')
finalizer = InitializerOrFinalizer('tests.setup.cleanup_database')
"""
def __call__(self, *args):
"""
Execute the configured function.
Args:
*args: Arguments to pass to the function
Raises:
InitializerOrFinalizerError: If function cannot be loaded or executed
"""from green.runner import run
from green.loader import GreenTestLoader
from green.output import GreenStream
from green.config import parseArguments, mergeConfig
import sys
# Load and configure
args = parseArguments(['tests/'])
config = mergeConfig(args)
loader = GreenTestLoader()
suite = loader.loadTargets(config.targets)
# Execute tests
stream = GreenStream(sys.stdout)
result = run(suite, stream, config)
# Check results
if result.wasSuccessful():
print("All tests passed!")
exit(0)
else:
print(f"Tests failed: {len(result.failures)} failures, {len(result.errors)} errors")
exit(1)from green.runner import run
from green.config import get_default_args
# Configure parallel execution
args = get_default_args()
args.processes = 8 # Use 8 processes
args.debug = 1 # Enable debug output
# Auto-detect optimal process count
args.processes = 0 # Green will use multiprocessing.cpu_count()
# Single-process execution (useful for debugging)
args.processes = 1from green.runner import run, InitializerOrFinalizer
from green.config import get_default_args
# Create worker setup functions
def setup_test_database():
"""Initialize test database connection in worker process."""
import sqlite3
global db_connection
db_connection = sqlite3.connect(':memory:')
# Setup test tables, etc.
def cleanup_test_database():
"""Clean up test database in worker process."""
global db_connection
if db_connection:
db_connection.close()
# Configure with initializer/finalizer
args = get_default_args()
args.initializer = 'tests.setup.setup_test_database'
args.finalizer = 'tests.setup.cleanup_test_database'
# The InitializerOrFinalizer will be used internally
result = run(suite, stream, args)from green.runner import run
from green.config import get_default_args
# Enable coverage
args = get_default_args()
args.run_coverage = True
args.coverage_config_file = '.coveragerc' # Custom coverage config
args.omit_patterns = ['*/tests/*', '*/venv/*'] # Patterns to omit
result = run(suite, stream, args)
# Coverage data will be automatically collected and reportedfrom green.runner import run
from green.config import get_default_args
# Enable detailed debug output
args = get_default_args()
args.debug = 2 # Higher debug levels provide more detail
args.processes = 1 # Single process for easier debugging
result = run(suite, stream, args)from green.runner import run
from green.exceptions import InitializerOrFinalizerError
try:
result = run(suite, stream, args)
# Check for various error conditions
if result.errors:
print(f"Test errors occurred: {len(result.errors)}")
for test, error in result.errors:
print(f" {test}: {error}")
if result.failures:
print(f"Test failures occurred: {len(result.failures)}")
for test, failure in result.failures:
print(f" {test}: {failure}")
except InitializerOrFinalizerError as e:
print(f"Worker process setup failed: {e}")
# Handle worker initialization errors
except KeyboardInterrupt:
print("Test execution interrupted by user")
# Handle Ctrl+C gracefully
except Exception as e:
print(f"Unexpected error during test execution: {e}")
# Handle other execution errorsfrom green.runner import run
from green.suite import GreenTestSuite
from green.config import get_default_args
# Custom test suite configuration
suite = GreenTestSuite()
# Add tests to suite...
# Configure for specific execution environment
args = get_default_args()
# CI/CD environment
if os.environ.get('CI'):
args.processes = 0 # Auto-detect
args.run_coverage = True
args.junit_report = 'test-results.xml'
args.verbose = 1 # Minimal output for CI logs
# Development environment
else:
args.processes = 2 # Don't overwhelm development machine
args.verbose = 2 # More verbose for development
args.debug = 1 # Enable debug output
result = run(suite, stream, args)from green.runner import run
from green.loader import GreenTestLoader
import unittest
class CustomTestResult(unittest.TestResult):
"""Custom result processor."""
pass
# Green can work with custom test frameworks
loader = GreenTestLoader()
suite = loader.loadTargets(['tests/'])
# Green will handle the parallel execution and result aggregation
result = run(suite, stream, args)
# Post-process results with custom logic
custom_processor = CustomTestResult()
# Process results as needed...Green uses a custom process pool implementation for enhanced parallel execution:
# Process count options
args.processes = 0 # Auto-detect (multiprocessing.cpu_count())
args.processes = 1 # Single process (no parallelization)
args.processes = 4 # Specific process count
args.processes = -1 # Use all available CPUs
# Worker customization
args.initializer = 'module.setup_function' # Run in each worker on startup
args.finalizer = 'module.cleanup_function' # Run in each worker on shutdown.coveragerc to optimize data collectionInstall with Tessl CLI
npx tessl i tessl/pypi-green