【问题标题】:Factory calling alternate constructor (classmethod)工厂调用备用构造函数(类方法)
【发布时间】:2018-06-19 18:05:13
【问题描述】:

我正在努力寻找一种方法来使用定义为 @classmethod 的替代构造函数来创建类 Factory(我使用 factory_boy 版本 2.11.1 和 Python 3)。

假设我们有一个用于构建 2D 点对象的类,该类具有默认构造函数和 2 个附加构造函数:

class Point:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    @classmethod
    def fromlist(cls, coords):  # alternate constructor from list
        return cls(coords[0], coords[1])

    @classmethod
    def duplicate(cls, obj):  # alternate constructor from another Point
        return cls(obj.x, obj.y)

我创建了一个基本的点工厂:

import factory

class PointFactory(factory.Factory):
    class Meta:
        model = Point
        inline_args = ('x', 'y')

    x = 1.
    y = 2.

默认情况下,它似乎调用了类的构造函数__init__,这看起来很合乎逻辑。我找不到将inline_args 传递为coords 以使用备用构造函数fromlist 的方法。有办法吗?

这是我第一次工作和建造工厂的经历,所以我也可能在网络上查找错误的关键字...

【问题讨论】:

  • 没用过factory boy,如果你弄model = Point.fromlist会怎么样?从语义上讲,它们都是接受参数并返回 Point 实例的可调用对象——我觉得这可能是一种方法。

标签: python python-3.x testing class-method factory-boy


【解决方案1】:

factory_boy 的目的是让生成测试实例变得容易。你只需调用PointFactory()就完成了,你的代码的其余部分都有测试实例。 这个用例永远不需要使用任何替代构造函数。工厂将只使用主构造函数。

如果您认为必须定义 factory_boy 工厂来测试额外的构造函数,那么您误解了它们的用途。使用 factory_boy 工厂为其他要测试的代码创建测试数据。您不会使用它们来测试Point 类(除了生成测试数据以传递您的构造函数之一)。

请注意,inline_args 仅在您的构造函数根本不接受关键字参数时才需要。你的Point() 类没有这样的限制; xy 既可以用作位置参数,也可以用作关键字参数。您可以放心地从您的定义中删除 inline_args,无论如何,工厂都会正常工作。

如果您必须使用其他构造函数之一(因为您无法使用主构造函数创建测试数据),只需将特定的构造函数方法作为模型传入:

class PointListFactory(factory.Factory):
    class Meta:
        model = Point.fromlist

    coords = (1., 2.)

【讨论】:

  • 感谢您的回答,这引发了 2 个额外的问题: - 我添加了 inline_args 因为我想为某些测试创建两个彼此不同的点,以便我可以将值传递给工厂。这是不好的做法吗? - 另外,我们是否可以考虑使用工厂来避免在其他不用于测试的函数中创建对象?在我看来,创建新对象实例的函数不能单独进行单元测试。
  • @Eskapp:您无需设置inline_args 即可将不同的值传递到工厂。您可以调用PointFactory(x=42.),它会使用默认的y 值和您的特定x 值来创建一个新的Point() 对象,无论哪种方式。 inline_args 不管理该功能。
  • @Eskapp:factory_boy 纯粹是为了测试。类本身已经是工厂;你调用一个类来产生一个实例。 factory_boy 所做的是为您提供更多选项来批量生成测试实例,用于特定的预定义场景等,随机生成的数据看起来很逼真,并支持所有由更多 factory_boy 工厂生成的对象的复杂层次结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
  • 1970-01-01
  • 2016-05-31
  • 2016-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多