I decided to add some tests to my frisor application, so that my Travis CI could actually be useful. Testing web applications is very annoying for me, I’m not sure what I should test. There are some methods or views, which are really simple and I don’t feel it’s possible to write a meaningful test for them. Anyway, as I played more with tests in my side project frisor (more about it here: Introduction to frisor) here are some of my thoughts.
Where are my tests?
My requirements for testing framework were at least:
- tests are in
tests
subdirectory in my application - having more than one file with tests
- readable output with summary
In Django there is a builtin testing engine which does test discovery (so finds tests
locations) and runs tests. It uses unittest
library for running tests.
To run tests use manage.py
script with command test
. When none of your tests will be
found, there can be a few reasons of it:
Running manage.py from invalid location
If you are running manage.py
from invalid location, tests may not be run.
For example: I was running it from as $ python frisor/manage.py test
,
so not in place where manage.py
is located. There are two ways of fixing it:
- use your application name (but it tests only for this application),
in my case:
$ python frisor/manage.py test frisor_urls
- run
manage.py
when being in place where it is located, so:$ python manage.py test
Subdirectory for tests should be a python package
If you are using tests
subdirectory it’s possible that you forgot to make it
Python package - this subdirectory has to contain __init__.py
file as it defines a package.
Tests have a naming convention
All tests names should start from test_
prefix to be found. If there are no tests
found, check if they are named properly and if your test class
derives from django.test.TestCase
How to do something for all tests in class?
Let’s say we want to have a default variables or do some actions before for each test,
for example I wanted to use the same url for POST requests in all tests
in my AddUrlViewTest
:
It can be done using two strategies:
- running some method before each test
- running some method before all tests (once)
Usually using the first one is better, because tests will be independent from each other. When using the second one approach, there might appear some dependency between tests - you should avoid it at all costs! When tests are dependent on each other, they can’t be run in parallel, they are also much harder to debug.
Doing something before each test
Implementing setUp
method can help you set up variables before each test,
so before every test you can have a fresh instance of variables - setUp
method
is run before each test.
Here I added setUp
method where I define url_add_url
variable. I can use
it in all my tests to create a POST request to that url. It will be easy to change
it in the future.
Of course there is also a method which runs after each test, it’s
called tearDown
.
Doing something before all tests
Sometimes you want to do something before all tests in your test class.
For example I wanted to create some urls for testing list view of urls
in my UrlView
.
To achieve this it’s enough to implement setUpClass
method, but you have to remember
it’s a classmethod
, not an instance method. It will be run before class
instance creation. For example:
In example above I’m creating some urls before running other tests in
my application.
Method tearDownClass
is run after all tests in test class are run.
There are also similar methods for whole modules (setUpModule
and tearDownModule
).
You can find my tests in my frisor github: firsor tests.
Leave a Comment