Skip to main content

Test a Django endpoint's public and private responses

2026-11-11 16:36:25.089184+00:00
Test a Django endpoint's public and private responses

A permission test that checks only "200 OK" can miss a sensitive field added to an otherwise public response. Verify the exact shape and contents that each audience is allowed to receive.

Each audience has an independently tested response-field contract.

Write a response matrix

Assume a toy project-detail endpoint deliberately exposes only id and title publicly. Its owner response may also contain internal_notes. Other authenticated users receive the public representation.

from django.test import TestCase

class ProjectVisibilityTests(TestCase):
    def test_public_payload_omits_private_notes(self):
        project = make_project(
            title="Fixture project",
            internal_notes="private fixture marker",
        )
        response = self.client.get(f"/api/projects/{project.pk}/")
        self.assertEqual(response.status_code, 200)
        payload = response.json()
        self.assertEqual(set(payload), {"id", "title"})
        self.assertNotIn("private fixture marker", response.content.decode())

    def test_owner_payload_contains_expected_notes(self):
        owner = make_user()
        project = make_project(owner=owner, internal_notes="owner-only")
        self.client.force_login(owner)
        response = self.client.get(f"/api/projects/{project.pk}/")
        self.assertEqual(response.json()["internal_notes"], "owner-only")

When the public and owner serializers differ, include a regression fixture for newly added model fields so private defaults cannot silently enter the public representation. The factories above are application-specific fixtures, not built-in Django functions. Implement them using the toy application's real model fields and include the corresponding endpoint implementation.

Exact key assertions are useful when accidental extra fields are a meaningful regression. They are less suitable for APIs designed to add harmless fields freely. Choose the strictness from the sensitivity of the representation, not from a universal testing preference.

Test the other user's path

Create a second user, authenticate as that user and request the owner's project. Confirm the expected public representation or denial, according to the product policy. Check list endpoints too: a detail-only rule does not prove a public list serializer excludes private data.

Repeat the checks for update and delete operations if they exist. A response can conceal internal_notes while still accepting a write to that field. Read and write permissions need separate assertions.

Keep a recognizable synthetic secret marker in the fixture so nested objects and error responses can also be searched for leaks. Avoid using real customer data to make a test feel realistic.

Authentication helpers intentionally bypass parts of a real login flow. They are useful for authorization tests, but they do not establish that cookies, CSRF settings or session expiry work in a deployed browser.

The Nirogidhara case study offers related role-sensitive application context. Django's testing tools describe the client and login helpers.