Как с помощью pytest и factory-boy создать фабрику для объектов нетрадиционного типа? - PullRequest
1 голос
/ 06 мая 2020

Я использую Django 2, Python 3,7 и заводской мальчик. Попытка создать фабрику для django -address 'AddressField - https://pypi.org/project/django-address/, что, как я полагаю, является нетрадиционной моделью, поскольку она не наследуется от models.Model. Я создал эту фабрику, используя objects = models.Manager() ...

class AddressFactory(factory.DjangoModelFactory):
    """
        Define Address Factory
    """
    objects = models.Manager()

    class Meta:
        model = AddressField

    street_number = "123"
    route = "Rd"
    raw = "123 Fake Rd"
    formatted = "123 Fake Rd."
    latitude = 87.1234
    longitude = -100.12342
    locality = factory.SubFactory(LocalityFactory)

class CoopFactory(factory.DjangoModelFactory):
    """
        Define Coop Factory
    """
    class Meta:
        model = Coop

    name = "test model"
    address = factory.SubFactory(AddressFactory)
    enabled = True
    phone = "312-999-1234"
    email = "test@hello.com"
    web_site = "http://www.hello.com"

    @factory.post_generation
    def types(self, create, extracted, **kwargs):
        if not create:
            # Simple build, do nothing.
            return

        if extracted:
            # A list of types were passed in, use them
            for type in extracted:
                self.types.add(type)
        else:
            type = factory.SubFactory(CoopTypeFactory)
            self.types.all().set( (type) )

Затем у меня есть этот тест ...

@pytest.mark.django_db
def test_address_create(self):
    """ Test address model """    # create customer model instance
    address = AddressFactory()
    assert address is not None

, но результаты теста отображаются в приведенной ниже ошибке ...

davea$ python manage.py test --settings=maps.test_settings
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
setUpTestData: Run once to set up non-modified data for all class methods.
setUp: Run once for every test method to setup clean data.
EsetUp: Run once for every test method to setup clean data.
.
======================================================================
ERROR: test_address_create (tests.test_models.ModelTests)
Test address model
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/django.py", line 126, in _get_manager
    manager = model_class.objects
AttributeError: type object 'AddressField' has no attribute 'objects'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/davea/Documents/workspace/chicommons/maps/web/tests/test_models.py", line 27, in test_address_create
    address = AddressFactory()
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/base.py", line 46, in __call__
    return cls.create(**kwargs)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/base.py", line 564, in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/django.py", line 141, in _generate
    return super(DjangoModelFactory, cls)._generate(strategy, params)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/base.py", line 501, in _generate
    return step.build()
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/builder.py", line 279, in build
    kwargs=kwargs,
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/base.py", line 315, in instantiate
    return self.factory._create(model, *args, **kwargs)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/django.py", line 184, in _create
    manager = cls._get_manager(model_class)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/django.py", line 130, in _get_manager
    manager = model_class._default_manager
AttributeError: type object 'AddressField' has no attribute '_default_manager'

Что мне нужно сделать, чтобы построить фабрику для этого типа объекта?

Изменить: Это моя модель Coop в вся его слава ...

class Coop(models.Model):
    objects = CoopManager()
    name = models.CharField(max_length=250, null=False)
    types = models.ManyToManyField(CoopType)
    address = AddressField(on_delete=models.CASCADE)
    enabled = models.BooleanField(default=True, null=False)
    phone = PhoneNumberField(null=True)
    email = models.EmailField(null=True)
    web_site = models.TextField()

1 Ответ

0 голосов
/ 20 мая 2020

Базовая модель Coop должна быть похожа на:

from address.models import AddressField
from django.db import models


class Coop(models.Model):
    name = models.CharField(max_length=255)
    address = AddressField()

Чтобы настроить фабрики в ваших тестах, вы должны создать фабрику для каждой модели из django-address

class CountryFactory(factory.DjangoModelFactory):
    class Meta:
        model = 'address.Country'

    name = 'Test Country'
    code = '123'


class StateFactory(factory.DjangoModelFactory):
    class Meta:
        model = 'address.State'

    name = 'Test State'
    code = '456'
    country = factory.SubFactory(CountryFactory)


class LocalityFactory(factory.DjangoModelFactory):
    class Meta:
        model = 'address.Locality'

    name = 'Test Locality'
    postal_code = '123'
    state = factory.SubFactory(StateFactory)


class AddressFactory(factory.DjangoModelFactory):
    class Meta:
        model = 'address.Address'

    street_number = "123"
    route = "Rd"
    raw = "123 Fake Rd"
    formatted = "123 Fake Rd."
    latitude = 87.1234
    longitude = -100.12342
    locality = factory.SubFactory(LocalityFactory)

class CoopFactory(factory.DjangoModelFactory):
    class Meta:
        model = Coop

    name = 'new Coop'
    address = factory.SubFactory(AddressFactory)

И тест будет:

class FactoryTest(TestCase):
    def test_example(self):
        coop_from_factory = CoopFactory()
        self.assertIsNotNone(coop_from_factory)

        coop = Coop.objects.create(name='test', address=coop_from_factory.address)
        self.assertIsNotNone(coop)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...