Django FactoryBoy - 随机选择不适用于 LazyFunction
Django FactoryBoy - random choice not working with LazyFunction
我正在为我们的 django 应用程序构建大量测试,我正在使用 FactoryBoy
Profile
模型有一个 gender
字段,定义如下:
class Profile(models.Model):
GENDER_CHOICES = (
(u'm', _(u'Male')),
(u'f', _(u'Female')),
)
gender = models.CharField(
max_length=2, choices=GENDER_CHOICES, verbose_name=_("Gender"),
null=True, blank=True
)
我想用下面这行代码在 factory boy 中随机化这个字段的值:
class ProfileFactory(factory.Factory):
(...)
gender = factory.LazyFunction(random.choice(['f', 'm']))
但是,这会引发 TypeError: 'str' object is not callable
错误
然后我使用旧博客尝试了以下解决方案,该解决方案有效:
gender = factory.LazyAttribute(lambda x: random.choice(['f', 'm']))
这解决了问题,但我不清楚为什么会这样。
factory.LazyFunction
的 documentation 指出:
The LazyFunction is the simplest case where the value of an attribute
does not depend on the object being built.
It takes as argument a method to call (function, lambda…); that method
should not take any argument, though keyword arguments are safe but
unused, and return a value.
据我了解,random.choice(['f', 'm'])
构成了一个方法调用,因此应该按我的预期工作。
但是我对 LazyFunction
的理解显然有缺陷,我希望有人能解释我在这里做错了什么
两者的区别在于
lambda x: random.choice(['f', 'm'])
returns 函数和
random.choice(['f', 'm'])
计算语句和 returns 字符串。
如果您要在没有 lambda 的情况下复制行为,您可以使用
def foo():
return random.choice(['f', 'm'])
# ...
gender = factory.LazyFunction(foo)
LazyFunction
需要一个 callable:它可以调用的东西。
random.choice(['f', 'm'])
returns 一个字符串;要使其成为可调用的,解决方案是 LazyFunction(lambda: random.choice(['f', 'm']))
.
但是,解决您的问题的最佳方法是使用专为您的用例设计的 factory.fuzzy.FuzzyChoice
:
gender = factory.fuzzy.FuzzyChoice(['f', 'm'])
这将自行执行随机调用,并支持适当的 seeding/randomness 管理 — 有关详细信息,请参阅 https://factoryboy.readthedocs.io/en/latest/reference.html#randomness-management。
我正在为我们的 django 应用程序构建大量测试,我正在使用 FactoryBoy
Profile
模型有一个 gender
字段,定义如下:
class Profile(models.Model):
GENDER_CHOICES = (
(u'm', _(u'Male')),
(u'f', _(u'Female')),
)
gender = models.CharField(
max_length=2, choices=GENDER_CHOICES, verbose_name=_("Gender"),
null=True, blank=True
)
我想用下面这行代码在 factory boy 中随机化这个字段的值:
class ProfileFactory(factory.Factory):
(...)
gender = factory.LazyFunction(random.choice(['f', 'm']))
但是,这会引发 TypeError: 'str' object is not callable
错误
然后我使用旧博客尝试了以下解决方案,该解决方案有效:
gender = factory.LazyAttribute(lambda x: random.choice(['f', 'm']))
这解决了问题,但我不清楚为什么会这样。
factory.LazyFunction
的 documentation 指出:
The LazyFunction is the simplest case where the value of an attribute
does not depend on the object being built.
It takes as argument a method to call (function, lambda…); that method
should not take any argument, though keyword arguments are safe but
unused, and return a value.
据我了解,random.choice(['f', 'm'])
构成了一个方法调用,因此应该按我的预期工作。
但是我对 LazyFunction
的理解显然有缺陷,我希望有人能解释我在这里做错了什么
两者的区别在于
lambda x: random.choice(['f', 'm'])
returns 函数和
random.choice(['f', 'm'])
计算语句和 returns 字符串。
如果您要在没有 lambda 的情况下复制行为,您可以使用
def foo():
return random.choice(['f', 'm'])
# ...
gender = factory.LazyFunction(foo)
LazyFunction
需要一个 callable:它可以调用的东西。
random.choice(['f', 'm'])
returns 一个字符串;要使其成为可调用的,解决方案是 LazyFunction(lambda: random.choice(['f', 'm']))
.
但是,解决您的问题的最佳方法是使用专为您的用例设计的 factory.fuzzy.FuzzyChoice
:
gender = factory.fuzzy.FuzzyChoice(['f', 'm'])
这将自行执行随机调用,并支持适当的 seeding/randomness 管理 — 有关详细信息,请参阅 https://factoryboy.readthedocs.io/en/latest/reference.html#randomness-management。