我正在考虑使用factory_boy库进行API测试.文档中的一个例子是:
class UserFactory(factory.Factory):
class Meta:
model = base.User
first_name = "John"
last_name = "Doe"
Run Code Online (Sandbox Code Playgroud)
对于这项工作,我们需要的first_name,last_name等被作为参数传递__init__()的方法base.User() class.但是,如果您有许多参数,则会导致以下情况:
class User(object):
GENDER_MALE = 'mr'
GENDER_FEMALE = 'ms'
def __init__(self, title=None, first_name=None, last_name=None, is_guest=None,
company_name=None, mobile=None, landline=None, email=None, password=None,
fax=None, wants_sms_notification=None, wants_email_notification=None,
wants_newsletter=None, street_address=None):
self. title = title
self.first_name = first_name
self.last_name = last_name
self.company_name = company_name
self.mobile = mobile
self.landline = landline
self.email = email
self.password = password
self.fax = fax
self.is_guest = is_guest
self.wants_sms_notification …Run Code Online (Sandbox Code Playgroud) 我正在使用带有 SQLAlchemy 的工厂男孩。
我正在尝试创建 Fact 对象,并且希望工厂男孩生成作为 Fact 的外键的 PatientDim 对象。但 Subfactory 不传递键,而是将整个对象传递给外键字段。
我怎样才能只通过 Subfactory 传递 PatientDim 密钥?
工厂.py
class FactFactory(SQLAlchemyModelFactory):
class Meta:
model = models.Fact
sqlalchemy_session = common.Session
patient_id = factory.SubFactory(PatientDimFactory)
class PatientDimFactory(SQLAlchemyModelFactory):
class Meta:
model = models.PatientDim
sqlalchemy_session = common.Session
Run Code Online (Sandbox Code Playgroud)
模型.py
class Fact(TimeStampedModel):
class Meta:
db_table = 'fact'
id = Column(Integer, primary_key=True)
patient_id = Column('patient_id', Integer, ForeignKey(PatientDim.__table__.c.id), nullable=False)
patient = relationship(PatientDim, foreign_keys='Fact.patient_id' )
Base = declarative_base()
class PatientDim(TimestampMixin, Base):
__tablename__ = 'patient_dim'
id = Column('id', Integer, primary_key=True)
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 Factoryboy 在创建时指定长度的对象中创建一个列表。
我可以创建列表,但是由于提供的长度/大小的惰性性质,每次尝试创建具有指定长度的列表都会导致问题。
这是我到目前为止所拥有的:
class FooFactory(factory.Factory):
class Meta:
model = command.Foo
foo_uuid = factory.Faker("uuid4")
bars = factory.List([
factory.LazyAttribute(lambda o: BarFactory()
for _ in range(3))
])
Run Code Online (Sandbox Code Playgroud)
这将创建一个包含 3 个随机条的列表。我尝试过使用 Params 和排除的组合,但由于 range 需要一个 Int,并且 int 直到稍后才会延迟加载,因此会导致错误。
我想要类似于如何使用 post_ Generation 生成一对多关系的东西,即。
foo = FooFactory(number_of_bars=5)
Run Code Online (Sandbox Code Playgroud)
有人有这样的运气吗?
我想找到一种方法来正确测试我的代码与Factory Boy.
有一个模型,像这样:
from django.db import models
class MyModel(models.Model):
param1 = <some field>
param1 = <some field>
param1 = <some field>
@property
def is_smth(self):
<some complicated code that returns boolean>
Run Code Online (Sandbox Code Playgroud)
这个型号有一个工厂:
import factory
class MyModelFactory(factory.DjangoModelFactory):
param1 = <some value>
param2 = <some value>
param3 = <some value>
# And here i need to "rewrite" property of the model
# so that it would always return true
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮助我吗?我没有在工厂男孩的文档中找到关于这个的提及,我尝试的各种变体似乎不起作用.
FactoryBoy似乎总是在默认数据库中创建实例.但我有以下问题.
cpses = CanonPerson.objects.filter(persons__vpd=6,
persons__country="United States").using("global")
Run Code Online (Sandbox Code Playgroud)
代码指向global数据库.我还没有找到在工厂中指定数据库的方法:
class CanonPersonFactory(django_factory.DjangoModelFactory):
class Meta:
model = CanonPerson
django_get_or_create = ('name_first', 'p_id')
p_id = 1
name_first = factory.Sequence(lambda n: "name_first #%s" % n)
@factory.post_generation
def persons(self, create, extracted, **kwargs):
if not create:
# Simple build, do nothing.
return
if extracted:
# A list of groups were passed in, use them
for person in extracted:
self.persons.add(person)
Run Code Online (Sandbox Code Playgroud) class MyClassTest(TestCase):
def setUp(self):
Someclass.objects.create()
def test_first_test(self):
# Here, Someclass.objects.all()[0].pk -> returns 1
def test_second_test(self):
# Here, Someclass.objects.all()[0].pk -> returns 2 !!! (bad !)
Run Code Online (Sandbox Code Playgroud)
使用SetUp()方法,应该清除数据并在每次测试之间重新创建.那么,为什么id从一个测试增加到另一个测试呢?这对我来说并不明显.
这样我就无法根据id进行测试(因为它们取决于其他测试).这就是为什么我总是希望得到1结果.
请注意,我对数据本身没有任何问题,旧数据可以从一个测试清除到另一个测试.问题只是ids.
我在这里读到django对象id在单元测试之间递增,问题与数据库有关,而不是与Django有关,但Django有没有改变它的技巧?
当我在动态类型的Ruby或Python中编写单元测试时,我分别使用库factory_girl和factory_boy,以便方便地生成测试对象.它们提供了直接对象实例化的便捷功能,例如:
在静态类型的Java或Scala中编写单元测试时,我可以使用哪些库/框架来实现具有类似优点的类似效果?
提前致谢!
我在这里发现了一个类似的StackOverflow问题,但不幸的是,最好的答案是(释义),"没有直接的等价,因为那将毫无意义".
当两个或多个模型有一个共同的外键时,我的工厂不断遇到问题,而每个模型都创建了自己的对象,而它们应该具有相同的对象。
为了说明问题,这里是一个简化的模型结构:
class Language (models.Model):
code = models.CharField(max_length=3, unique=True)
class Audio(models.Model):
language = models.ForeignKey(Language)
soundfile = models.FileField()
class Subtitles(models.Model):
language = models.ForeignKey(Language)
text = models.TextField()
class Recording(models.Model):
audio = models.ForeignKey(Audio)
subtitles = models.ForeignKey(Subtitles)
Run Code Online (Sandbox Code Playgroud)
所以 aRecording具有Audio和Subtitles,并且两者都有一个Language对于每种语言代码都是唯一的。
这是这种结构的工厂。
class LanguageFactory(factory.django.DjangoModelFactory):
class Meta:
model = Language
class AudioFactory(factory.django.DjangoModelFactory):
class Meta:
model = Audio
language = factory.SubFactory(LanguageFactory, code='en1')
class SubtitlesFactory(factory.django.DjangoModelFactory):
class Meta:
model = Subtitles
language = factory.SubFactory(LanguageFactory, code='en1')
class RecordingFactory(factory.django.DjangoModelFactory):
class Meta:
model = Recording …Run Code Online (Sandbox Code Playgroud) 我正在使用Factory Boy来测试Django项目,并且在测试我已经覆盖了save方法的模型时遇到了一个问题.
该模型:
class Profile(models.Model):
active = models.BooleanField()
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,
related_name='profiles')
department = models.ForeignKey(Department, null=True, blank=True)
category_at_start = models.ForeignKey(Category)
role = models.ForeignKey(Role)
series = models.ForeignKey(Series, null=True, blank=True)
status = models.ForeignKey('Status', Status)
def save(self, *args, **kwargs):
super(Profile, self).save(*args, **kwargs)
active_roles = []
active_status = []
for profile in Profile.objects.filter(user=self.user):
if profile.active:
active_roles.append(profile.role.code)
active_status.append(profile.status.name)
self.user.current_role = '/'.join(set(active_roles))
if 'Training' in active_status:
self.user.current_status = 'Training'
elif 'Certified' in active_status:
self.user.current_status = 'Certified'
else:
self.user.current_status = '/'.join(set(active_status))
self.user.save()
super(Profile, self).save(*args, …Run Code Online (Sandbox Code Playgroud) 我的 SQLAlchemy 模型中有多对一关系。一份报告有许多示例(为简洁起见,进行了简化):
class Sample(db.Model, CRUDMixin):
sample_id = Column(Integer, primary_key=True)
report_id = Column(Integer, ForeignKey('report.report_id', ondelete='CASCADE'), index=True, nullable=False)
report = relationship('Report', back_populates='samples')
class Report(db.Model, CRUDMixin):
report_id = Column(Integer, primary_key=True)
samples = relationship('Sample', back_populates='report')
Run Code Online (Sandbox Code Playgroud)
现在,在我的测试中,我希望能够生成一个Sample或多个实例Report,并填充缺失的关系。
class ReportFactory(BaseFactory):
class Meta:
model = models.Report
report_id = Faker('pyint')
samples = RelatedFactoryList('tests.factories.SampleFactory', size=3)
class SampleFactory(BaseFactory):
class Meta:
model = models.Sample
sample_id = Faker('pyint')
report = SubFactory(ReportFactory)
Run Code Online (Sandbox Code Playgroud)
当我去创建它们的实例时,工厂陷入无限循环:
RecursionError: maximum recursion depth exceeded in comparison
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试使用SelfAttributes 来停止无限循环,我最终会得到一个没有任何样本的报告:
RecursionError: maximum recursion depth …Run Code Online (Sandbox Code Playgroud) factory-boy ×10
python ×8
django ×5
unit-testing ×4
sqlalchemy ×2
factory-bot ×1
java ×1
scala ×1
testing ×1