Doctests sind die einfachste Art Tests zu schreiben. Starte dafür eine Python Shell und führe einige Operationen an der Datenbank durch, ähnlich wie im Kapitel Die Datenbank API.
$ python manage.py shell
Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from recipes.models import Recipe
>>> title = 'Doctest'
>>> from django.template.defaultfilters import slugify
>>> from django.contrib.auth.models import User
>>> admin = User.objects.get(username='admin')
>>> r = Recipe.objects.create(title=title, slug=slugify(title), number_of_portions=4,
... author=admin)
>>> r.title
'Doctest'
>>> r.slug
u'doctest'
>>> r.number_of_portions
4
>>> r.author
<User: admin>
>>> import datetime
>>> r.date_created.date() == datetime.datetime.now().date()
True
>>> r.date_updated.date() == datetime.datetime.now().date()
True
>>> r.difficulty == Recipe.DIFFICULTY_MEDIUM
True
Die gerade durchgeführten Operationen haben ein neues Rezept erstellt und einige Attribute getestet.
Jetzt wollen wir noch einige Fehler provozieren:
>>> Recipe.objects.create(title=title, slug=slugify(title), number_of_portions=4,
... author=admin)
Traceback (most recent call last):
...
IntegrityError: column slug is not unique
>>> title = 'Doctest 2'
>>> Recipe.objects.create(title=title, slug=slugify(title))
Traceback (most recent call last):
...
IntegrityError: recipes_recipe.number_of_portions may not be NULL
>>> Recipe.objects.create(title=title, slug=slugify(title), number_of_portions=4)
Traceback (most recent call last):
...
IntegrityError: recipes_recipe.author_id may not be NULL
Damit sind wir mit der Erstellung der Doctests fertig. Du musst den Code aus der Shell jetzt nur noch in die Datei recipes/tests.py kopieren. Und zwar als Ersatz für den einfachen Beispiel-Doctest:
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
Da der Benutzer “admin” in der Testdatenbank nicht existiert musst du ihn manuell während des Tests erstellen. Ersetze dazu die Zeile:
>>> admin = User.objects.get(username='admin')
mit folgendem Code:
>>> admin = User.objects.create_user('admin', 'admin@example.com', 'admin')
Die Datei recipes/tests.py sieht dann so aus:
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)
__test__ = {"doctest": """
>>> from recipes.models import Recipe
>>> title = 'Doctest'
>>> from django.template.defaultfilters import slugify
>>> from django.contrib.auth.models import User
>>> admin = User.objects.create_user('admin', 'admin@example.com', 'admin')
>>> r = Recipe.objects.create(title=title, slug=slugify(title), number_of_portions=4,
... author=admin)
>>> r.title
'Doctest'
>>> r.slug
u'doctest'
>>> r.number_of_portions
4
>>> r.author
<User: admin>
>>> import datetime
>>> r.date_created.date() == datetime.datetime.now().date()
True
>>> r.date_updated.date() == datetime.datetime.now().date()
True
>>> r.difficulty == Recipe.DIFFICULTY_MEDIUM
True
>>> Recipe.objects.create(title=title, slug=slugify(title), number_of_portions=4,
... author=admin)
Traceback (most recent call last):
...
IntegrityError: column slug is not unique
>>> title = 'Doctest 2'
>>> Recipe.objects.create(title=title, slug=slugify(title))
Traceback (most recent call last):
...
IntegrityError: recipes_recipe.number_of_portions may not be NULL
>>> Recipe.objects.create(title=title, slug=slugify(title), number_of_portions=4)
Traceback (most recent call last):
...
IntegrityError: recipes_recipe.author_id may not be NULL
"""}
Bemerkung
Die Details der Tracebacks werden wirklich durch den String ”...” ersetzt.
Jetzt kannst du mit dem Kommando python manage.py test recipes -v 2 die Tests laufen lassen und sehen, dass die Doctests ausgeführt werden. Mit python manage.py test recipes.doctest -v 2 kannst du auch nur die Doctests alleine aufrufen.