Permalink
Browse files

Take runner from django-nose so we can pass params from command line

  • Loading branch information...
Almad committed Mar 13, 2011
1 parent 378e214 commit b8c4bf094187f3cc2f06efdb40e5101f3152c55d
View
@@ -1,4 +1,4 @@
-Lukas Linhart <bugs@almad.net> is primary author of this library.
+Lukas "Almad" Linhart <bugs@almad.net> is the primary author of this library.
However, code and/or inspiration has been taken from other generous
open-source authors, listed in arbitrary order:
@@ -11,13 +11,14 @@ Jeff Balogh wrote a patch for Django's #12671. Snippets from this patch
(commited in http://code.djangoproject.com/changeset/12306) were used for
flushing cache part.
+Jeff also started django-nose project. Its test runners are used in DST.
+
Jason Pellerin wrote the nose testing framework that made this library
possible. Also, he wrote propagation methods for making unittest assert
-methods available.
+methods available that were adopted in DST.
Rob Hudson wrote a patch for multithreaded Django dev server, available at
http://code.djangoproject.com/ticket/3357 . It served as a base for Django live
server embedded in code.
Andrej Tokarcik contributed TemplateTagTestCase and variety of improvements.
-
No changes.
@@ -0,0 +1,35 @@
+"""
+Add extra options from the test runner to the ``test`` command, so that you can
+browse all the nose options from the command line.
+"""
+# Taken from django_nose project
+
+from django.conf import settings
+from django.test.utils import get_runner
+
+
+if 'south' in settings.INSTALLED_APPS:
+ from south.management.commands.test import Command
+else:
+ from django.core.management.commands.test import Command
+
+
+# Django < 1.2 compatibility
+test_runner = settings.TEST_RUNNER
+if test_runner.endswith('run_tests') or test_runner.endswith('run_gis_tests'):
+ import warnings
+ warnings.warn(
+ 'Use `django_nose.NoseTestSuiteRunner` instead of `%s`' % test_runner,
+ DeprecationWarning)
+
+
+TestRunner = get_runner(settings)
+
+if hasattr(TestRunner, 'options'):
+ extra_options = TestRunner.options
+else:
+ extra_options = []
+
+
+class Command(Command):
+ option_list = Command.option_list + tuple(extra_options)
@@ -32,7 +32,7 @@
selenium_patched_open
)
-__all__ = ("CherryPyLiveServerPlugin", "DjangoLiveServerPlugin", "DjangoPlugin", "SeleniumPlugin", "SaneTestSelectionPlugin")
+__all__ = ("CherryPyLiveServerPlugin", "DjangoLiveServerPlugin", "DjangoPlugin", "SeleniumPlugin", "SaneTestSelectionPlugin", "ResultPlugin")
def flush_cache(test_case=None):
from django.contrib.contenttypes.models import ContentType
@@ -613,3 +613,28 @@ def startTest(self, test):
self.skipped = True
#raise SkipTest(u"Test type %s not enabled" % getattr(test_case, "test_type", "unit"))
+##########
+### Result plugin is used when using Django test runner
+### Taken from django-nose project.
+### (C) Jeff Balogh and contributors, released under BSD license.
+##########
+
+class ResultPlugin(Plugin):
+ """
+ Captures the TestResult object for later inspection.
+
+ nose doesn't return the full test result object from any of its runner
+ methods. Pass an instance of this plugin to the TestProgram and use
+ ``result`` after running the tests to get the TestResult object.
+ """
+
+ name = "djangoresult"
+ activation_parameter = '--with-djangoresult'
+ enabled = True
+
+ def configure(self, options, config):
+ Plugin.configure(self, options, config)
+
+ def finalize(self, result):
+ self.result = result
+
@@ -1,49 +1,124 @@
+import os
import sys
+import nose
+from nose.config import Config, all_config_files
+from nose.plugins.manager import DefaultPluginManager
+
+from django.core.management.base import BaseCommand
+from django.test import utils
+
from djangosanetesting.noseplugins import (
DjangoPlugin,
DjangoLiveServerPlugin, SeleniumPlugin, CherryPyLiveServerPlugin,
DjangoTranslationPlugin,
+ ResultPlugin,
)
-import nose
-from nose.config import Config, all_config_files
-from nose.plugins.manager import DefaultPluginManager
-
__all__ = ("run_tests",)
-def activate_plugin(plugin):
- if plugin.activation_parameter not in sys.argv:
- sys.argv.append(plugin.activation_parameter)
+"""
+Act as Django test runner, but use nose. Enable common django-sane-testing
+plugins by default.
+
+You can use
+
+ DST_NOSE_ARGS = ['list', 'of', 'args']
+
+in settings.py for arguments that you always want passed to nose.
+
+Test runners themselves are basically copypasted from django-nose project.
+(C) Jeff Balogh and contributors, released under BSD license.
+
+Thanks and kudos.
+
+Modified for django-sane-testing by Almad.
+"""
+
+def activate_plugin(plugin, argv=None):
+ argv = argv or sys.argv
+ if plugin.activation_parameter not in argv:
+ argv.append(plugin.activation_parameter)
-def run_tests(test_labels, verbosity=1, interactive=True, extra_tests=[]):
- """ Run tests with nose instead of defualt test runner """
+try:
+ any
+except NameError:
+ def any(iterable):
+ for element in iterable:
+ if element:
+ return True
+ return False
+
+def run_tests(test_labels, verbosity=1, interactive=True, spatial_db=False):
+ """Test runner that invokes nose."""
+ # Prepare django for testing.
from django.conf import settings
-
- plugins = [DjangoPlugin(), SeleniumPlugin(), DjangoTranslationPlugin()]
+
+ utils.setup_test_environment()
+ old_db_name = settings.DATABASE_NAME
+
+ result_plugin = ResultPlugin()
+ plugins = [DjangoPlugin(), SeleniumPlugin(), DjangoTranslationPlugin(), result_plugin]
if getattr(settings, 'CHERRYPY_TEST_SERVER', False):
plugins.append(CherryPyLiveServerPlugin())
else:
plugins.append(DjangoLiveServerPlugin())
- config = Config(files=all_config_files(), plugins=DefaultPluginManager(plugins))
-
- # we've been called in form ./manage.py test. Test is however not a test location,
- # so strip it so we can get one
- sys.argv = [sys.argv[0]] + sys.argv[2:]
-
+ # Do not pretend it's a production environment.
+ # settings.DEBUG = False
+
+ # We pass nose a list of arguments that looks like sys.argv, but customize
+ # to avoid unknown django arguments.
+ nose_argv = ['nosetests']
+ if hasattr(settings, 'NOSE_ARGS'):
+ nose_argv.extend(settings.NOSE_ARGS)
+
# activate all required plugins
- activate_plugin(DjangoPlugin)
- activate_plugin(SeleniumPlugin)
- activate_plugin(DjangoTranslationPlugin)
+ activate_plugin(DjangoPlugin, nose_argv)
+ activate_plugin(SeleniumPlugin, nose_argv)
+ activate_plugin(DjangoTranslationPlugin, nose_argv)
+# activate_plugin(ResultPlugin, nose_argv)
if getattr(settings, 'CHERRYPY_TEST_SERVER', False):
- activate_plugin(CherryPyLiveServerPlugin)
+ activate_plugin(CherryPyLiveServerPlugin, nose_argv)
else:
- activate_plugin(DjangoLiveServerPlugin)
+ activate_plugin(DjangoLiveServerPlugin, nose_argv)
+
+ # Skip over 'manage.py test' and any arguments handled by django.
+ django_opts = ['--noinput']
+ for opt in BaseCommand.option_list:
+ django_opts.extend(opt._long_opts)
+ django_opts.extend(opt._short_opts)
+
+ nose_argv.extend(opt for opt in sys.argv[2:] if
+ not any(opt.startswith(d) for d in django_opts))
+
+ if verbosity >= 1:
+ print ' '.join(nose_argv)
+
+ test_program = nose.core.TestProgram(argv=nose_argv, exit=False,
+ addplugins=plugins)
+
+ # FIXME: ResultPlugin is working not exactly as advertised in django-nose
+ # multiple instance problem, find workaround
+# result = result_plugin.result
+# return len(result.failures) + len(result.errors)
+ return not test_program.success
+
+def _get_options():
+ """Return all nose options that don't conflict with django options."""
+ cfg_files = nose.core.all_config_files()
+ manager = nose.core.DefaultPluginManager()
+ config = nose.core.Config(env=os.environ, files=cfg_files, plugins=manager)
+ options = config.getParser().option_list
+ django_opts = [opt.dest for opt in BaseCommand.option_list] + ['version']
+ return tuple(o for o in options if o.dest not in django_opts and
+ o.action != 'help')
+
- return nose.run(config=config)
+# Replace the builtin command options with the merged django/nose options.
+run_tests.options = _get_options()
run_tests.__test__ = False
View
@@ -45,7 +45,8 @@
'django = %s.noseplugins:DjangoPlugin' % name,
'selenium = %s.noseplugins:SeleniumPlugin' % name,
'sanetestselection = %s.noseplugins:SaneTestSelectionPlugin' % name,
- 'djangotranslations = %s.noseplugins:DjangoTranslationPlugin' % name,
+ 'djangotranslations = %s.noseplugins:DjangoTranslationPlugin' % name,
+ 'djangoresultplugin = %s.noseplugins:ResultPlugin' % name,
]
}
)
View
@@ -45,6 +45,8 @@
'django.contrib.sites',
'django.contrib.admin',
'testapp',
+
+ 'djangosanetesting',
)
TEST_RUNNER='djangosanetesting.testrunner.run_tests'

0 comments on commit b8c4bf0

Please sign in to comment.