[Django]-How to test single application (not project) in Django?

17đź‘Ť

âś…

It is possible to run a single app’s tests standalone, without creating a Django test project for that purpose. One way of doing so is by creating a runtests.py in your app’s root dir which setups Django settings and runs ./manage.py test your_app programmatically. One example of runtests.py is Django’s own: runtests.py (documentation).

Django’s own runtests.py is a good reference but I find it convoluted for most cases. Below are a couple of alternative examples:

👤Dário

13đź‘Ť

Writing this down because I don’t see it on here yet

From the docs

If your django structure looks something like this as it should:

Project dir/
    /myapp
    /myotherapp
    /myproject

Django allows you to execute test from only “myotherapp” by executing:

./manage.py test myotherapp/

This will execute all test under “myotherapp” whereas

./manage.py test 

will execute all test in your projects directory.

👤Nick Brady

7đź‘Ť

If you use nose you can run a single app’s tests.

python manage.py test app.tests:TestClassHere

as for testing a single app. I just follow the convention other big django projects do, and that is exactly what you are doing. Create a test_project directory.

https://github.com/mozilla/django-piston/tree/master/tests/test_project

I figure if it is good enough for some of the biggest django pluggable apps it’s good enough for me.

👤dm03514

2đź‘Ť

Ofcourse you can test the Python parts with a standalone unittest if you don’t need any django dependencies

A Django environment requires atleast a settings.py and manage.py file. You can setup those with essential stuff only and UnitTest your app with manage.py. You should see a project as a Django runtime environment, there’s no Django without it. You can probably mimic settings but tbh you would just be creating more hacks than simplicity.

2đź‘Ť

You can also create a custom test runner and override the path it searches for tests in.

Perhaps I buried the lede here. I recently inherited a project that had legacy tests they wanted to keep for historical reasons, so I was forced to write all my tests in one folder and point to it

from django.test.runner import DiscoverRunner


class MyTestRunner(DiscoverRunner):
    
    def __init__(self, *args, **kwargs):
        kwargs.update({'top_level': str(settings.TEST_DISCOVER_TOP_LEVEL)})
        super().__init__(*args, **kwargs)

    def run_tests(self, test_labels, extra_tests=None, **kwargs):
        # In order to override the top_level directory, the test_label must match the top_level
        kwargs.update({'test_labels': [str(settings.TEST_DISCOVER_TOP_LEVEL)]})
        return super().run_tests(extra_tests=extra_tests, **kwargs)

and in your settings

TEST_RUNNER = 'path.to.my.module.MyTestRunner'

TEST_DISCOVER_TOP_LEVEL = BASE_DIR / 'tests/unit_and_integration_tests'
👤Dr Manhattan

Leave a comment