Unittest and reusable app

Unittest and reusable app

Published July 19, 2015 in Development - Last update on July 18, 2015.

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

Post your comment

Comment as . Log out.