Let's say I have an Article
model, like this:
from django.db import models
class Article(models.Model):
author = models.CharField(max_length=100)
title = models.CharField(max_length=200)
body = models.TextField()
This is naively simple compared to my actual usage (author
should be a ForeignKey
to another model, etc.), but this way it's more clear.
Imagine I want to list titles of all the articles by certain authors, yet keeping each author's pieces together. It could be represented as a list of lists:
def get_beatles_articles_titles():
beatles = [
"John Lennon",
"Paul McCartney",
"George Harrison",
"Ringo Starrr",
]
return [article.author for author in beatles
for article in Article.objects.filter(author=author)]
Oh, a nested list comprehension, so our method isn't that simple. There's a big chance of a bug being somewhere here, so we should test it somehow! The easiest solution seems to be creating some Article
instances corresponding to each author (and saving them in the database) and check if all of them are properly fetched.
from django.test import TestCase
from models import Article
from views import get_beatles_articles_titles
class ArticlesTitlesTestCase(TestCase):
def test_that_every_beatles__article_is_fetched(self):
Article.objects.create(author="John Lennon", title="John's")
Article.objects.create(author="Paul McCartney", title="Paul's")
Article.objects.create(author="George Harrison", title="George's")
Article.objects.create(author="Ringo Starr", title="Ringo's")
self.assertEqual(get_beatles_articles_titles(), [
["John's"],
["Paul's"],
["George's"],
["Ringo's"]
])
Running that test we can see that there's a typo in our original code, so it proved its usefulness.
However, accessing database is frowned upon in favor of mocking things (no wonder, I've experienced that time difference can be significant). What can be mocked in the test above? I'm particularly anxious about correctness of my .filter
query (it might get pretty complex), so I don't want to guess QuerySet
s a DB would give me.
Ideally, I'd like to use something like this (pseudo code follows):
johns_article = Article(author="John Lennon")
fake_query = MockQuery(author__contains="John")
assertTrue(fakeQuery.contains(johns_article))