Testing Django

Testing in Django means writing automated checks that confirm your application behaves correctly — using the built-in TestCase class, which spins up a temporary database, lets you create test data, and provides a test Client to simulate requests so you can assert that models, views, and forms work as expected.

Learn Testing Django in our free Django course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Django course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll write your first test cases, exercise views through the test Client, run the suite with manage.py, and learn how Django isolates every test inside its own throwaway database.

Django's testing tools live in django.test . The workhorse is django.test.TestCase , which subclasses Python's built-in unittest.TestCase . That inheritance means every familiar assertion — assertEqual , assertTrue , assertFalse — is available, plus web-specific ones like assertContains .

A test class groups related checks. Each method whose name starts with test_ is run automatically. The special setUp method runs before every test method , so it's the perfect place to create the data each test needs.

Here is what a real Django model test looks like. It creates a Post in setUp and checks that the model's string representation returns its title:

The example below runs the same API using Python's real unittest module — which Django's TestCase is built on — so you can watch setUp and the assertions execute right here in the editor.

Every Django TestCase gives you a ready-made test Client at self.client . It simulates a browser without starting a real server: you call self.client.get(url) and get back a response object you can inspect — its status_code , its rendered content, and which template produced it.

Always build the URL with reverse() instead of hard-coding a path, so your tests keep working even if you rename a route. Useful response checks include:

The runnable version below models a minimal "client" and "view" in plain Python so you can see how a response's status code and body are asserted — exactly the pattern Django uses.

You run your whole suite with one command. Django discovers every file named tests.py (or any module inside a tests/ package), creates a fresh test database , runs the tests, prints the results, and tears the database down again.

Forms are great to test because they hold validation rules. You build a form with a data dictionary and assert whether it is valid. Here is a real Django form test:

The runnable example below recreates that validation logic in plain Python so you can see is_valid being asserted both ways:

Fill in the blank with the assertion method that checks two values are equal, so the test passes.

Test methods must start with the prefix test_ . A method named check_title is invisible to the test runner.

✅ Fix: rename it to test_check_title so Django discovers and runs it.

Tests run against a brand-new, empty test database — not your real one. Objects you created in development do not exist.

✅ Fix: create everything a test needs inside setUp or the test method itself.

You hard-coded a path or passed the wrong name to reverse() , so the URL can't be resolved.

✅ Fix: use reverse("the_named_url") with the exact name from your URLconf.

Write a test class with setUp and two test_ methods that verify a discount function. Use assertEqual and assertTrue just like a Django TestCase would.

Lesson 23 complete — your code now has a safety net!

You can write tests with TestCase and setUp , assert with assertEqual , assertTrue , and assertContains , exercise views through self.client , run everything with python manage.py test against an isolated test database, and validate forms with is_valid() .

🚀 Up next: Capstone: A Blog App — put every skill together and build a complete, tested Django blog from scratch.

Practice quiz

Which class does Django's django.test.TestCase build on?

  • pytest.TestCase
  • django.db.Model
  • Python's unittest.TestCase
  • django.views.View

Answer: Python's unittest.TestCase. Django's TestCase subclasses Python's unittest.TestCase, so all its assertions are available.

When does the setUp method run?

  • Before every test method in the class
  • Once before the whole class
  • Only after a test fails
  • Once at the end of the run

Answer: Before every test method in the class. setUp runs before each test_ method, making it the place to build fresh fixtures.

Which prefix must a method name have for the test runner to discover it?

  • check_
  • test_
  • assert_
  • run_

Answer: test_. Only methods whose names start with test_ are run automatically.

What does self.client provide in a Django TestCase?

  • A database connection
  • A reference to the current request
  • A logging handler
  • A test Client that simulates requests without a running server

Answer: A test Client that simulates requests without a running server. self.client is a test Client you use like self.client.get(url) to exercise views.

Which assertion checks that a response body contains some text?

  • assertEqual(response, text)
  • assertContains(response, text)
  • assertBody(response, text)
  • assertIn(response, text)

Answer: assertContains(response, text). assertContains(response, text) passes when the rendered response includes that text.

Why use reverse() instead of hard-coding a path in a test?

  • The test keeps working even if you rename the route
  • It runs the test faster
  • reverse() creates the test database
  • Hard-coded paths are not allowed by Python

Answer: The test keeps working even if you rename the route. Building the URL by name with reverse() keeps tests working when paths change.

What does running python manage.py test do to the database?

  • It runs tests against your production database
  • It modifies your development data in place
  • It creates a fresh test database, runs tests, then destroys it
  • It requires you to create the test database by hand

Answer: It creates a fresh test database, runs tests, then destroys it. Django builds a throwaway test database, runs the suite, and tears it down afterward.

Which assertion verifies the expected template rendered a response?

  • assertEqual(response.template, name)
  • assertContains(response, name)
  • assertTemplate(name)
  • assertTemplateUsed(response, name)

Answer: assertTemplateUsed(response, name). assertTemplateUsed(response, name) confirms the named template produced the response.

How do you run only one test method from the command line?

  • Pass its dotted path, e.g. python manage.py test app.tests.MyTest.test_one
  • Pass --only test_one
  • You cannot — the whole suite always runs
  • Set RUN_SINGLE=True in settings

Answer: Pass its dotted path, e.g. python manage.py test app.tests.MyTest.test_one. A dotted path like app.tests.ClassName.test_method runs just that one test.

A test you wrote is silently skipped. What is the most likely cause?

  • assertEqual is misspelled
  • setUp raised an exception
  • The method name does not start with test_
  • The test database was not created

Answer: The method name does not start with test_. Methods that do not start with test_ are invisible to the runner and never execute.