【问题标题】:How to get more helpful error messages when comparing two instances? [duplicate]比较两个实例时如何获得更多有用的错误消息? [复制]
【发布时间】:2021-03-02 09:04:39
【问题描述】:

我正在比较两个类实例。以下是我的示例测试代码:

from unittest import TestCase

class Dog:
    age: int
    name: str

    def __eq__(self, other):
        if not isinstance(other, Dog):
            return False

        return self.age == other.age and self.name == other.name


class MyTests(TestCase):
    def test_compare(self):    
    d1 = Dog()
    d1.age = 1
    d1.name = 'dog1'

    d2 = Dog()
    d2.age = 2
    d2.name = 'dog2'

    self.assertEqual(d1, d2)

这会产生一个断言错误:

AssertionError: <test.Dog object at 0x0000020444FCA520> != <test.Dog object at 0x0000020444F97D60>

有没有办法直接比较两个实例并获得更有用的错误消息,例如导致断言失败的字段?我发现的唯一方法是直接比较字段,如下所示。有没有不那么繁琐的方法?

self.assertEqual(d1.age, d2.age)
self.assertEqual(d1.name, d2.name)

【问题讨论】:

  • @manveti 不,我认为这不是我要找的东西,但无论如何感谢您的分享!
  • 我想你会发现如果你实现 str 和 repr,你会得到更好的消息,也许使用数据类。
  • @BrianMcCutchon 在看到下面 Jack Taylor 的回答中的代码后,我认为它毕竟与我正在寻找的东西有关!
  • @manveti 看到下面杰克泰勒的回答,它确实回答了我的问题!谢谢你的链接!
  • 另外,使用 pytest 通常会比内置的 unittest 模块提供更多有用的错误消息。

标签: python unit-testing equality assertion error-messaging


【解决方案1】:

我刚刚发现的另一种方法是创建一个辅助函数来比较两个实例。

不再需要实现__eq__

它不那么繁琐,因为我只需要编写一次函数:

def test_compare(self):        
    d1 = Dog()
    d1.age = 1
    d1.name = 'dog1'

    d2 = Dog()
    d2.age = 2
    d2.name = 'dog2'

    self.__assertDogsAreEqual(d1, d2)

def __assertDogsAreEqual(self, dog1: Dog, dog2: Dog):
    self.assertEqual(dog1.age, dog2.age)
    self.assertEqual(dog1.name, dog2.name)
    

它现在提供了更有用的错误消息:

Traceback (most recent call last):
  File "test.py", line 119, in test_temp
    self.__assertDogsAreEqual(d1, d2)
  File "test.py", line 122, in __assertDogsAreEqual
    self.assertEqual(dog1.age, dog2.age)
AssertionError: 1 != 2

我可能会接受这个作为答案,但我仍然很好奇是否有更好的方法。

不过,这确实是目前最实用的方法。

【讨论】:

    【解决方案2】:

    您可以在类中定义__repr__ 方法。这用于为调试目的创建对象的字符串表示形式。

    class Dog:
        age: int
        name: str
    
        def __init__(self, age, name):
            self.age = age
            self.name = name
    
        def __eq__(self, other):
            if not isinstance(other, Dog):
                return False
    
            return self.age == other.age and self.name == other.name
    
        def __repr__(self):
            return f"{self.__class__.__name__}({repr(self.age)}, {repr(self.name)})"
    
    print(Dog(5, "Fido"))  # Prints "Dog(5, 'Fido')"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-19
      • 1970-01-01
      • 2016-08-11
      • 1970-01-01
      • 2020-02-19
      • 1970-01-01
      相关资源
      最近更新 更多