4

In a Django project, unit test are usually organized by app, with Django providing a facility to run all of the tests, the tests for a single app, a single test case, or a single test method.

Yet, I find that test cases in a single application usually belong to separate logical groups or clusters, and it would be often useful to be able to only run a single group of tests. Imagine, for example:

  • I have several test cases covering each a different configuration of a single model, and I want to run all of them (and just them) while developing the model. (This is especially troublesome, because the cheap way to do that is to lump the test cases together, so now you have a single test case which you can easily run, but is a nightmare to read and maintain).
  • I have a series of utility classes whose tests are extremely quick because they do not hit the database. I don't need to run model tests and view tests while refactoring these.

I searched around. But while it is relatively straightforward to split your tests in multiple files (see for example these two questions), there doesn't seem to be a straightforward way to run the test groups separately.

So, am I missing something? What is the secret sauce to group tests?

Community
  • 1
  • 1
tawmas
  • 7,443
  • 3
  • 25
  • 24

2 Answers2

2

For Django < 1.6
Personaly I do :

You have a init file :

myapp/tests/__init__.py :

from test1 import *
from test2 import *

def suite():
    import unittest
    #import doctest # If you want to use doctest

    TEST_CASES = ( 
     'sendim.tests.test1',
     'sendim.tests.test2',
    )   
    suite = unittest.TestSuite()

    #suite.addTest(doctest.DocTestSuite(object)) # object which have doctest
    for t in TEST_CASES :
        suite.addTest(unittest.TestLoader().loadTestsFromModule(__import__(t, globals(), locals(), fromlist=["*"])))
    return suite

And for example a testcase in a file named 'TestCase1' :

myapp/tests/test1.py :

from django.utils import unittest

class TestCase1(unittest.TestCase) :
    # Your testcase

If you launch ./manage.py test myapp, it will lauch every testcases.
Else if you launch `./manage.py test myapp.TestCase1, it will execute only this one.

Zulu
  • 8,765
  • 9
  • 49
  • 56
  • By default, when you type `./manage.py test myapp`, it launches `myapp.tests.suite()`. So how you write, it will try to launch tests of suite app. – Zulu May 31 '13 at 07:17
  • Thanks, I misunderstood, you're overriding `suite`. Cheers – TankorSmash May 31 '13 at 12:32
2

It's worth looking at the nose test framework for python for one approach to this problem.

Specifically you can tag tests or set attributes on them. Then only run a subset of tests (across an app or your whole project) tagged with a given tag or tags.

https://nose.readthedocs.org/en/latest/plugins/attrib.html?highlight=tags

Note that nose extends unittest, so you're existing django unittest suite will likely already run with the nose runner.

Greg Sadetsky
  • 4,863
  • 1
  • 38
  • 48
Garethr
  • 1,947
  • 16
  • 19
  • Yep, that's exactly what I was looking for. I found django-nose provides the needed interface with Django, including a test runner and a custom test command! – tawmas Jul 01 '11 at 01:09