Wanneer je een Django-app maakt, wordt er automatisch een tests.py aangemaakt.
De meeste ontwikkelaars denken daar op een gegeven moment over na.
“Kan ik dit bestand… verwijderen?”
“Hoe moet ik het eigenlijk gebruiken?”
Eigenlijk is tests.py het officieel aanbevolen testpunt door Django, en,
als je er een beetje aan gewend raakt, biedt het echt een grote verzekering bij refactoren, het toevoegen van functies en upgrades. (Django Project)
In dit artikel bespreken we:
-
Wat het doel van
tests.pyis -
Hoe je het schrijft en uitvoert
-
In welke situaties het vooral nuttig is
-
Praktische voorbeelden
Alles in één overzicht.
1. Wat is tests.py voor een bestand?
Django maakt gebruik van het testframework gebaseerd op unittest van de Python standaardbibliotheek.
-
Je maakt testklassen die overerven van
django.test.TestCase, en -
schrijft methoden die beginnen met
test_ -
met het commando
./manage.py testworden ze automatisch gevonden en uitgevoerd.
Wanneer je een app aanmaakt met startapp, wordt er standaard een tests.py aangemaakt:
-
Kleine projecten → één
tests.pyis voldoende -
Bij grotere projecten → aanbevolen door Django om te splitsen in een
tests/-pakket (test_models.py,test_views.py, enz.)
Met andere woorden, het is te begrijpen als de basislocatie voor tests op app-niveau.
2. Wanneer is het nuttig? (Waarom zou je tests moeten gebruiken?)
Django-tests komen vooral tot hun recht in de volgende situaties.
-
Validatie van modellen/businesslogica
-
Hoe ingewikkelder de rekenlogica, statuswijzigingen en aangepaste methoden zijn
-
Als je eenmaal een test hebt gemaakt, kun je erop vertrouwen dat je kunt refactoren bij toekomstige aanpassingen
-
-
Weergave/URL/toegangscontrole
-
Verandert de responscode afhankelijk van de authenticatie?
-
Maakt het correct een redirect / foutafhandeling voor onjuiste input?
-
Worden de benodigde contextgegevens voor de sjabloon correct overgedragen?
-
-
Voorkomen van regressiefouten
- Als je een fout eenmaal hebt vastgelegd, kun je die met tests vastleggen, zodat hetzelfde probleem zich niet opnieuw voordoet
-
Beveiligen van stabiliteit tijdens upgrades
-
Wanneer je de versie van Django of een bibliotheek verhoogt
-
kun je een
./manage.py testdraaien om te controleren voordat je verder gaat
-
3. De meest basale tests.py voorbeeld
3-1. Modeltest
# myapp/tests.py
from django.test import TestCase
from .models import Article
class ArticleModelTests(TestCase):
def setUp(self):
self.article = Article.objects.create(
title="Testtitel",
content="Inhoud",
views=0,
)
def test_increase_views(self):
# gegeven
self.assertEqual(self.article.views, 0)
# wanneer
self.article.increase_views()
# dan
self.assertEqual(self.article.views, 1)
-
TestCaseis een klasse voor Django dieunittest.TestCaseuitbreidt. -
Elke test is geïsoleerd per transactie, waardoor de database bij elke test wordt teruggedraaid, zodat ze elkaar niet beïnvloeden.
4. Hoe test je weergave/URL – gebruik van Client
Django biedt een HTTP-client voor testdoeleinden, django.test.Client.
Je kunt GET/POST verzoeken naar een URL sturen en de reacties controleren zonder een echte server te draaien.
4-1. Eenvoudige weergavetest
# myapp/tests.py
from django.test import TestCase
from django.urls import reverse
from .models import Article
class ArticleViewTests(TestCase):
def setUp(self):
self.article = Article.objects.create(
title="Bericht 1",
content="Inhoud",
views=0,
)
def test_article_detail_page_returns_200(self):
url = reverse("article_detail", args=[self.article.id])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Bericht 1")
Hier zijn de kernpunten:
-
self.client: een testclientinstantie die standaard doorTestCasewordt geleverd -
reverse("article_detail", args=[...]): in plaats van hardcoding van de URL, ophalen op naam -
assertContains: controleren of een specifieke string in de respons inhoud is opgenomen
4-2. Test van inloggen/toegangscontrole
from django.contrib.auth import get_user_model
class ArticlePermissionTests(TestCase):
def setUp(self):
self.user = get_user_model().objects.create_user(
username="tester",
password="pass1234",
)
self.article = Article.objects.create(
title="geheim",
content="Geheime Inhoud",
views=0,
)
def test_anonymous_user_redirected_to_login(self):
url = reverse("article_edit", args=[self.article.id])
response = self.client.get(url)
self.assertEqual(response.status_code, 302)
self.assertIn("/accounts/login", response["Location"])
def test_logged_in_user_can_access_edit_page(self):
self.client.login(username="tester", password="pass1234")
url = reverse("article_edit", args=[self.article.id])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
-
Als een anonieme gebruiker toegang probeert te krijgen, wordt er een redirect uitgevoerd
-
Kan een ingelogde gebruiker daarentegen normaal toegang krijgen
Zo kun je buggerelateerde toegangsproblemen aanvankelijk opsporen.
5. Wanneer / hoe voer je tests.py uit?
5-1. Voer alle tests uit
$ python manage.py test
- Het zoekt en voert automatisch
test*.pybestanden uit binnen de huidige directory
unittest.TestCaseofdjango.test.TestCasesubclasses.
5-2. Voer alleen specifieke app uit
$ python manage.py test myapp
5-3. Voer alleen bepaalde modules / klassen / methoden uit
# Hele myapp.tests module
$ python manage.py test myapp.tests
# Specifieke TestCase
$ python manage.py test myapp.tests.ArticleViewTests
# Bepaalde testmethode
$ python manage.py test myapp.tests.ArticleViewTests.test_article_detail_page_returns_200
Het is goed om tijdens de ontwikkeling de gewoonte aan te nemen om alleen de gewijzigde delen snel opnieuw uit te voeren.
6. tests.py uitbreiden naar tests-pakket
Als het project groeit, kan één tests.py bestand niet langer voldoende zijn.
Django-documentatie raadt ook aan om het in pakketstructuur te splitsen.(Django Project)
Bijvoorbeeld:
myapp/
tests/
__init__.py
test_models.py
test_views.py
test_forms.py
test_api.py
In elk bestand:
# myapp/tests/test_models.py
from django.test import TestCase
from myapp.models import Article
class ArticleModelTests(TestCase):
...
Je kunt het op deze manier splitsen en het uitvoeren blijft hetzelfde.
$ python manage.py test myapp # Alles
$ python manage.py test myapp.tests.test_models # Alleen modeltesten
7. Enkele praktische gebruiksvoorbeelden
7-1. “Bug reproductietests” voor regressie voorkomen
-
Er treedt een bug op in productie
-
Schrijf een reproductietest lokaal (deze moet falen)
-
Pas de code aan
-
Controleer of de test slaagt
-
gitmet tests + correctiecode samen commit
Als je dit doet, voorkom je dat dezelfde bug opnieuw optreedt tijdens refactoring.
7-2. API-response-indeling vastzetten
Bij samenwerking met de frontend is het formaat van de API-respons heel belangrijk.
class ArticleApiTests(TestCase):
def setUp(self):
self.article = Article.objects.create(
title="API Titel",
content="Inhoud",
views=0,
)
def test_article_detail_api_response(self):
url = reverse("api:article-detail", args=[self.article.id])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertEqual(data["id"], self.article.id)
self.assertIn("title", data)
self.assertIn("content", data)
-
Geef expliciet aan welke velden altijd moeten worden opgenomen in de respons
-
Als je een veldnaam per ongeluk wijzigt of verwijdert, zal de test onmiddellijk falen
7-3. Testen van formuliervalidatielogica
from .forms import ArticleForm
class ArticleFormTests(TestCase):
def test_title_is_required(self):
form = ArticleForm(data={"title": "", "content": "Inhoud"})
self.assertFalse(form.is_valid())
self.assertIn("title", form.errors)
def test_valid_form(self):
form = ArticleForm(data={"title": "Titel", "content": "Inhoud"})
self.assertTrue(form.is_valid())
- Je kunt de validatieregels van het formulier als documentatie met testen vastleggen.

8. Samenvatting – Verwijder tests.py niet, maar gebruik het een keer goed
In één zin samengevat:
tests.pyis het bestand dat een “veiligheidsnet voor Django-apps” creëert.
-
In het begin kan het vervelend zijn, maar
-
Als je eenmaal de flow van ontwikkelen op basis van tests hebt ervaren,
-
zal de stress bij refactoren/functie toevoegingen/upgrades aanzienlijk verminderen.
In echte projecten:
-
Bij het maken van nieuwe functies – voeg minimaal 1-2 tests toe
-
Bij het herstellen van bugs – schrijf altijd eerst een test die de bug reproduceert
-
Wanneer je begint met het uitbreiden van het project – refactor
tests.pynaar eentests/pakket
Als je dit patroon volgt, zul je een totaal andere ontwikkelervaring hebben dan met een “Django-project zonder tests”.
댓글이 없습니다.