Is there a way to compare nested data structures in unittest
but ignoring concrete types of objects, like assertSequenceEqual
but recursive, for example:
#!/usr/bin/env python
import unittest
class DeepCompareTestCase(unittest.TestCase):
def test_compare(self):
# this test fails
self.assertSequenceEqual(
[['abc', 'def']],
(('abc', 'def'),)
)
unittest.main()
(something like Test::Deep
in Perl)
Would something like this work?
import unittest
from itertools import zip_longest
class RecursiveTestCase(unittest.TestCase):
def assertSequenceDeepEqual(self, x, y):
MissingValue = MissingValueSentinel()
for x, y, in zip_longest(x, y, fillvalue=MissingValue):
try:
self.assertSequenceDeepEqual(self, x, y)
except TypeError:
self.assertEqual(x, y)
self.assertIsNot(x, MissingValue)
self.assertIsNot(y, MissingValue)
class MissingValueSentinel(object):
pass
zip_longest
raises TypeError
if one or more of the items is not an iterator, indicating you're at the bottom of the recursion.
If one of the iterators is shorter than the other, I have it returning a custom MissingValueSentinel
object, which is detected by the assertIsNot
calls at the end of the function. The only reason for this would be if x
or y
has a class that for whatever reason compares equal to even ad-hoc classes like MissingValueSentinel
, but where assertEqual
is still meaningful between two different objects of that class. That seems like a pretty weird edge case and you can probably safely ignore it.
Using zip_longest
instead of zip
prevents [1, 2, 3]
incorrectly matching [1, 2]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With