我试图通过在测试之间缓存对象来加快单元测试的速度。
我知道测试应该相互隔离。但是创建对象的操作很昂贵,因此无需一遍又一遍地创建相同的对象。
最初,我以为我可以从setup_class
调用固定装置,但是显然这是行不通的。因此,我刚刚编写了一个简单的函数,可以在每次测试开始时进行调用。这几乎有效。但是,相关对象为空。
以下是一些代码:
models.py:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, related_name="books")
tests.py:
import factory
import pytest
from faker import Faker
from django.db import models
from models import Book, Author
fake = Faker()
class AuthorFactory(factory.django.DjangoModelFactory):
class Meta:
model = Author
name = factory.Faker('name')
class BookFactory(factory.django.DjangoModelFactory):
class Meta:
model = Book
title = factory.Faker('sentence')
author = factory.SubFactory(AuthorFactory)
def make_an_author(**kwargs):
n_books = kwargs.pop("n_books", 10)
author = AuthorFactory.create(**kwargs)
for i in range(n_books):
BookFactory.create(author=author)
return author
@pytest.mark.django_db
class TestAuthor:
N_AUTHORS = 10
cached_authors = []
def cache_authors(self, n_authors):
current_n_authors = len(self.cached_authors)
if current_n_authors < n_authors:
self.cached_authors.extend(
[
make_an_author(n_books=2)
for i in range(current_n_authors, n_authors)
]
)
def test_one(self, cache_authors):
self.cache_authors(10)
author = fake.choice(self.cached_authors)
# THIS WORKS!
assert author.books.count() != 0
def test_two(self, cache_authors):
self.cache_authors(10)
author = fake.choice(self.cached_authors)
# THIS FAILS!
assert author.books.count() != 0
每次第一次测试后,作者与书籍之间的反向关系都是空的。
有什么想法吗?
答案 0 :(得分:1)
这里最好的选择也许是在缓存Book
时预取Author
对象。当前,Book
是通过RelatedManager
上的Author
按需查找的。该查找不适用于第二个测试,因为在最初缓存对象的第一个测试之后,事务被拆除。
您可以尝试:
def make_an_author(**kwargs):
n_books = kwargs.pop("n_books", 10)
author = AuthorFactory.create(**kwargs)
for i in range(n_books):
BookFactory.create(author=author)
# Prefetch the books before caching the author
author = Author.objects.prefetch_related('books').get(pk=author.pk)
return author