run every TestCase inside a module - django

How can you run tests from all TestCase classes, in a specific module under tests package?
In a Django project, I have split tests.py under tests/
Each file(module) has several TestCase classes, and each of them having several test methods.
init.py imports each of them.
I already know that I can do these:
Run all the test:
./manage.py test myapp
Or run specific TestCase:
./manage.py test myapp.OneOfManyTestCase
Or run very specific test method from a TestCase class:
./manage.py test myapp.OneOfManyTestCase.test_some_small_method
However, I can't figure out how to run every TestCases from a particular module.
Say, OneOfManyTestCase class is from tests/lot_of_test.py, and there are other test cases too.
Django doesn't seem to care about modules with TestCases.
How can I run all the TestCases inside lot_of_test?

I think to achieve this you need to subclass your own TestRunner from DjangoTestSuiteRunner and override build_suite method.

I ended up writing down my own TestSuiteRunner, like #sneawo said.
After Django-style fails, try importing as usual python-style.
One line to fix:
suite.addTest(build_test(label))
into
try:
suite.addTest(django.test.simple.build_test(label))
except ValueError:
# change to python-style package name
head, tail = label.split('.', 1)
full_label = '.'.join([head, django.test.simple.TEST_MODULE, tail])
# load tests
tests = unittest.defaultTestLoader.loadTestsFromName(full_label)
suite.addTests(tests)
and set TEST_RUNNER in settings.py:
TEST_RUNNER='myapp.tests.module_test_suite_runner.ModuleTestSuiteRunner'

Related

Overriding TEST_RUNNER with #override_settings

In order to run my tests faster I created a no db test runner as in this answer. Then I needed to set the TEST_RUNNER settings variable to my new test runner but only for certain tests. To achieve this, I tried using django.test.utils.override_settings decorator like this (as in the docs):
from django.test import TestCase
from django.test.utils import override_settings
class MyTestCase(TestCase):
#override_settings(TEST_RUNNER='path_to_my_no_db_test_runner')
def test_my_test_case(self):
...
The problem is that when I run this test, django will still create the database, which is not the expected behavior of course. The curious thing is that if I set the TEST_RUNNER directly in my settings.py it works perfectly, but with django.test.utils.override_settings it seems to have no effect. I also tried using this override_settings module but got the same results.
What am I dping wrong? Is there any other way of achieving this? I'd rather not to create a test_settings.py and run my tests with --settings argument.
Put this piece of code in your config :
TESTING = 'test' in sys.argv
...
if TESTING:
TEST_RUNNER = 'path_to_my_no_db_test_runner'
DATABASES = {}
The TESTING setting will be defined only when you run tests, you can then dynamically change some settings including your DB, migrations, test runners...
It will be loaded at the very beginning of Django initialisation therefore if you override DATABASES no DBs will be created.

Testing backend code in Django

I am writing an authentication back-end in Django to log only a few users.
It is in a folder called restrictedauthentification/ which is at the root of my Django Project. (I am written it down for a specific project.)
It has two files in it : backend.py and tests.py
In the last file, I have written down some tests for it.
But I can't run them with command ./manage.py test because it isn't an installed app.
Any ideas how I could run them ?
Okay, I found a solution that keep me from turning my backend into a module.
Somthing that I didn't understand and that could help some beginners : In python, a test cannot run itself. It need to be executed by a TestRunner.
Now, one could use the TextTestRunner bundled python that execute the tests and show the results on the standard output, but when testing with django, one need to do one thing before and after the test: calling the function setup_test_environment() and teardown_test_environment().
So I just created a class that inherit from TextTestRunner and redefine its methode run() in order that it execute the two functions provided by Django.
Here it is :
from restrictedauthentification.tests import TestRestrictedAuthentification
from django.test.utils import setup_test_environment, teardown_test_environment
from unittest import TextTestRunner
class DeadSimpleDjangoTestRunner(TextTestRunner):
def run(self, test):
setup_test_environment()
super().run(test)
teardown_test_environment()

How to run a single test or single TestCase with django-nose?

With Django's normal test runner, you can drill down to run tests in a specific app, a specific subclass of TestCase, or a specific test within a specific subclass of TestCase.
E.g.:
./manage.py test myapp.MyTestCase.test_something
However, django-nose doesn't appear to support anything beyond testing a specific app. How do I replicate the last two behaviors?
Nose supports the following syntax (note : between test script name and test class name):
./manage.py test myapp.tests.test_script:MyTestCase.test_method
The correct answer is ./manage.py test myapp/tests/test_script:MyTestCase.test_method.
Using dots in the relative path did not work for me, but slashes did.

Custom test suite for django app

I have a pretty complex django app which has following structure.
/myapp
/myapp/obj1/..
/myapp/obj1/views.py
/myapp/obj1/forms.py
/myapp/obj2/..
/myapp/obj2/views.py
/myapp/obj2/forms.py
/myapp/tests/..
/myapp/tests/__init__.py
/myapp/tests/test_obj1.py
/myapp/tests/test_obj2.py
I have a lot more objects. In /myapp/tests/__init__.py I import TestCase instances from test_obj1.py and test_obj2.py and it is enough to run all available test.
What I'm trying to do is to create a custom test suite. According to the documentation:
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.
So, i've created this function like this:
def suite():
suite = unittest.TestSuite()
suite.addTest(TestObj1Form())
suite.addTest(TestObj2Form())
return suite
However, when I run tests I get this error: ValueError: no such test method in <class 'myproject.myapp.tests.test_obj1.TestObj1Form'>: runTest. Of course I can define this method, but then if I run test it will invoke only this method and ignore all of the test* methods.
Any suggestions how to create a custom test suite for django app properly? I've googled and I found nothing about that.
You should add all your tests with a special function:
suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestObj1Form))

Django ignoring fixtures when run from tests

I have a simple class in a Django app called "project"
from django.test import TestCase
class ProjectTest(TestCase):
"""Unit tests for the "Project" app """
fixtures = ['test_data.json', ]
def setUp(self):
pass
def testTotalAmountOfWhuffie(self):
"""Tests that the calculation to find the total amount of Whuffie allocated is correct."""
pass
if __name__ == '__main__':
unittest.main()
and when I run
manage.py test project
it completely ignores the fixtures. If I rename the file to initial_data.json it gets picked up by the test runner, so I'm sure the directory structure is right.
If I increase the verbosity of the test runs, they don't even look for the fixtures that I specify, I can even go as far as specifying the full path to the file, and they don't get loaded.
If 'test_data.json' is under project/fixtures, then I can't see any problem with what you have got. Try using the fixture data in a test.
"it completely ignores the fixtures"
How do you know this?
"If I rename the file to initial_data.json it gets picked up by the test runner"
This is only picked up because the test runner runs syncdb. See http://docs.djangoproject.com/en/dev/howto/initial-data/#automatically-loading-initial-data-fixtures
"If I increase the verbosity of the test runs, they don't even look for the fixtures that I specify,"
How can you be sure? I ran my tests with the verbosity set to 3, and the test runner did not mention my fixtures at all. (The tests work)
I even tried using a non-existent fixture in the test. Again, the test runner did not mention any problem.