How to write a custom `.assertFoo()` method in Python?

Viewed 11987

I'm writing some test cases for my application using Python's unittest. Now I need to compare a list of objects with a list of another objects to check if the objects from the first list are what I'm expecting.

How can I write a custom .assertFoo() method? What should it do? Should it raise an exception on failure? If yes, which exception? And how to pass the error message? Should the error message be a unicode string or a bytestring?

Unfortunately, the official documentation doesn't explain how to write custom assertion methods.

If you need a real-world example for this, continue reading.


The code I'm writing is somewhat like this:

def assert_object_list(self, objs, expected):
    for index, (item, values) in enumerate(zip(objs, expected)):
        self.assertEqual(
            item.foo, values[0],
            'Item {0}: {1} != {2}'.format(index, item.foo, values[0])
        )
        self.assertEqual(
            item.bar, values[1],
            'Item {0}: {1} != {2}'.format(index, item.bar, values[1])
        )

def test_foobar(self):
    objs = [...]  # Some processing here
    expected = [
        # Expected values for ".foo" and ".bar" for each object
        (1, 'something'),
        (2, 'nothing'),
    ]
    self.assert_object_list(objs, expected)

This approach makes it extremely easy to describe the expected values of each object in a very compact way, and without needing to actually create full objects.

However... When one object fails the assertion, no further objects are compared, and this makes debugging a bit more difficult. I would like to write a custom method that would unconditionally compare all objects, and then would display all objects that failed, instead of just the first one.

3 Answers

Just an example to sum up with a numpy comparaison unittest

import numpy as np
class CustomTestCase(unittest.TestCase):
    def npAssertAlmostEqual(self, first, second, rtol=1e-06, atol=1e-08):
        np.testing.assert_allclose(first, second, rtol=rtol, atol=atol)


class TestVector(CustomTestCase):
    def testFunction(self):
        vx = np.random.rand(size)
        vy = np.random.rand(size)
        self.npAssertAlmostEqual(vx, vy)
Related