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

Fixed #6364 -- Added the ability to run individual doctests.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12364 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent e0dd8a93
Loading
Loading
Loading
Loading
+43 −9
Original line number Diff line number Diff line
@@ -133,24 +133,58 @@ def build_test(label):
    if len(parts) < 2 or len(parts) > 3:
        raise ValueError("Test label '%s' should be of the form app.TestCase or app.TestCase.test_method" % label)

    #
    # First, look for TestCase instances with a name that matches
    #
    app_module = get_app(parts[0])
    test_module = get_tests(app_module)
    TestClass = getattr(app_module, parts[1], None)

    # Couldn't find the test class in models.py; look in tests.py
    if TestClass is None:
        test_module = get_tests(app_module)
        if test_module:
            TestClass = getattr(test_module, parts[1], None)

    try:
        if issubclass(TestClass, unittest.TestCase):
            print 'is a test case'
            if len(parts) == 2: # label is app.TestClass
                try:
                    return unittest.TestLoader().loadTestsFromTestCase(TestClass)
                except TypeError:
                    raise ValueError("Test label '%s' does not refer to a test class" % label)
            else: # label is app.TestClass.test_method
        if not TestClass:
            raise ValueError("Test label '%s' does not refer to a test class" % label)
                return TestClass(parts[2])
    except TypeError:
        # TestClass isn't a TestClass - it must be a method or normal class
        pass

    #
    # If there isn't a TestCase, look for a doctest that matches
    #
    tests = []
    for module in app_module, test_module:
        try:
            doctests = doctest.DocTestSuite(module,
                                            checker=doctestOutputChecker,
                                            runner=DocTestRunner)
            # Now iterate over the suite, looking for doctests whose name
            # matches the pattern that was given
            for test in doctests:
                if test._dt_test.name in (
                        '%s.%s' % (module.__name__, '.'.join(parts[1:])),
                        '%s.__test__.%s' % (module.__name__, '.'.join(parts[1:]))):
                    tests.append(test)
        except ValueError:
            # No doctests found.
            pass

    # If no tests were found, then we were given a bad test label.
    if not tests:
        raise ValueError("Test label '%s' does not refer to a test" % label)

    # Construct a suite out of the tests that matched.
    return unittest.TestSuite(tests)

# Python 2.3 compatibility: TestSuites were made iterable in 2.4.
# We need to iterate over them, so we add the missing method when
+27 −7
Original line number Diff line number Diff line
@@ -261,19 +261,39 @@ Note that we used ``animals``, not ``myproject.animals``.
.. versionadded:: 1.0
   You can now choose which test to run.

If you use unit tests, as opposed to
doctests, you can be even *more* specific in choosing which tests to execute.
To run a single test case in an application (for example, the
``AnimalTestCase`` described in the "Writing unit tests" section), add the
name of the test case to the label on the command line::
You can be even *more* specific by naming an individual test case. To
run a single test case in an application (for example, the
``AnimalTestCase`` described in the "Writing unit tests" section), add
the name of the test case to the label on the command line::

    $ ./manage.py test animals.AnimalTestCase

And it gets even more granular than that! To run a *single* test method inside
a test case, add the name of the test method to the label::
And it gets even more granular than that! To run a *single* test
method inside a test case, add the name of the test method to the
label::

    $ ./manage.py test animals.AnimalTestCase.testFluffyAnimals

.. versionadded:: 1.2
   The ability to select individual doctests was added.

You can use the same rules if you're using doctests. Django will use the
test label as a path to the test method or class that you want to run.
If your ``models.py`` or ``tests.py`` has a function with a doctest, or
class with a class-level doctest, you can invoke that test by appending the
name of the test method or class to the label::

    $ ./manage.py test animals.classify

If you want to run the doctest for a specific method in a class, add the
name of the method to the label::

    $ ./manage.py test animals.Classifier.run

If you're using a ``__test__`` dictionary to specify doctests for a
module, Django will use the label as a key in the ``__test__`` dictionary
for defined in ``models.py`` and ``tests.py``.

.. versionadded:: 1.2
   You can now trigger a graceful exit from a test run by pressing ``Ctrl-C``.