Running a specific test case in Django when your app has a tests directory
Asked Answered
T

8

255

The Django documentation (http://docs.djangoproject.com/en/1.3/topics/testing/#running-tests) says that you can run individual test cases by specifying them:

$ ./manage.py test animals.AnimalTestCase

This assumes that you have your tests in a tests.py file in your Django application. If this is true, then this command works like expected.

I have my tests for a Django application in a tests directory:

my_project/apps/my_app/
├── __init__.py
├── tests
│   ├── __init__.py
│   ├── field_tests.py
│   ├── storage_tests.py
├── urls.py
├── utils.py
└── views.py

The tests/__init__.py file has a suite() function:

import unittest

from my_project.apps.my_app.tests import field_tests, storage_tests

def suite():
    tests_loader = unittest.TestLoader().loadTestsFromModule
    test_suites = []
    test_suites.append(tests_loader(field_tests))
    test_suites.append(tests_loader(storage_tests))
    return unittest.TestSuite(test_suites)

To run the tests I do:

$ ./manage.py test my_app

Trying to specify an individual test case raises an exception:

$ ./manage.py test my_app.tests.storage_tests.StorageTestCase
...
ValueError: Test label 'my_app.tests.storage_tests.StorageTestCase' should be of the form app.TestCase or app.TestCase.test_method

I tried to do what the exception message said:

$ ./manage.py test my_app.StorageTestCase
...
ValueError: Test label 'my_app.StorageTestCase' does not refer to a test

How do I specify an individual test case when my tests are in multiple files?

Tonguing answered 3/5, 2011 at 20:11 Comment(0)
F
194

Check out django-nose. This allows you to specify tests to run like:

python manage.py test another.test:TestCase.test_method

or as noted in comments, use the syntax:

python manage.py test another.test.TestCase.test_method
Flosi answered 3/5, 2011 at 20:20 Comment(7)
Thanks @sdolan. Encountered the same problem as hekevintran. Switched to django-nose and it fixed that issue, also works much better than the default Django test runner.Huarache
This runs a test, but how to run an entire TestCase?Bakelite
@jMyles: another.test:TestCaseFlosi
Attention people like me who blindly paste from Stackoverflow: This will error without the mentioned plugin, use the syntax described in the other answer (. instead of :) which works in Django 1.6+.Jolandajolanta
i downvoted this answer because it actually doesn't answer the OP's question, which was how to do this in Django. Rather, it just suggests to switch to NosetestToxoid
Another cool (and shorter) way with nose is to use nose.plugins.attrib decorator to tag your tests like so: @attr("test-me") you can then tell the test runner to only run tagged tests: manage.py test -a test-meCastellan
nose is deprecated and use of django-nose is no longer recommended. for an answer using unittest, use -k, as noted here: https://mcmap.net/q/109538/-running-a-specific-test-case-in-django-when-your-app-has-a-tests-directoryDowntrodden
B
264

Since Django 1.6 you can run a complete test case, or single test, using the complete dot notation for the element you want to run.

Automatic test discovery will now find tests in any file that starts with test under the working directory, so addressing the question you would have to rename your files, but you can now keep them inside the directory you want. If you want to use custom file names you can specify a pattern (default Django test runner) with the option flag --pattern="my_pattern_*.py".

So if you are in your manage.py directory and want to run the test test_a inside TestCase subclass A inside a file tests.py under the app/module example you would do:

python manage.py test example.tests.A.test_a

If you don't want to include a dependency and are in Django 1.6 or later that's how you do it.

See the Django documentation for more information

Bloodshot answered 24/2, 2014 at 10:46 Comment(1)
I can't get this to work at all: error: option --pattern not recognized and invalid command nameSignpost
F
194

Check out django-nose. This allows you to specify tests to run like:

python manage.py test another.test:TestCase.test_method

or as noted in comments, use the syntax:

python manage.py test another.test.TestCase.test_method
Flosi answered 3/5, 2011 at 20:20 Comment(7)
Thanks @sdolan. Encountered the same problem as hekevintran. Switched to django-nose and it fixed that issue, also works much better than the default Django test runner.Huarache
This runs a test, but how to run an entire TestCase?Bakelite
@jMyles: another.test:TestCaseFlosi
Attention people like me who blindly paste from Stackoverflow: This will error without the mentioned plugin, use the syntax described in the other answer (. instead of :) which works in Django 1.6+.Jolandajolanta
i downvoted this answer because it actually doesn't answer the OP's question, which was how to do this in Django. Rather, it just suggests to switch to NosetestToxoid
Another cool (and shorter) way with nose is to use nose.plugins.attrib decorator to tag your tests like so: @attr("test-me") you can then tell the test runner to only run tagged tests: manage.py test -a test-meCastellan
nose is deprecated and use of django-nose is no longer recommended. for an answer using unittest, use -k, as noted here: https://mcmap.net/q/109538/-running-a-specific-test-case-in-django-when-your-app-has-a-tests-directoryDowntrodden
W
29

This should work-

python manage.py test my_app.tests.storage_tests
Web answered 12/5, 2017 at 6:58 Comment(0)
H
20

Use the -k flag to run a specific test by name without specifying the whole path:

./manage.py test animals.AnimalTestCase -k my_test_name

or just

./manage.py test -k my_test_name

(I know this wasn't the exact question but this page ranks high in a google search when I was trying to figure this out)

Hathcock answered 13/10, 2022 at 16:5 Comment(2)
works as of Nov 2022Bruis
Good to know it still works a month later lolHathcock
A
11

I was having this problem myself and found this question, in case anyone else comes along, here was what I dug up. The DjangoTestSuiteRuner uses a method called build_test(label) that figures out what test cases to run based on the label. Looking into this method it turns out they're doing a getattr() on either the "models" or "test" module. This means if you return a suite the test runner isn't looking for your test cases in that suite, it only looks in one of those modules.

A quick work-around is to use __init__.py to import your tests directly instead of defining a suite. The makes them part of the "test" module and so build_test(label) can find them.

For your example above, tests/__init__.py should simply contain:

from field_tests import *
from storage_tests import *

This isn't very elegant and of course if you're trying to do something more complicated with your suite then this won't work, but it would for this case.

Assets answered 9/5, 2012 at 18:12 Comment(0)
T
4

I also ran into this problem and instead of using django-nose I followed this link here: http://www.pioverpi.net/2010/03/10/organizing-django-tests-into-folders/. You need to open you init.py and import your tests.

Ex in init.py: from unique_test_file import *

Tamberg answered 24/1, 2013 at 13:14 Comment(1)
your link is broken, please update your answer.Remission
P
4

Put this code in your __init__.py and it will import all test classes in the package and subpackages. This will allow you to run specific tests without manually importing every file.

import pkgutil
import unittest

for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
    module = loader.find_module(module_name).load_module(module_name)
    for name in dir(module):
        obj = getattr(module, name)
        if isinstance(obj, type) and issubclass(obj, unittest.case.TestCase):
            exec ('%s = obj' % obj.__name__)

Similarly, for your test suite you can simply use:

def suite():   
    return unittest.TestLoader().discover("appname.tests", pattern="*.py")

Now all you have to do for new tests is write them and make sure they are in the tests folder. No more tedious maintenance of the imports!

Publicness answered 13/3, 2013 at 22:22 Comment(0)
W
4

If you want to run a test case class which has the path <module_name>/tests/test_views.py, you can run the command python manage.py test <module_name>.tests.test_views.<test_case_name>.

Wolfsbane answered 31/3, 2021 at 4:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.