← Back to Django Course | Chapter 13: Testing in Django | Lesson 6 of 9

The Django Test Client

The test client is a pretend web browser that lives inside your tests, letting them visit pages without opening a real browser.

Accessing the test client

Every TestCase instance automatically has self.client, a Client object that can simulate GET and POST requests against your URLs.

Example: Accessing the test client

Every TestCase instance automatically has self.client, a Client object that can simulate GET and POST requests against your URLs.

markup
from django.test import TestCase


class ClientTests(TestCase):
    def test_client_exists(self):
        self.assertIsNotNone(self.client)
{# Django-only code -- models.py/views.py/urls.py/settings.py snippets, or template markup using Django template tags/variables -- can't run standalone via Judge0 or the browser preview, since it needs a real Django project. Only this course's pure-Python examples (example_lang == 'python', no Django imports) are actually runnable, so those still get the button below. #}

Simulating a POST request

client.post() takes the URL and a dictionary of form data, exactly like a real browser submitting a form.

Note: Match the dictionary keys to the form field name attributes exactly.

Example: Simulating a POST request

client.post() takes the URL and a dictionary of form data, exactly like a real browser submitting a form.

markup
def test_post_creates_object(self):
    response = self.client.post('/books/add/', {'title': 'New Book'})
    self.assertEqual(response.status_code, 302)
{# Django-only code -- models.py/views.py/urls.py/settings.py snippets, or template markup using Django template tags/variables -- can't run standalone via Judge0 or the browser preview, since it needs a real Django project. Only this course's pure-Python examples (example_lang == 'python', no Django imports) are actually runnable, so those still get the button below. #}

Logging in for protected views

client.login() simulates authentication, letting tests reach views wrapped in @login_required.

Example: Logging in for protected views

client.login() simulates authentication, letting tests reach views wrapped in @login_required.

markup
from django.contrib.auth.models import User


class ProtectedViewTests(TestCase):
    def setUp(self):
        self.user = User.objects.create_user('alice', password='pass123')

    def test_dashboard_requires_login(self):
        self.client.login(username='alice', password='pass123')
        response = self.client.get('/dashboard/')
        self.assertEqual(response.status_code, 200)
{# Django-only code -- models.py/views.py/urls.py/settings.py snippets, or template markup using Django template tags/variables -- can't run standalone via Judge0 or the browser preview, since it needs a real Django project. Only this course's pure-Python examples (example_lang == 'python', no Django imports) are actually runnable, so those still get the button below. #}
Common Mistakes
  1. Assuming self.client persists login across test methods — each test method gets a fresh, logged-out client.
  2. Sending POST data as a plain string instead of a dictionary, which the client cannot parse correctly.
  3. Forgetting to call self.client.login() before testing a view that requires authentication.
Chapter Summary
  • self.client is available automatically on any Django TestCase subclass.
  • client.get(url) and client.post(url, data_dict) simulate real HTTP requests.
  • client.login(username=..., password=...) simulates a logged-in session for protected views.
  • The client never touches the network — it calls your views directly through Django's request/response cycle.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.