You had fun, you wrote a Django third app. You should have write unittests before but you didn't know where to place them. For my case when I wrote Django Admin CLI I used the work made in Django Comments, let's explain it a little.
All testing code are stored in tests/ directory at root of project. in fact, this is a light Django project (as created with django-admin.py startproject) with inside a testapp (as created by django-admin.py startapp). Instead of settings.py, wsgi.py, urls.py and etc, there is one file which make all project's base code and launch tests. This file is generaly named runtests.py, you can see an example below:
#!/usr/bin/env python
import os
import sys
import django
from django.conf import settings
here = os.path.dirname(os.path.abspath(__file__))
parent = os.path.dirname(here)
sys.path[0:0] = [here, parent]
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_ROOT = os.path.join(BASE_DIR, 'tests/media')
INSTALLED_APPS = (
'testapp',
'my3rdApp',
)
settings.configure(
MEDIA_ROOT=MEDIA_ROOT,
MIDDLEWARE_CLASSES=(),
CACHES={'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}},
INSTALLED_APPS=INSTALLED_APPS,
DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}},
ROOT_URLCONF='testapp.urls',
SECRET_KEY="it's a secret to everyone",
SITE_ID=1,
)
def main():
if django.VERSION >= (1, 7):
django.setup()
from django.test.runner import DiscoverRunner
runner = DiscoverRunner(failfast=True, verbosity=int(os.environ.get('DJANGO_DEBUG', 1)))
failures = runner.run_tests(['testapp'], interactive=True)
sys.exit(failures)
if __name__ == '__main__':
main()
The testapp contains all the things you need for tests: models, migrations, admin, form or whatever you want. It also contains tests.py or tests/ folder with classical Django testing.
For follow setuptools usage, you add the following parameters in your setup.py:
from setuptools import setup, find_packages
setup(
...
packages=find_packages(exclude=['tests.runtests.main']),
test_suite='tests.runtests.main',
...
)
This will exclude tests from packaging and allow user to launch tests with a simple:
python setup.py test
All is done. If you don't understand everything, I invite you to comment or read repositories' code which use this method:
Comments