在pytest中使用太多工厂是否被认为是一种好习惯?

问题描述

我正在尝试为Django / DjangoREST项目编写测试。我决定使用pytest。我在专门为Django项目编写测试方面经验不足。所以我现在很困惑。

这里是一个例子:

@pytest.mark.django_db
def test_some_view(
    api_client,simple_user,model1_factory,model2_factory,...  # many other model factories
    modelN_factory
):
    # ...
    # creating here other objects that really depends on each other
    # ...
    model2_obj = ...   # model2 object on its own side depends on model3,model4... and so on

    model1_objs = []
    for i in range(10):
        model1_objs.append(model1_factory(some_field=100,some_model2_rel=model2_obj)
    assert len(model1_objs) == 1,"Created items with duplicate `some_field`"

如您所见,我的工厂太多,无法在一项测试中使用。但是看 就目前的模型结构而言,我想不出更好的方法。可以使用那么多吗 工厂进行一次测试?还是应该找到一些与表的关系有关的问题?

感谢您的帮助。预先感谢

解决方法

factory_boy的主要目标是摆脱固定装置;它的典型用例是:

  1. 设计您的Factory类,这些类基本上是获得“现实”对象实例的秘诀
  2. 在测试中,仅调用所需的工厂,仅指定该测试用例的参数。

据我了解,pytest固定装置旨在用于“设置测试环境”:引导数据库,模拟外部服务等;在数据库内部创建对象不适合它们。

我编写代码的方式如下:

# factories.py
import factory
import factory.fuzzy

from . import models

class DivisionFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Division
    name = factory.Faker('company')

class EmployeeFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.Employee
    username = factory.Faker('username')
    name = factory.Faker('name')
    employee_id = factory.Sequence(lambda n: 'EM199%06d' % n)
    division = factory.SubFactory(DivisionFactory)
    role = factory.fuzzy.FuzzyChoice(models.Employee.ROLES)
    hired_on = factory.fuzzy.FuzzyDate(
        start_date=datetime.date.today() - datetime.timedelta(days=100),end_date=datetime.date.today() - datetime.timedelta(days=10),)

我们有一个工厂供员工使用,有一个工厂供部门使用-每个雇员都被分配到一个部门。 提供了每个必填字段;如果我们需要为某些对象配置文件创建特定工厂,则可以通过子类化或使用traits添加。

我们现在可以编写测试,只传递测试所需的详细信息:

# tests.py

@pytest.mark.django_db
def test_get_new_hire(api_client):
    employee = factories.EmployeeFactory(
        hired_on=datetime.date.today(),division__name="Finance",)
    data = api_client.get(f'/employees/{employee.username}')
    assert data['division'] == "Finance"
    assert data['orientation_status'] == 'pending'

请注意,直接使用Django的测试运行器是否更有意义?它针对Django内部进行了更精细的调整:每个测试都可以本地包装在子事务中以提高性能,测试客户端可以提供帮助程序来对视图结果进行深入的自省,等等。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...