Django doctests in views.py Django doctests in views.py python python

Django doctests in views.py


You can do this by adding/editing the suite() function in tests.py which defines what tests will be run by the django test runner.

import unittestimport doctestfrom project import viewsdef suite():    suite = unittest.TestSuite()    suite.addTest(doctest.DocTestSuite(views))    return suite

Then just run your tests as usual and you should see your doctests in views.py run.

$ python manage.py test project

This is described in more detail in the django testing documentation

When you run your tests, the default behavior of the test utility is to find all the test cases (that is, subclasses of unittest.TestCase) in models.py and tests.py, automatically build a test suite out of those test cases, and run that suite.

There is a second way to define the test suite for a module: if you define a function called suite() in either models.py or tests.py, the Django test runner will use that function to construct the test suite for that module. This follows the suggested organization for unit tests. See the Python documentation for more details on how to construct a complex test suite.

However, keep in mind that constructing your own test suite means that the django test runner will not automatically run any tests you have in tests.py. You'll have to add these into your suite manually, for example

import unittestimport doctestfrom project import viewsclass FooTestCase(unittest.TestCase):    def testFoo(self):        self.assertEquals('foo', 'bar')def suite():    suite = unittest.TestSuite()    suite.addTest(doctest.DocTestSuite(views))    suite.addTest(unittest.TestLoader().loadTestsFromTestCase(FooTestCase))    return suite


Things have changed in Django 1.6:

Doctests will no longer be automatically discovered. To integrate doctests in your test suite, follow the recommendations in the Python documentation.

So all I had to do myself was (in my_app/tests.py):

import unittestimport doctestfrom my_app import viewsdef load_tests(loader, tests, ignore):    tests.addTests(doctest.DocTestSuite(views))    return tests


This is my tests/__init__.py implementation, based on Jesse Shieh answer:

import doctestimport unittestlist_of_doctests = [    'myapp.views.myview',    'myapp.forms.myform',]list_of_unittests = [    'sometestshere',  # This file is myapp/tests/sometestshere.py    'moretestshere',  # This file is myapp/tests/moretestshere.py    'myapp.tests.othertest',  # Absolute paths also work.]def suite():    suite = unittest.TestSuite()    for t in list_of_doctests:        suite.addTest(doctest.DocTestSuite(            __import__(t, globals(), locals(), fromlist=["*"])        ))    for t in list_of_unittests:        suite.addTest(unittest.TestLoader().loadTestsFromModule(            __import__(t, globals(), locals(), fromlist=["*"])        ))    return suite

Basically, this solution allows adding arbitrary "files" (actually, modules) to the test suite. It allows splitting the unit tests into separate files, and allows adding any module that contains doctests. Just add the module names to the appropriate list at the top of this file.