Кэширование объектов между тестами с использованием pytest-django - PullRequest
0 голосов
/ 24 сентября 2018

Я пытаюсь ускорить свои юнит-тесты, кэшируя объекты между тестами.

Я знаю, что тесты должны быть изолированы друг от друга.Но создание моих объектов стоит дорого, и нет необходимости продолжать создавать одни и те же объекты снова и снова.

Первоначально я думал, что могу вызвать осветитель из 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

Каждый раз после первого теста обратная связь между автором и книгами пуста.

Есть идеи, почему?

1 Ответ

0 голосов
/ 25 сентября 2018

Лучшим вариантом здесь, возможно, является предварительная выборка объектов Book при кэшировании Author.В настоящее время Book s ищутся по запросу через 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
...