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 Django test runner requires that I put a suite() function in the __init__.py
file of my application's tests directory. That function returns the test cases that will run when I do
$ python manage.py test
I installed django-nose. When I try to run the tests with django-nose, 0 tests are run:
$ python manage.py test <app_name>
If I point directly at the test module, the tests are run:
$ python manage.py test my_project.apps.my_app.tests.storage_tests
Why does django-nose's test runner not find my tests? What must I do?
If you use django-nose you can use a simple selector:
from nose.selector import Selector
from nose.plugins import Plugin
import os
import django.test
class TestDiscoverySelector(Selector):
def wantDirectory(self, dirname):
parts = dirname.split(os.path.sep)
return 'my_app' in parts
def wantClass(self, cls):
return issubclass(cls, django.test.TestCase)
def wantFile(self, filename):
parts = filename.split(os.path.sep)
return 'test' in parts and filename.endswith('.py')
def wantModule(self, module):
parts = module.__name__.split('.')
return 'test' in parts
class TestDiscoveryPlugin(Plugin):
enabled = True
def configure(self, options, conf):
pass
def prepareTestLoader(self, loader):
loader.selector = TestDiscoverySelector(loader.config)
This is just an example implementation and you can make it more configurable or adjust it to your needs. To use it in your Django project just provide the following option in settigs.py
NOSE_PLUGINS = ['lorepo.utility.noseplugins.TestDiscoveryPlugin']
Wrong:
python manage.py test my_app.tests.storage_tests:TestCase.test_name
is in fact with slashes until the class name and with the extension of the file
Right:
python manage.py test my_app/tests/storage_tests.py:TestCase.test_name
nose will pick automatically, if you add test = True in the beginning of module and if your methods starts with test_
see how nose detects tests http://nose.readthedocs.io/en/latest/finding_tests.html
I have run into this same situation as well. Using the suite it will allow you to run all tests, or tests for an app, but not a specific test case or a specific test.
It's pretty hacky, but what I've done to get around this is instead of defining a suite in __init__.py
is to just import *
from all of the other test modules, it sucks but it works.
There are a few things that I do to help make sure that I don't end up clobbering test suites in other modules... have __all__
declared in each test modules so only the test names are imported with the * and keep pylint running I'm notified of class name redefinitions.
Having said that you should be able to get this to work without any ugly import *
crap... I do not use nose and django-nose...(which I intend to correct very soon)... since that is what you're doing it looks like you can do this to run all of the tests in your apps directory:
python manage.py test apps
or to run all of the tests for a single test module:
python manage.py test apps.my_app.tests.storage_tests
notice I did not include the project in the previous example... which seemed to work fine for me using nosetests and django-nose.
Also, to run a specific test suite you can do this:
python manage.py test apps.my_app.tests.storage_tests:TestCase
Or to run one specific test:
python manage.py test apps.my_app.tests.storage_tests:TestCase.test_name
To make nose realize where your apps are add these to the top of manage.py
import os, site
ROOT = os.path.dirname(os.path.abspath(__file__))
path = lambda *a: os.path.join(ROOT, *a)
site.addsitedir(path('apps'))
Since then you can use
python manage.py test my_app.tests.storage_tests:TestCase.test_name