unittest-based test runner with Ant/JUnit like XML reporting.
Specialized test runner for Django projects that integrates unittest-xml-reporting with Django's testing framework. Provides Django-specific configuration options and seamless integration with Django's test discovery and execution system.
Django test runner that extends Django's DiscoverRunner to use XMLTestRunner for XML report generation.
class XMLTestRunner(DiscoverRunner):
test_runner = xmlrunner.XMLTestRunner
def get_resultclass(self):
"""
Override Django's default result class behavior.
Returns:
- None: suppresses Django's DebugSQLTextTestResult to use XMLTestResult
"""
def get_test_runner_kwargs(self):
"""
Get keyword arguments for XMLTestRunner based on Django settings.
Returns:
- dict: configuration dictionary for XMLTestRunner
"""
def run_suite(self, suite, **kwargs):
"""
Execute test suite using XMLTestRunner.
Parameters:
- suite: TestSuite instance
- **kwargs: additional run arguments
Returns:
- TestResult: result object with test outcomes
"""Configure the Django test runner and its behavior through Django settings:
# settings.py
# Enable XML test runner
TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner'
# XML reporting configuration
TEST_OUTPUT_VERBOSE = 1 # Verbosity level (0|1|2)
TEST_OUTPUT_DESCRIPTIONS = False # Show docstrings instead of method names
TEST_OUTPUT_DIR = '.' # Output directory for XML reports
TEST_OUTPUT_FILE_NAME = None # Single output file name (None = multiple files)# Verbosity levels
TEST_OUTPUT_VERBOSE: int = 1
# 0: Minimal output
# 1: Standard output with test results
# 2: Verbose output with test descriptions
# Description display
TEST_OUTPUT_DESCRIPTIONS: bool = False
# False: Show test method names (test_method_name)
# True: Show test docstrings when verbosity = 2
# Output configuration
TEST_OUTPUT_DIR: str = '.'
# Directory path for XML report files
# Created if it doesn't exist
TEST_OUTPUT_FILE_NAME: str | None = None
# None: Generate separate file per test class
# str: Generate single XML file with specified name# settings.py
TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner'
TEST_OUTPUT_DIR = 'test-reports'
TEST_OUTPUT_VERBOSE = 2
TEST_OUTPUT_DESCRIPTIONS = True
# Run Django tests
python manage.py test# settings.py
import os
# Different configurations for different environments
if os.getenv('CI'):
# CI environment - single file output
TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner'
TEST_OUTPUT_DIR = '/tmp/test-reports'
TEST_OUTPUT_FILE_NAME = 'django-tests.xml'
TEST_OUTPUT_VERBOSE = 1
else:
# Development environment - multiple files
TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner'
TEST_OUTPUT_DIR = 'test-reports'
TEST_OUTPUT_VERBOSE = 2
TEST_OUTPUT_DESCRIPTIONS = True# Run all tests with XML reporting
python manage.py test
# Run specific app tests
python manage.py test myapp
# Run with custom verbosity
python manage.py test --verbosity=2
# Run specific test class
python manage.py test myapp.tests.TestMyModel
# Run with custom settings
python manage.py test --settings=myproject.test_settings# tests.py
from django.test import TestCase
from django.contrib.auth.models import User
class UserModelTest(TestCase):
"""Test user model functionality."""
def setUp(self):
"""Set up test data."""
self.user = User.objects.create_user(
username='testuser',
email='test@example.com',
password='testpass123'
)
def test_user_creation(self):
"""Test user is created correctly."""
self.assertEqual(self.user.username, 'testuser')
self.assertEqual(self.user.email, 'test@example.com')
self.assertTrue(self.user.check_password('testpass123'))
def test_user_str_representation(self):
"""Test user string representation."""
self.assertEqual(str(self.user), 'testuser')
# XML report will include Django-specific test information# test_settings.py
from .settings import *
# Use in-memory SQLite for faster tests
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
}
}
# XML test runner configuration
TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner'
TEST_OUTPUT_DIR = 'test-reports'
TEST_OUTPUT_FILE_NAME = 'django-tests.xml'
# Run tests with: python manage.py test --settings=myproject.test_settings# custom_test_runner.py
from xmlrunner.extra.djangotestrunner import XMLTestRunner as BaseXMLTestRunner
class CustomXMLTestRunner(BaseXMLTestRunner):
def get_test_runner_kwargs(self):
"""Customize test runner arguments."""
kwargs = super().get_test_runner_kwargs()
# Add custom properties to XML reports
kwargs.update({
'properties': {
'django_version': django.VERSION,
'database_engine': settings.DATABASES['default']['ENGINE'],
'test_environment': 'custom',
}
})
return kwargs
def run_suite(self, suite, **kwargs):
"""Add custom pre/post test logic."""
print("Starting Django XML test run...")
result = super().run_suite(suite, **kwargs)
print(f"Tests completed: {result.testsRun}")
return result
# settings.py
TEST_RUNNER = 'myproject.custom_test_runner.CustomXMLTestRunner'# ci_settings.py
import os
from .settings import *
# CI-specific configuration
TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner'
# Use environment variables for flexibility
TEST_OUTPUT_DIR = os.getenv('TEST_OUTPUT_DIR', 'test-reports')
TEST_OUTPUT_FILE_NAME = os.getenv('TEST_OUTPUT_FILE', 'django-tests.xml')
TEST_OUTPUT_VERBOSE = int(os.getenv('TEST_VERBOSITY', '1'))
# Example CI script usage:
# export TEST_OUTPUT_DIR=/tmp/test-reports
# export TEST_OUTPUT_FILE=django-junit.xml
# python manage.py test --settings=myproject.ci_settingsThe Django integration:
Django XML reports include Django-specific information:
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite name="myapp.tests.UserModelTest" tests="2" failures="0" errors="0"
time="0.123" timestamp="2023-12-01T10:30:00">
<testcase classname="myapp.tests.UserModelTest" name="test_user_creation"
time="0.045" timestamp="2023-12-01T10:30:00"/>
<testcase classname="myapp.tests.UserModelTest" name="test_user_str_representation"
time="0.012" timestamp="2023-12-01T10:30:01"/>
</testsuite>
</testsuites>The integration automatically handles Django's test database lifecycle and ensures proper test isolation while generating comprehensive XML reports.
Install with Tessl CLI
npx tessl i tessl/pypi-unittest-xml-reporting