0

I'm comparing two class instances with each other. Below is my sample test code:

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)

This generates an assertion error:

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

Is there a way to compare two instances directly and get a more helpful error message, such as the field that caused the assertion to fail? The only way I've found is to compare fields directly like below. Is there a less tedious way?

self.assertEqual(d1.age, d2.age)
self.assertEqual(d1.name, d2.name)
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Floating Sunfish
  • 4,920
  • 5
  • 29
  • 48

2 Answers2

1

You can define a __repr__ method in the class. This is used to create string representations of objects for debugging purposes.

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')"
Jack Taylor
  • 5,588
  • 19
  • 35
-1

Another way I just found is to create a helper function to compare the two instances.

There's no longer a need to implement __eq__.

It's less tedious because I only have to write the function once:

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)
    

It now gives a more helpful error message:

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

I might accept this as the answer, but I'm still curious if there's a better way.

This does look like the most practical approach for now, though.

Floating Sunfish
  • 4,920
  • 5
  • 29
  • 48