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
This commit is contained in:
Russell Keith-Magee 2010-02-01 13:00:00 +00:00
parent e0dd8a930b
commit 84599495a0
2 changed files with 70 additions and 16 deletions

View File

@ -133,24 +133,58 @@ def build_test(label):
if len(parts) < 2 or len(parts) > 3: 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) 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]) app_module = get_app(parts[0])
test_module = get_tests(app_module)
TestClass = getattr(app_module, parts[1], None) TestClass = getattr(app_module, parts[1], None)
# Couldn't find the test class in models.py; look in tests.py # Couldn't find the test class in models.py; look in tests.py
if TestClass is None: if TestClass is None:
test_module = get_tests(app_module)
if test_module: if test_module:
TestClass = getattr(test_module, parts[1], None) TestClass = getattr(test_module, parts[1], None)
if len(parts) == 2: # label is app.TestClass 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
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: try:
return unittest.TestLoader().loadTestsFromTestCase(TestClass) doctests = doctest.DocTestSuite(module,
except TypeError: checker=doctestOutputChecker,
raise ValueError("Test label '%s' does not refer to a test class" % label) runner=DocTestRunner)
else: # label is app.TestClass.test_method # Now iterate over the suite, looking for doctests whose name
if not TestClass: # matches the pattern that was given
raise ValueError("Test label '%s' does not refer to a test class" % label) for test in doctests:
return TestClass(parts[2]) 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. # Python 2.3 compatibility: TestSuites were made iterable in 2.4.
# We need to iterate over them, so we add the missing method when # We need to iterate over them, so we add the missing method when

View File

@ -261,19 +261,39 @@ Note that we used ``animals``, not ``myproject.animals``.
.. versionadded:: 1.0 .. versionadded:: 1.0
You can now choose which test to run. You can now choose which test to run.
If you use unit tests, as opposed to You can be even *more* specific by naming an individual test case. To
doctests, you can be even *more* specific in choosing which tests to execute. run a single test case in an application (for example, the
To run a single test case in an application (for example, the ``AnimalTestCase`` described in the "Writing unit tests" section), add
``AnimalTestCase`` described in the "Writing unit tests" section), add the the name of the test case to the label on the command line::
name of the test case to the label on the command line::
$ ./manage.py test animals.AnimalTestCase $ ./manage.py test animals.AnimalTestCase
And it gets even more granular than that! To run a *single* test method inside And it gets even more granular than that! To run a *single* test
a test case, add the name of the test method to the label:: method inside a test case, add the name of the test method to the
label::
$ ./manage.py test animals.AnimalTestCase.testFluffyAnimals $ ./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 .. versionadded:: 1.2
You can now trigger a graceful exit from a test run by pressing ``Ctrl-C``. You can now trigger a graceful exit from a test run by pressing ``Ctrl-C``.