微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决在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内部进行了更精细的调整:每个测试都可以本地包装在子事务中以提高性能,测试客户端可以提供帮助程序来对视图结果进行深入的自省,等等。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?