使用 pytest 和 factory-boy,如何为非传统类型的对象创建工厂?
With pytest and factory-boy, how do I create a factory for a non-traditional type of object?
我正在使用 Django 2、Python 3.7 和 factory-boy。尝试为 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()
基本 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)
我正在使用 Django 2、Python 3.7 和 factory-boy。尝试为 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()
基本 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)