为什么工厂类创建多个 django 模型?

问题描述 投票:0回答:1

我创建了工厂类“ShopModelFactory”vie factory-boy包,它应该返回django模型“Shop”,另外模型的字段通过faker感觉起来,比我通过pytest编写测试,但是 在 django 项目中运行 pytest 后出现此错误 ->

django.db.utils.IntegrityError: duplicate key value violates unique constraint "shops_shop_pkey"
DETAIL:  Key (id)=(cd84e095-7d1a-41fc-adb3-7f5db5e07d50) already exists.
========================================================================== short test summary info ===========================================================================
FAILED tests/models/test_shop.py::test_shop_creation - django.db.utils.IntegrityError: duplicate key value violates unique constraint "shops_shop_pkey"

但是我的数据库是空的,另外我要删除之前的所有记录

我的模型

class Shop(TimedBaseModel):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    first_name = models.CharField("First Name", max_length=20)
    last_name = models.CharField("Last Name", max_length=20)
    email = models.EmailField("Email", unique=True)
    phone = PhoneNumberField(
        "Phone Number",
        unique=True,
    )
    shop_name = models.CharField("Shop Name", max_length=50, unique=True)
    shop_url = models.URLField("Shop URL", unique=True)
    logo = models.ImageField("Logo", upload_to="logos/", blank=True, null=True)
    banner = models.ImageField(
        "Banner",
        upload_to="banners/",
        blank=True,
        null=True,
    )
    street1 = models.CharField("Street 1", max_length=50)
    street2 = models.CharField("Street 2", max_length=50, blank=True)
    city = models.CharField("Town / City", max_length=100)
    zip_code = models.CharField("Zip Code", max_length=10)
    country = CountryField("Country", blank_label="(select country)")
    state = models.CharField("State", max_length=100, blank=True, default="")
    password = models.CharField("Password")
    confirm_password = models.CharField("Confirm Password")
    is_visible = models.BooleanField(
        verbose_name="Is the shop visible in the shops catalog",
        default=True,
    )

    class Meta:
        verbose_name = "Խանութ"
        verbose_name_plural = "Խանութներ"
        app_label = "shops"

    def __str__(self):
        return self.shop_name

    def save(self, *args, **kwargs):
        instance = super().save(*args, **kwargs)
        if self.logo:
            instance = super().save(*args, **kwargs)
            logo_path = self.logo.path

            logo = Image.open(logo_path)
            logo_size = os.path.getsize(logo_path)  # in bytes
            thirty_mb = 30 * 1024 * 1024

            while logo_size > thirty_mb:
                logo = logo.convert("RGB")
                logo.save(
                    logo_path,
                    quality=60,
                    optimize=True,
                    format="JPEG",
                )
        return instance

我的工厂

import factory
from factory.django import DjangoModelFactory, ImageField
from api.v1.apps.shops.models.shops import Shop


class ShopModelFactory(DjangoModelFactory):
    class Meta:
        model = Shop

    
    first_name = factory.Faker('first_name')
    last_name = factory.Faker('last_name')
    email = factory.Faker('email')
    phone = factory.Faker('phone_number')
    shop_name = factory.Faker('company')
    shop_url = factory.Faker('url')
    logo = ImageField(color='blue')
    banner = ImageField(color='red')
    street1 = factory.Faker('street_address')
    street2 = factory.Faker('secondary_address')
    city = factory.Faker('city')
    zip_code = factory.Faker('postcode')
    country = factory.Faker('country_code')
    state = factory.Faker('state')
    password = factory.Faker('password')
    confirm_password = password
    is_visible = factory.Faker('boolean')

我的测试

@pytest.mark.django_db(transaction=True)
def test_shop_creation():
    Shop.objects.all().delete()  # even before model creation I'm deleting all records from database
    shop = ShopModelFactory()
    assert Shop.objects.count() == 1
    assert Shop.objects.first() == shop
    assert shop.first_name
    assert shop.last_name
    assert shop.email
    assert shop.phone
    assert shop.shop_name
    assert shop.shop_url
    assert shop.street1
    assert shop.city
    assert shop.zip_code
    assert shop.country
    assert shop.state
    assert shop.password
    assert shop.confirm_password
    assert isinstance(shop.is_visible, bool)

再次请注意,在我的测试函数中,我还在使用 ShopModelFactory 创建新模型之前从数据库中删除了所有记录。此外,我可以说我可以在管理面板中无缝创建记录

django django-models pytest faker factory-boy
1个回答
0
投票

删除

@pytest.mark.django_db(transaction=True)

不要使用

transaction=True
,因为你不需要它,它会导致不需要的行为,因此删除操作和创建将在最后作为一个事务发生,这不是你想要测试的东西

© www.soinside.com 2019 - 2024. All rights reserved.