Kur*_*eek 5 python django factory-boy
我想定义两个模型,Company和Package。每个Package只有一个Company,但一个Company可以有多个Packages。但是,每个公司只能有一个default_package(可以为空)。我的设置如下:
class Company(models.Model):
default_package = models.OneToOneField(
'dashboard.Package',
on_delete=models.SET_NULL,
blank=True,
null=True,
related_name='default_for_%(class)s')
class Package(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE)
Run Code Online (Sandbox Code Playgroud)
dashboard应用程序标签在哪里。
为了简化这些模型的测试,我使用factory_boy如下方式为它们创建了测试工厂:
import factory
from .models import Company, Package
class CompanyFactory(factory.Factory):
class Meta:
model = Company
default_package = factory.SubFactory('dashboard.test_factories.PackageFactory')
class PackageFactory(factory.Factory):
class Meta:
model = Package
company = factory.SubFactory(CompanyFactory)
Run Code Online (Sandbox Code Playgroud)
现在我正在尝试两个测试:
class DefaultPackageTest(TestCase):
def test_1(self):
company = Company.objects.create()
def test_2(self):
company = CompanyFactory()
Run Code Online (Sandbox Code Playgroud)
第一个只是创建一个Company,而第二个尝试使用 做同样的事情CompanyFactory。
然而奇怪的是,第一个测试通过了,而第二个测试失败了:
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/factory/builder.py", line 233, in recurse
return builder.build(parent_step=self, force_sequence=force_sequence)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/factory/builder.py", line 272, in build
step.resolve(pre)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/factory/builder.py", line 221, in resolve
self.attributes[field_name] = getattr(self.stub, field_name)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/factory/builder.py", line 355, in __getattr__
declaration = self.__declarations[name]
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/factory/builder.py", line 121, in __getitem__
context=self.contexts[key],
RecursionError: maximum recursion depth exceeded
----------------------------------------------------------------------
Ran 2 tests in 0.012s
FAILED (errors=1)
Destroying test database for alias 'default'...
Run Code Online (Sandbox Code Playgroud)
知道为什么这不起作用吗?我相信我已经按照文档(http://factoryboy.readthedocs.io/en/latest/reference.html#circular-importsCompanyFactory )提供了的子工厂的完整路径。
更新
看来这个用例是由 Factory Boy 的后代 hooks解决的。看起来很有希望的是RelatedFactory,给出了以下示例:
class CityFactory(factory.Factory):
class Meta:
model = City
capital_of = None
name = "Toronto"
class CountryFactory(factory.Factory):
class Meta:
model = Country
lang = 'fr'
capital_city = factory.RelatedFactory(CityFactory, 'capital_of', name="Paris")
Run Code Online (Sandbox Code Playgroud)
在Python REPL中测试如下:
>>> france = CountryFactory()
>>> City.objects.get(capital_of=france)
<City: Paris>
Run Code Online (Sandbox Code Playgroud)
然而,我很难将此示例应用于我的情况。(文档中没有City和模型的文本解释或代码并没有帮助)。Country看起来capital_city与我的情况类似default_package,所以我尝试将其变成RelatedFactory这样,
default_package = factory.RelatedFactory('dashboard.test_factories.PackageFactory')
Run Code Online (Sandbox Code Playgroud)
但我仍然遇到同样的错误。
小智 4
因此,我通过实现一个post_generation函数来实现这一点:
class PackageFactory(factory.Factory):
class Meta:
model = Package
company = factory.SubFactory('dashboard.test_factories.CompanyFactory')
class CompanyFactory(factory.Factory):
class Meta:
model = Company
@factory.post_generation
def default_package(self, create, _, **__):
PackageFactory(company=self)
Run Code Online (Sandbox Code Playgroud)
kwargcompany=self停止递归,并使用所需的默认包属性正确创建工厂。
| 归档时间: |
|
| 查看次数: |
1229 次 |
| 最近记录: |