检查Pytest中两个对象是否具有相同的内容

9
我是一名正在学习如何使用Pytest(以及单元测试)的人,我想编写一个测试来检查同一类的两个对象是否具有相同的属性。

例如:

class Something(object):
    def __init__(self, a, b):
        self.a, self.b = a, b

    def __repr__(self):
        return 'Something(a={}, b={})'.format(self.a, self.b)

def test_equality():
    obj1 = Something(1, 2)
    obj2 = Something(1, 2)
    assert obj1.a == obj2.a
    assert obj1 == obj2

这个测试在第三个断言失败并抛出了 AssertionError 异常:

    def test_equality():
        obj1 = Something(1, 2)
        obj2 = Something(1, 2)
        assert obj1.a == obj2.a
        assert obj1.b == obj2.b                                                                                                                                                                                                               
>       assert obj1 == obj2                                                                                                                                                                                                                   
E       assert Something(a=1, b=2) == Something(a=1, b=2)                                                                                                                                                                                     

tests/test_model.py:13: AssertionError

在Python或Pytest中,只使用assert obj1 == obj2是可行的吗?我是否应该为每个要测试的类实现“丰富比较”方法,或者有更简单的方法?


1
通常最好实现一个比较运算符,例如 __eq__,因为有些对象即使字段不同也可能相等。一种丑陋的方法通常可以奏效,如果 (a) 属性本身是可比较的,且 (b) 所有属性都存储在字典中,则可以使用 type(obj1) == type(obj2) and obj1.__dict__ == obj2.__dict__,但这种方法非常有限。 - Willem Van Onsem
@Idos:是的,它看起来非常相似。 - maln0ir
1个回答

13

重写Something类的__eq__函数。

def __eq__(self, other)
    if isinstance(self, other.__class__):
        return self.a == other.a and self.b == other.b
    return False

另外。

assert obj1 == obj2

实际上是一个由两部分构成的语句。第一部分是表达式 obj1 == obj2,它调用 obj1.__eq__(obj2) 并返回一个布尔值,第二部分则断言该布尔值为真。


1
在这里覆盖__eq__运算符可能会产生意想不到的后果,这取决于如何确定此对象的唯一性。 - Michael Robellard
如果你覆盖__eq__方法,你应该知道唯一性是什么。对我来说,这才是正确的答案。 - Tzomas
这种情况不好的一个例子是,如果你对你的类进行子类化,你想要一个子类,其中这两个属性都设置为等于基类吗?有时候你会想要,有时候不会,这取决于具体情况。 - Michael Robellard
在这种情况下,子类也应该重载等号运算符,并使用子类所需的任何附加字段或等价参数以及对超类eq的调用。这是一个架构问题,我认为这不是重载__eq__本身的问题。 - TTT
1
实际上,所有覆盖任何方法并与面向对象语言中的继承相结合的决定都是如此。 - TTT
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接