As promised! Let’s dig in to how we run tests using Django.
We run a web server using apache where the code is written using Django. We put information regarding the state of the optmization worker jobs, advertiser/publisher data upload systems and such for other engineers and analysts to use.
How to run Django test suites per application:
We run Django tests separately on our testing framework. We run Django tests with the command:
1 | $ python path/to/manage.py test |
Django tests are documented at https://docs.djangoproject.com/en/dev/topics/testing/. The document tells you that if you have a Django application, we can put our tests in the application directory’s file named tests.py. Let’s name the application app1.
What they say:
1 2 3 4 | $ ls www app1 $ ls app1/ tests.py |
However, I don’t like this test organization. If we write many tests, the tests.py file will be huge. Also I want the filename to reflect which module is being tested.
What I want:
1 2 3 4 5 6 7 8 | $ ls www app1 $ ls app1/ some_files tests $ ls app1/tests/ views/ models/ $ ls app1/tests/views test_main_page.py |
You want to keep not only the tests but also the test organization as clean as possible.
How do we achieve this? It is actually a tough job to do, and I had to search quite a bit, but now it works!
1. Write your application. Have the application in the www directory (or Django root directory).
2. Create tests and place them in appropriate location where you think they belong. As in our example, we put them in app1/tests/views/test_main_page.py, app1/tests/models/test_model.py etc. Make sure that you have the Django unit test import statement in your test files as covered in the Django docs.
1 | import django.utils.unittest |
3. Add the application in the tuple INSTALLED_APPS in settings.py
4. In apache.django.wsgi add the Django main directory to the system path
1 | sys.path.append('/path/to/www/') |
5. Add __init__.py to app1/tests/, app1/tests/views/, app1/tests/models/, etc. to all the subdirectories so the tests can be referred as modules
6. Import the test classes from the test module you wrote in the app1/__init__.py by putting the following line:
1 2 | from www.app1.tests.views.test_main_page import TestModuleFunctions, TestMainPage |
7. app1/tests/views/__init__.py can be empty
8. To make the test easier by using in-memory db for testing functions, you must add the following code to settings.py for every db key used in the tests.
1 2 3 4 5 | if 'test' in sys.argv: DATABASES[db_key] = { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': test_db_name } |
Ok that is it! Now it should work by typing the command:
1 | python path/to/www/manage.py test app1 |
You can add the command to the Jenkins configuration.
I hope you enjoyed our blog entry and found it useful. Writing tests makes your code better. It is much easier to stub-out/mock aggregated objects than module objects. You take more care in designing your modules/classes/functions.