Django provides many testing tools; in this tutorial we'll use some of them to test an app with a custom user model and authentication.
We'll test the app userauth
that we have created in an earlier tutorial. It features a custom user model and authentication with allauth. The command to run tests for a specific app or directory is:
The argument test
is comparable to other arguments that Django uses, such as runserver
, createsuperuser
, migrate
etc. You might get the following error:
That's because Django will create a test database, that will be destroyed when all the tests have been executed. So you need to give the database user the permission to create this test database. Go to the psql
command prompt:
and type in the following command:
where usr_pet
is your database user. Leave psql
with \q
.
Another error that might occur is:
or something similar. This is due to the use of ManifestStaticFilesStorage
in the parameter STATICFILES_STORAGE
in our settings. Django recommends to set this parameter to its default during testing, so comment out the line in your settings where this parameter is defined.
Now if we run python3 manage.py test userauth
, Django will tell you how many tests were executed and display any errors. Even with no tests we can still run the test command; Django will go through setup and do some more things, so will return OK or detect errors if it found any.
There are many ways of testing and many articles on the limitations of it. Two popular testing methods are coverage testing (e.g. with Coverage) and browser automation (e.g. with Selenium). Here we will limit ourselves to coverage testing, which can be easily integrated with Django. Install the package:
Add it to requirements.txt
and add coverage
to INSTALLED_APPS
. Run it with:
The flag source
tells coverage only to measure the code in the directory userauth
, and the userauth
and the end of the command tells Django only to execute tests in the app userauth
. The subsequent command
creates a directory htmlcov
in the project directory with a file index.html
in it. Right click it and choose open in browser.
For our app userauth
we see that a substantial portion of the code is already visited, even without tests. That's because in our app we have made maximum use of Django's and allauth's built-in classes and methods. Let's create some tests for the pieces of code that were not covered, starting with a simple one: the string representation of the custom user model. Recapping from our earlier tutorial on our customer user model:
We will use Django's class Testcase
. First we create a user in our set up with setUpTestData
, then we test with assertEqual
whether the string representation is what it should be:
Running coverage again will reveal that we have now covered that piece of code. This is of course a very simple example. Let's test the get_absolute_url
method of our model. Again from our earlier tutorial:
with the following in our urls.py
:
and in our views.py
:
A call to profile_view
with a logged in user should give a valid response. The Django docs describe how to simulate a user login using RequestFactory
, which generates a request
object. We import RequestFactory
and profile_view
:
In our setUpTestData
we add the line:
and then our test is (using the HttpResponse
attribute status_code
):
Our final test for userauth
will be on LoginForm
in forms.py
. Define a second user in setUpTestData
:
We cannot reuse the first user, because the tests are not necessarily run in the order they are defined, which means that changes in one test could affect reused variables in another. Define some form data, feed it to SignupForm
, and use the form's signup
method on the newly created user to check whether the method does what it's supposed to do:
Running coverage again shows that we have covered more than 95% of the code of userauth
and that only some straightforward code lines are missing. We leave the testing of this app and move on to the next.
Comment on this article (sign in first or confirm by name and email below)