From ab20b0da8042fb803d7e246fa230cbac27807cb7 Mon Sep 17 00:00:00 2001 From: Damien Nozay Date: Fri, 12 Feb 2016 13:38:17 -0800 Subject: [PATCH] Add more tests for the django test runner. see also issue #44. --- tests/django_example/example/__init__.py | 0 tests/django_example/example/settings.py | 31 +++++++++++ tests/django_example/example/urls.py | 8 +++ tests/django_example/example/wsgi.py | 7 +++ tests/django_example/manage.py | 9 ++++ tests/django_test.py | 69 ++++++++++++++++++++---- xmlrunner/extra/djangotestrunner.py | 17 ++++-- 7 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 tests/django_example/example/__init__.py create mode 100644 tests/django_example/example/settings.py create mode 100644 tests/django_example/example/urls.py create mode 100644 tests/django_example/example/wsgi.py create mode 100755 tests/django_example/manage.py diff --git a/tests/django_example/example/__init__.py b/tests/django_example/example/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/django_example/example/settings.py b/tests/django_example/example/settings.py new file mode 100644 index 0000000..1f69f09 --- /dev/null +++ b/tests/django_example/example/settings.py @@ -0,0 +1,31 @@ + +import os + + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +SECRET_KEY = 'not-a-secret' +DEBUG = True +ALLOWED_HOSTS = [] +INSTALLED_APPS = ['app', 'app2'] +MIDDLEWARE_CLASSES = [] +ROOT_URLCONF = 'example.urls' +TEMPLATES = [] +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +LANGUAGE_CODE = 'en-us' +TIME_ZONE = 'UTC' +USE_I18N = True +USE_L10N = True +USE_TZ = True +STATIC_URL = '/static/' + +# The settings we care about for xmlrunner. +# They are commented out because we will use settings.configure() in tests. + +# TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner' +# TEST_OUTPUT_FILE_NAME = 'results.xml' +# TEST_OUTPUT_VERBOSE = 2 diff --git a/tests/django_example/example/urls.py b/tests/django_example/example/urls.py new file mode 100644 index 0000000..0c8ed42 --- /dev/null +++ b/tests/django_example/example/urls.py @@ -0,0 +1,8 @@ + +from django.conf.urls import url +from django.contrib import admin + + +urlpatterns = [ + url(r'^admin/', admin.site.urls), +] diff --git a/tests/django_example/example/wsgi.py b/tests/django_example/example/wsgi.py new file mode 100644 index 0000000..314e9ca --- /dev/null +++ b/tests/django_example/example/wsgi.py @@ -0,0 +1,7 @@ + +import os +from django.core.wsgi import get_wsgi_application + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings") +application = get_wsgi_application() diff --git a/tests/django_example/manage.py b/tests/django_example/manage.py new file mode 100755 index 0000000..e0e65d2 --- /dev/null +++ b/tests/django_example/manage.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python +import os +import sys + + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings") + from django.core.management import execute_from_command_line + execute_from_command_line(sys.argv) diff --git a/tests/django_test.py b/tests/django_test.py index f113991..b4d4f23 100644 --- a/tests/django_test.py +++ b/tests/django_test.py @@ -1,7 +1,11 @@ from xmlrunner.unittest import unittest import sys -from os import path, chdir, getcwd +import os +from os import path +import glob +import tempfile +import shutil try: import django @@ -9,6 +13,9 @@ django = None else: from django.test.utils import get_runner + from django.conf import settings, UserSettingsHolder + from django.apps import apps + TESTS_DIR = path.dirname(__file__) @@ -17,15 +24,30 @@ class DjangoTest(unittest.TestCase): def setUp(self): - self._old_cwd = getcwd() + self._old_cwd = os.getcwd() self.project_dir = path.abspath(path.join(TESTS_DIR, 'django_example')) - chdir(self.project_dir) + self.tmpdir = tempfile.mkdtemp() + os.chdir(self.project_dir) sys.path.append(self.project_dir) - import django.conf - django.conf.settings = django.conf.LazySettings() + # allow changing settings + self.old_settings = settings._wrapped + os.environ['DJANGO_SETTINGS_MODULE'] = 'example.settings' + settings.INSTALLED_APPS # load settings on first access + settings.DATABASES['default']['NAME'] = path.join( + self.tmpdir, 'db.sqlilte3') + # this goes around the "settings already loaded" issue. + self.override = UserSettingsHolder(settings._wrapped) + settings._wrapped = self.override def tearDown(self): - chdir(self._old_cwd) + os.chdir(self._old_cwd) + shutil.rmtree(self.tmpdir) + settings._wrapped = self.old_settings + + def _override_settings(self, **kwargs): + # see django.test.utils.override_settings + for key, new_value in kwargs.items(): + setattr(self.override, key, new_value) def _check_runner(self, runner): suite = runner.build_suite(test_labels=['app2', 'app']) @@ -42,17 +64,42 @@ def _check_runner(self, runner): ])) def test_django_runner(self): - from django.conf import settings - settings.configure(INSTALLED_APPS=['app', 'app2']) runner_class = get_runner(settings) runner = runner_class() self._check_runner(runner) def test_django_xmlrunner(self): - from django.conf import settings - settings.configure( - INSTALLED_APPS=['app', 'app2'], + self._override_settings( TEST_RUNNER='xmlrunner.extra.djangotestrunner.XMLTestRunner') runner_class = get_runner(settings) runner = runner_class() self._check_runner(runner) + + def test_django_single_report(self): + self._override_settings( + TEST_OUTPUT_DIR=self.tmpdir, + TEST_OUTPUT_FILE_NAME='results.xml', + TEST_OUTPUT_VERBOSE=0, + TEST_RUNNER='xmlrunner.extra.djangotestrunner.XMLTestRunner') + apps.populate(settings.INSTALLED_APPS) + runner_class = get_runner(settings) + runner = runner_class() + suite = runner.build_suite() + runner.run_suite(suite) + expected_file = path.join(self.tmpdir, 'results.xml') + self.assertTrue(path.exists(expected_file), + 'did not generate xml report where expected.') + + def test_django_multiple_reports(self): + self._override_settings( + TEST_OUTPUT_DIR=self.tmpdir, + TEST_OUTPUT_VERBOSE=0, + TEST_RUNNER='xmlrunner.extra.djangotestrunner.XMLTestRunner') + apps.populate(settings.INSTALLED_APPS) + runner_class = get_runner(settings) + runner = runner_class() + suite = runner.build_suite(test_labels=None) + runner.run_suite(suite) + test_files = glob.glob(path.join(self.tmpdir, 'TEST*.xml')) + self.assertTrue(test_files, + 'did not generate xml reports where expected.') diff --git a/xmlrunner/extra/djangotestrunner.py b/xmlrunner/extra/djangotestrunner.py index a4c6905..0e565aa 100644 --- a/xmlrunner/extra/djangotestrunner.py +++ b/xmlrunner/extra/djangotestrunner.py @@ -10,6 +10,7 @@ """ import xmlrunner +import os.path from django.conf import settings from django.test.runner import DiscoverRunner @@ -23,7 +24,17 @@ def run_suite(self, suite, **kwargs): if isinstance(verbosity, bool): verbosity = (1, 2)[verbosity] descriptions = getattr(settings, 'TEST_OUTPUT_DESCRIPTIONS', False) - output = getattr(settings, 'TEST_OUTPUT_DIR', '.') - return xmlrunner.XMLTestRunner( + output_dir = getattr(settings, 'TEST_OUTPUT_DIR', '.') + single_file = getattr(settings, 'TEST_OUTPUT_FILE_NAME', None) + + kwargs = dict( verbosity=verbosity, descriptions=descriptions, - output=output, failfast=self.failfast).run(suite) + failfast=self.failfast) + if single_file is not None: + file_path = os.path.join(output_dir, single_file) + with open(file_path, 'wb') as xml: + return xmlrunner.XMLTestRunner( + output=xml, **kwargs).run(suite) + else: + return xmlrunner.XMLTestRunner( + output=output_dir, **kwargs).run(suite)