How to spread django unit tests over multiple files?

DjangoUnit Testing

Django Problem Overview


  • I have a python-django application
  • I'm using the unit testing framework
  • The tests are arranged in the file "tests.py" in the module directory
  • I'm running the tests via ./manage.py test app

Now..

  • The tests.py file is getting rather large/complex/messy
  • I'd like to break tests.py up into smaller collections of tests...

How?

Django Solutions


Solution 1 - Django

Note that this approach is no longer valid from Django 1.6, see this post.

You can create tests folder with ___init___.py inside (so that it becomes a package). Then you add your split test .py files there and import all of them in ___init___.py.

I.e: Substitute the test.py file with a module that looks and acts like the file:

Create a tests Directory under the app in question

app
app\models.py
app\views.py
app\tests
app\tests_init_.py
app\tests\bananas.py
app\tests\apples.py

Import the submodules into app\tests\__init__.py:

from bananas import *
from apples import *

Now you can use ./manage.py as if they were all in a single file:

./manage.py test app.some_test_in_bananas

Solution 2 - Django

The behavior has changed in Django 1.6, so there is no longer a need to create a package. Just name your files test*.py.

From Django 1.7 documentation > When you run your tests, the default behavior of the test utility is > to find all the test cases (that is, subclasses of unittest.TestCase) > in any file whose name begins with test, automatically build a test > suite out of those test cases, and run that suite.

From Django 1.6 documentation, > Test discovery is based on the unittest module’s built-in test > discovery. By default, this will discover tests in any file named > “test*.py” under the current working directory.

Previous behavior, from Django 1.5 documentation: > When you run your tests, the default behavior of the test utility is > to find all the test cases (that is, subclasses of unittest.TestCase) > in models.py and tests.py, automatically build a test suite out of > those test cases, and run that suite. > > There is a second way to define the test suite for a module: if you > define a function called suite() in either models.py or tests.py, the > Django test runner will use that function to construct the test suite > for that module. This follows the suggested organization for unit > tests. See the Python documentation for more details on how to > construct a complex test suite.

Solution 3 - Django

The answer as stated by Tomasz is correct. However, it can become tedious to ensure that the imports in __init__.py match your file structure.

To automatically detect all tests in the folder you can add this in __init__.py:

import unittest

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

This will allow you to run ./manage.py test appname but won't handle running specific tests. To do that you can use this code (also in __init__.py):

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__)

Now you can run all your tests via manage.py test app or specific ones via manage.py test app.TestApples

Solution 4 - Django

Just make your directory structure like this:

myapp/
    __init__.py
    tests/
        __init__.py
        test_one.py
        test_two.py
        ...
    ...

And python manage.py test myapp will work as expected.

Solution 5 - Django

http://docs.python.org/library/unittest.html#organizing-tests talks about splitting the files into modules, and the section right above it has an example.

Solution 6 - Django

With Django 2.2 a simple and fairly good solution could be to create a test folder inside an app, and you can put your related test_...py files into, just add __init__.py to the test folder.

Solution 7 - Django

No need to code anything in init. Just create a subdirectory in your app. Only requirement is not to call it tests* For exemple

app/
app/__init_.py
app/serializers.py
app/testing/
app/testing/__init__.py
app/testing/tests_serializers.py

Solution 8 - Django

If you have a more complicated setup, or don't want to use from ... import *-type statements, you can define a function called suite in your tests.py (or tests/_init_.py), which returns an instance of unittest.TestSuite.

Solution 9 - Django

I have two files. One is tests.py and another is test_api.py. I can run these individually as below.

manage.py test companies.tests
manage.py test companies.test_api

Refer @osa's response about file naming convention.

Solution 10 - Django

I think ./manage.py test simply does running all the tests trick (in django >= 1.7).

If your organizing tests is about grouping and cherrypicking and you are fan of nose use django nose:

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

If you know nose, then you know how to "wildcard" much nicer over all your files.

PS

It is just a better practice. Hope that helps. The answer was borrowed from here: https://stackoverflow.com/questions/5875111/running-a-specific-test-case-in-django-when-your-app-has-a-tests-directory

Solution 11 - Django

In django you can use below comman or can check documentation. Also using this command will pick up files with pattern you provide not just test*.py or test_*.py.

> Documentation
You can specify a custom filename pattern match using the -p (or --pattern) option, if your test files are named differently from the test*.py pattern:

$ ./manage.py test --pattern="tests_*.py"

Solution 12 - Django

Just create different test files with tests_name in your app

Say you have following test files:

tests_admins.py
tests_staff.py
tests_others.py
# will run both test files
(venv)..yourapp$./manage.py test --keepdb -v 2 appname

Solution 13 - Django

Or in Windows, if you do not want to create a package (i.e folder with __init__.py) and just want to create a folder called "Tests" and this folder contains the test files then to run tests in cmd just enter

python manage.py test your_app_name/Tests

Since a path is expected

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJohn MeeView Question on Stackoverflow
Solution 1 - DjangoTomasz ZielińskiView Answer on Stackoverflow
Solution 2 - DjangoSergey OrshanskiyView Answer on Stackoverflow
Solution 3 - DjangoBryce DrennanView Answer on Stackoverflow
Solution 4 - DjangospiderlamaView Answer on Stackoverflow
Solution 5 - DjangoJim DevilleView Answer on Stackoverflow
Solution 6 - DjangoGaborView Answer on Stackoverflow
Solution 7 - DjangoMaxBlax360View Answer on Stackoverflow
Solution 8 - DjangoJoel CrossView Answer on Stackoverflow
Solution 9 - DjangoktaView Answer on Stackoverflow
Solution 10 - DjangoYauhen YakimovichView Answer on Stackoverflow
Solution 11 - DjangoHimanshu PatelView Answer on Stackoverflow
Solution 12 - Django7guyoView Answer on Stackoverflow
Solution 13 - DjangoAtul TripathiView Answer on Stackoverflow