How to spread django unit tests over multiple files?
DjangoUnit TestingDjango 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