Django Test Runner

  1. Django Test Runner Pytest
  2. Django Test Db
  3. Django Test Runner Settings
  4. Django Test Runner Download

Testing is an important but often neglected part of any Django project. In this tutorial we'll review testing best practices and example code that can be applied to any Django app.

Broadly speaking there are two types of tests you need to run:

It will teach you how to build a SPA (single-page application) using React and Wagtail CMS. You will be able to: Understand Docker and use Docker Compose to do development. Build a REST API for Wagtail CMS. Use the Django shell to test code and check data. Test the REST API and generate test coverage report.

  • The best base class for most tests is django.test.TestCase. This test class creates a clean database before its tests are run, and runs every test function in its own transaction. The class also owns a test Client that you can use to simulate a user interacting with the code at the view level.
  • Commands in Django allow you to write scripts for your application that you can run from the command line, using manage.py. Recently, I needed to write unit tests for custom Django commands. This is the quick guide I wish I’d found first thing Why test custom commands?
  • Unit Tests are small, isolated, and focus on one specific function.
  • Integration Tests are aimed at mimicking user behavior and combine multiple pieces of code and functionality.

While we might we use a unit test to confirm that the homepage returns an HTTP status code of 200, an integration test might mimic the entire registration flow of a user.

For all tests the expectation is that the result is either expected, unexpected, or an error. An expected result would be a 200 response on the homepage, but we can--and should--also test that the homepage does not return something unexpected, like a 404 response. Anything else would be an error requiring further debugging.

The main focus of testing should be unit tests. You can't write too many of them. They are far easier to write, read, and debug than integration tests. They are also quite fast to run.

Complete source code is available on Github.

When to run tests

The short answer is all the time! Practically speaking, whenever code is pushed or pulled from a repo to a staging environment is ideal. A continuous integration service can perform this automatically. You should also re-run all tests when upgrading software packages, especially Django itself.

Layout

By default all new apps in a Django project come with a tests.py file. Any test within this file that starts with test_ will be run by Django's test runner. Make sure all test files start with test_.

As projects grow in complexity, it's recommended to delete this initial tests.py file and replace it with an app-level tests folder that contains individual tests files for each area of functionality.

For example:

Sample Project

Test

Let's create a small Django project from scratch and thoroughly test it. It will mimic the message board app from Chapter 4 of Django for Beginners.

On the command line run the following commands to start our new project. We'll place the code in a folder called testy on the Desktop, but you can locate the code anywhere you choose.

Now update settings.py to add our new pages app and configure Django to look for a project-level templates folder.

Create our two templates to test for a homepage and about page.

Populate the templates with the following simple code.

Update the project-level urls.py file to point to the pages app.

Pycharm django test runner

Create a urls.py file within the pages app.

Then update it as follows:

And as a final step add our views.

Start up the local Django server.

Then navigate to the homepage at http://127.0.0.1:8000/ and about page at http://127.0.0.1:8000/about to confirm everything is working.

Runner

Time for tests.

SimpleTestCase

Our Django application only has two static pages at the moment. There's no database involved which means we should use SimpleTestCase.

We can use the existing pages/tests.py file for our tests for now. Take a look at the code below which adds five tests for our homepage. First we test that it exists and returns a 200 HTTP status code. Then we confirm that it uses the url named home. We check that the template used is home.html, the HTML matches what we've typed so far, and even test that it does not contain incorrect HTML. It's always good to test both expected and unexpected behavior.

Now run the tests.

They should all pass.

As an exercise, see if you can add a class for AboutPageTests in this same file. It should have the same five tests but will need to be updated slightly. Run the test runner once complete. The correct code is below so try not to peak...

Message Board app

Now let's create our message board app so we can try testing out database queries. First create another app called posts.

Add it to our settings.py file.

Then run migrate to create our initial database.

Now add a basic model.

Django Test Runner Pytest

Django test runner custom

Create a database migration file and activate it.

For simplicity we can just a post via the Django admin. So first create a superuser account and fill in all prompts.

Update our admin.py file so the posts app is active in the Django admin.

Then restart the Django server with python manage.py runserver and login to the Django admin at http://127.0.0.1:8000/admin/. You should see the admin’s login screen:

Click on the link for + Add next to Posts. Enter in the simple text Hello world!.

On 'save' you'll see the following page.

Now add our views file.

Create a posts.html template file.

And add the code below to simply output all posts in the database.

Finally, we need to update our urls.py files. Start with the project-level one located at myproject/urls.py.

Then create a urls.py file in the posts app.

And populate it as follows.

Okay, phew! We're done. Start up the local server python manage.py runserver and navigate to our new message board page at http://127.0.0.1:8000/posts.

It simply displays our single post entry. Time for tests!

TestCase

TestCase is the most common class for writing tests in Django. It allows us to mock queries to the database.

Django Test Db

Let's test out our Post database model.

With TestCase the Django test runner will create a sample test database just for our tests. Here we've populated it with the text 'just a test'.

In the first test we confirm that the test entry has the primary id of 1 and the content matches. Then in the second test on the view we confirm that that it uses the url name posts, has a 200 HTTP response status code, contains the correct text, and uses the correct template.

Run the new test to confirm everything works.

Next Steps

There is far more testing-wise that can be added to a Django project. A short list includes:

Django Test Runner Settings

  • Continuous Integration: automatically run all tests whenever a new commit is made, which can be done using Github Actions or a service like Travis CI.
  • pytest: pytest is the most popular enhancement to Django and Python's built-in testing tools, allowing for more repeatable tests and a heavy use of fixtures.
  • coverage: With coverage.py you can have a rough overview of a project's total test coverage.
  • Integration tests: useful for testing the flow of a website, such as authentication or perhaps even payments that rely on a 3rd party.

Django Test Runner Download

I'm working on a future course on advanced Django testing so make sure to sign up for the LearnDjango newsletter below to be notified when it's ready.

Test

If you need more testing help now, an excellent course is Test-Driven Development with Django, Django REST Framework, and Docker by my friend Michael Herman.