Сравниваем структуры без учета порядка

Часто там нужно сравнивать одни части структур упорядоченно, а другие без учета порядке. Например, когда из API возвращается список с неупорядоченными значениями. Причем эти значения могут быть глубоко-глубоко внутри вложенного объекта.

class MyTestCase(unittest.TestCase):
    def test_one(self):
        data = make_request(...).json()
        self.assertEqual(data, {
            'root': {
                'sub': {
                    'items': ['a', 'b', 'c']
                }
            }
        })

Этот тест может падать, если на сервере структура items порождена, например, из set() или dict().values().
Что с этим делать? Предлагаю вот такое элегантное решение!

import unittest
from unittest.util import _count_diff_hashable, _count_diff_all_purpose

class Unordered(list):
    def __eq__(self, other):
        if not isinstance(other, type(self).__bases__):
            return False
        try:
            return not _count_diff_hashable(self, other)
        except TypeError:
            return not _count_diff_all_purpose(self, other)

class MyTestCase(unittest.TestCase):
    def test_one(self):
        data = make_request(...).json()
        self.assertEqual(data, {
            'root': {
                'sub': {
                    'items': Unordered(['a', 'b', 'c'])
                }
            }
        })

Благодаря тому, что класс Unordered наследован от list, метод __eq__ будет вызываться когда Unordered находится как слева от ==, так и справа от == (см. документацию на __eq__).

Leave a Reply

Your email address will not be published. Required fields are marked *