代码之家  ›  专栏  ›  技术社区  ›  trubliphone

使用pytest django在测试之间缓存对象

  •  1
  • trubliphone  · 技术社区  · 6 年前

    我试图通过在测试之间缓存对象来加速我的单元测试。

    我知道考试应该互相隔离。但是创建我的对象的行为是昂贵的,没有必要一次又一次地创建相同的对象。

    setup_class 但显然这不管用。所以我刚刚编写了一个简单的函数,在每个测试开始时调用。这个 几乎 作品。但是,相关对象是空的。

    下面是一些代码:

    型号.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")
    

    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 回复  |  直到 6 年前
        1
  •  1
  •   Will Keeling    6 年前

    这里最好的选择也许是预取 Book Author 通过 RelatedManager 作者 . 该查找在第二个测试上不起作用,因为事务在最初缓存对象的第一个测试之后被拆毁。

    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