← Zurück zum Blog
TestingDjango2. Juni 2026· 13 min Lesezeit

Django-Tests: Models, Views und Forms richtig testen

Inhalt
  1. TestCase & Datenbank
  2. Models testen
  3. Forms testen
  4. Views mit dem Test-Client
  5. Authentifizierte Views
  6. Tests schnell halten
  7. Fazit

Django bringt ein durchdachtes Test-Framework mit. Der Schlüssel zu einer guten Suite ist, jede Ebene — Models, Forms, Views — mit der passenden Strategie zu testen. Hier meine Vorgehensweise aus vielen Projekten.

TestCase & Datenbank

Djangos TestCase kapselt jeden Test in eine Transaktion, die danach zurückgerollt wird — so bleibt die Test-DB sauber. Für Tests ohne DB-Bedarf nimm das leichtere SimpleTestCase:

from django.test import TestCase, SimpleTestCase

class ReinerLogikTest(SimpleTestCase):
    """Kein DB-Zugriff -> schneller"""
    def test_slug(self):
        self.assertEqual(slugify("Mein Titel"), "mein-titel")

class MitDatenbankTest(TestCase):
    """Braucht DB -> TestCase"""
    def test_erstellung(self):
        obj = Article.objects.create(title="Test")
        self.assertEqual(Article.objects.count(), 1)

Models testen

Bei Models teste ich vor allem: eigene Methoden, Properties, save()-Logik, Constraints und Validierung — nicht die von Django selbst bereitgestellten Felder.

class ArticleModelTest(TestCase):
    def test_str(self):
        a = Article(title="Hallo Welt")
        self.assertEqual(str(a), "Hallo Welt")

    def test_publish_setzt_datum(self):
        a = Article.objects.create(title="X", status="draft")
        a.publish()
        self.assertEqual(a.status, "published")
        self.assertIsNotNone(a.published_at)

    def test_slug_wird_generiert(self):
        a = Article.objects.create(title="Mein Artikel")
        self.assertEqual(a.slug, "mein-artikel")

Forms testen

Forms sind dankbar zu testen: Eingabe rein, is_valid() prüfen, Fehler kontrollieren. Kein Test-Client nötig.

from myapp.forms import ContactForm

class ContactFormTest(TestCase):
    def test_gueltig(self):
        form = ContactForm(data={
            "name": "Eugen", "email": "e@example.com", "message": "Hallo"
        })
        self.assertTrue(form.is_valid())

    def test_email_pflicht(self):
        form = ContactForm(data={"name": "Eugen", "message": "Hallo"})
        self.assertFalse(form.is_valid())
        self.assertIn("email", form.errors)

Views mit dem Test-Client

Der Test-Client simuliert HTTP-Requests, ohne einen echten Server zu starten:

class ArticleViewTest(TestCase):
    def setUp(self):
        self.article = Article.objects.create(title="Test", status="published")

    def test_liste_erreichbar(self):
        response = self.client.get("/articles/")
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Test")

    def test_detail_404_bei_draft(self):
        draft = Article.objects.create(title="Entwurf", status="draft")
        response = self.client.get(f"/articles/{draft.slug}/")
        self.assertEqual(response.status_code, 404)

Authentifizierte Views

from django.contrib.auth import get_user_model

class GeschuetzteViewTest(TestCase):
    def setUp(self):
        User = get_user_model()
        self.user = User.objects.create_user("tester", password="geheim123")

    def test_redirect_ohne_login(self):
        response = self.client.get("/dashboard/")
        self.assertEqual(response.status_code, 302)  # Redirect zum Login

    def test_zugriff_mit_login(self):
        self.client.login(username="tester", password="geheim123")
        response = self.client.get("/dashboard/")
        self.assertEqual(response.status_code, 200)

Tests schnell halten

# settings/test.py
PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"]

# setUpTestData: einmal pro Testklasse
class ArticleTest(TestCase):
    @classmethod
    def setUpTestData(cls):
        cls.author = User.objects.create_user("autor")

Fazit

Jede Django-Ebene hat ihre Teststrategie: Models über ihre Methoden, Forms über Validierung, Views über den Test-Client. Wer SimpleTestCase, setUpTestData und schnelle Hasher nutzt, hält die Suite auch bei hunderten Tests flott. Das ist die Grundlage, auf der sich ein Projekt angstfrei weiterentwickeln lässt.

Yevhen Chubchyk
Yevhen Chubchyk
Senior Python / Django Entwickler · Freelancer seit 2016 · 20+ Jahre IT-Erfahrung. Baut testgetriebene Backend-Systeme für Kunden im DACH-Raum.