Commit 53b61d9c authored by Russell Keith-Magee's avatar Russell Keith-Magee
Browse files

Fixed #12624 -- Modified test runners to be class based.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12255 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 34e42018
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -487,8 +487,8 @@ MESSAGE_STORAGE = 'django.contrib.messages.storage.user_messages.LegacyFallbackS
# TESTING #
###########

# The name of the method to use to invoke the test suite
TEST_RUNNER = 'django.test.simple.run_tests'
# The name of the class to use to run the test suite
TEST_RUNNER = 'django.test.simple.DjangoTestSuiteRunner'

# The name of the database to use for testing purposes.
# If None, a name of 'test_' + DATABASE_NAME will be assumed
+12 −6
Original line number Diff line number Diff line
@@ -21,14 +21,20 @@ class Command(BaseCommand):
        verbosity = int(options.get('verbosity', 1))
        interactive = options.get('interactive', True)
        failfast = options.get('failfast', False)
        test_runner = get_runner(settings)
        TestRunner = get_runner(settings)

        # Some custom test runners won't accept the failfast flag, so let's make sure they accept it before passing it to them
        if 'failfast' in test_runner.func_code.co_varnames:
            failures = test_runner(test_labels, verbosity=verbosity, interactive=interactive,
                                   failfast=failfast)
        if hasattr(TestRunner, 'func_name'):
            # Pre 1.2 test runners were just functions,
            # and did not support the 'failfast' option.
            import warnings
            warnings.warn(
                'Function-based test runners are deprecated. Test runners should be classes with a run_tests() method.',
                PendingDeprecationWarning
            )
            failures = TestRunner(test_labels, verbosity=verbosity, interactive=interactive)
        else:
            failures = test_runner(test_labels, verbosity=verbosity, interactive=interactive)
            test_runner = TestRunner(verbosity=verbosity, interactive=interactive, failfast=failfast)
            failures = test_runner.run_tests(test_labels)

        if failures:
            sys.exit(bool(failures))
+87 −46
Original line number Diff line number Diff line
@@ -197,28 +197,18 @@ def reorder_suite(suite, classes):
        bins[0].addTests(bins[i+1])
    return bins[0]

def run_tests(test_labels, verbosity=1, interactive=True, failfast=False, extra_tests=[]):
    """
    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.
class DjangoTestSuiteRunner(object):
    def __init__(self, verbosity=1, interactive=True, failfast=True):
        self.verbosity = verbosity
        self.interactive = interactive
        self.failfast = failfast

    Returns the number of tests that failed.
    """
    def setup_test_environment(self):
        setup_test_environment()

        settings.DEBUG = False

    def build_suite(self, test_labels, extra_tests=None):
        suite = unittest.TestSuite()

        if test_labels:
@@ -232,21 +222,72 @@ def run_tests(test_labels, verbosity=1, interactive=True, failfast=False, extra_
            for app in get_apps():
                suite.addTest(build_suite(app))

        if extra_tests:
            for test in extra_tests:
                suite.addTest(test)

    suite = reorder_suite(suite, (TestCase,))
        return reorder_suite(suite, (TestCase,))

    def setup_databases(self):
        from django.db import connections
        old_names = []
        for alias in connections:
            connection = connections[alias]
            old_names.append((connection, connection.settings_dict['NAME']))
        connection.creation.create_test_db(verbosity, autoclobber=not interactive)
    result = DjangoTestRunner(verbosity=verbosity, failfast=failfast).run(suite)
            connection.creation.create_test_db(self.verbosity, autoclobber=not self.interactive)
        return old_names

    def run_suite(self, suite):
        return DjangoTestRunner(verbosity=self.verbosity, failfast=self.failfast).run(suite)

    def teardown_databases(self, old_names):
        for connection, old_name in old_names:
        connection.creation.destroy_test_db(old_name, verbosity)
            connection.creation.destroy_test_db(old_name, self.verbosity)

    def teardown_test_environment(self):
        teardown_test_environment()

    def suite_result(self, result):
        return len(result.failures) + len(result.errors)

    def run_tests(self, test_labels, extra_tests=None):
        """
        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.
        """
        self.setup_test_environment()

        old_names = self.setup_databases()

        suite = self.build_suite(test_labels, extra_tests)

        result = self.run_suite(suite)

        self.teardown_databases(old_names)

        self.teardown_test_environment()

        return self.suite_result(result)

def run_tests(test_labels, verbosity=1, interactive=True, failfast=False, extra_tests=None):
    import warnings
    warnings.warn(
        'The run_tests() test runner has been deprecated in favor of DjangoTestSuiteRunner.',
        PendingDeprecationWarning
    )
    test_runner = DjangoTestSuiteRunner(verbosity=verbosity, interactive=interactive, failfast=failfast)
    return test_runner.run_tests(test_labels, extra_tests=extra_tests)
+3 −0
Original line number Diff line number Diff line
@@ -74,6 +74,9 @@ their deprecation, as per the :ref:`Django deprecation policy
          ``django.utils.formats.get_format()`` to get the appropriate
          formats.

        * The ability to use a function-based test runners will be removed,
          along with the ``django.test.simple.run_tests()`` test runner.

    * 2.0
        * ``django.views.defaults.shortcut()``. This function has been moved
          to ``django.contrib.contenttypes.views.shortcut()`` as part of the
+10 −2
Original line number Diff line number Diff line
@@ -367,6 +367,14 @@ An undocumented regex for validating email addresses has been moved from
django.form.fields to django.core.validators. You will need to update
your imports if you are using it.

Function-based test runners
---------------------------

Django 1.2 changes the test runner tools to use a class-based
approach. Old style function-based test runners will still work, but
should be updated to use the new :ref:`class-based runners
<topics-testing-test_runner>`.

What's new in Django 1.2
========================

Loading