django-discover-runner and XML reports? django-discover-runner and XML reports? xml xml

django-discover-runner and XML reports?


Since this question was asked, the unittest-xml-reporting project has added support for the new Django DiscoverRunner class. You can just set the test runner in your Django settings file:

TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner'

It will run the same tests as the DiscoverRunner would.


So it turns out that the solution to this is much easier than I expected. For any other n00bs who may be looking to do this:

The short answer is that I simply cobbled together the two test runners provided by django-discover-runner and unittest-xml-reporting into a custom test runner:

from django.conf import settingsfrom django.test.utils import setup_test_environment, teardown_test_environmentimport xmlrunnerfrom django.core.exceptions import ImproperlyConfiguredfrom django.test import TestCasefrom django.test.simple import DjangoTestSuiteRunner, reorder_suitefrom django.utils.importlib import import_moduletry:    from django.utils.unittest import defaultTestLoaderexcept ImportError:    try:        from unittest2 import defaultTestLoader  # noqa    except ImportError:        raise ImproperlyConfigured("Couldn't import unittest2 default "                               "test loader. Please use Django >= 1.3 "                               "or go install the unittest2 library.")### CUSTOM RUNNER NAMEclass myTestRunner(DjangoTestSuiteRunner):    ### THIS SECTION FROM UNITTESTS-XML-REPORTING    def build_suite(self, test_labels, extra_tests=None, **kwargs):        suite = None        root = getattr(settings, 'TEST_DISCOVER_ROOT', '.')        top_level = getattr(settings, 'TEST_DISCOVER_TOP_LEVEL', None)        pattern = getattr(settings, 'TEST_DISCOVER_PATTERN', 'test*.py')        if test_labels:            suite = defaultTestLoader.loadTestsFromNames(test_labels)            # if single named module has no tests, do discovery within it            if not suite.countTestCases() and len(test_labels) == 1:                suite = None                root = import_module(test_labels[0]).__path__[0]        if suite is None:            suite = defaultTestLoader.discover(root,                pattern=pattern, top_level_dir=top_level)        if extra_tests:            for test in extra_tests:                suite.addTest(test)        return reorder_suite(suite, (TestCase,))    ###THIS SECTION FROM DJANGO-DISCOVER-RUNNER    def run_tests(self, test_labels, extra_tests=None, **kwargs):        """        Run the unit tests for all the test labels in the provided list.        Labels must be of the form:         - app.TestClass.test_method        Run a single specific test method         - app.TestClass        Run all the test methods in a given class         - app        Search for doctests and unittests in the named application.        When looking for tests, the test runner will look in the models and        tests modules for the application.        A list of 'extra' tests may also be provided; these tests        will be added to the test suite.        Returns the number of tests that failed.        """        setup_test_environment()        settings.DEBUG = False        verbosity = getattr(settings, 'TEST_OUTPUT_VERBOSE', 1)        if isinstance(verbosity, bool):            verbosity = (1, 2)[verbosity]        descriptions = getattr(settings, 'TEST_OUTPUT_DESCRIPTIONS', False)        output = getattr(settings, 'TEST_OUTPUT_DIR', '.')        suite = self.build_suite(test_labels, extra_tests)        old_config = self.setup_databases()        result = xmlrunner.XMLTestRunner(            verbosity=verbosity, descriptions=descriptions,            output=output).run(suite)        self.teardown_databases(old_config)        teardown_test_environment()        return len(result.failures) + len(result.errors)

This should be saved somewhere suitable within your project. In your test settings file (test_settings.py - as per django-discover-runner instructions), set the Test Runner:

TEST_RUNNER = '<your-django-project>.customTestRunner.myTestRunner'

You would then use (again, as per django-discover-runner instructions):

django-admin.py test --settings=myapp.test_settings

This solution allows me to use django-discover-runner's features to discover all the test files across my project - specified by django-discover-runner's TEST_DISCOVER_PATTERN option - and still output XML reports as required by Bamboo. Big thanks to the authors of the original code:

django-discover-runner

unittest-xml-reports