Python unittest assertDictContainsSubset рекомендует альтернативу

У меня есть некоторые тесты на Python, написанные в unittest. Я хочу проверить, что некоторые мои словари содержат по крайней мере некоторые атрибуты, равные определенным значениям. Если есть дополнительные значения, это будет хорошо. assertDictContainsSubset будет идеальным, за исключением того, что он устарел. Есть ли лучшее, что я должен использовать или должен ли я просто рекурсивно утверждать, что содержимое должно быть равным, если они находятся в целевом словаре?

Документы рекомендуют использовать addTypeEqualityFunc, но я хочу использовать обычный assertEqual для dicts в некоторых случаях.

Ответ 1

Если вы тестировали, если dict A является подмножеством dict B, я бы написал функцию, которая пытается извлечь содержимое dict A из dict B, создавая новый dict C, а затем assertEqual (A, C).

def extractDictAFromB(A,B):
    return dict([(k,B[k]) for k in A.keys() if k in B.keys()])

тогда вы могли бы просто сделать

assertEqual(A,extractDictAFromB(A,B))

Ответ 2

Продолжая ответ @bman, воспользовавшись тем, что операторы сравнения для множествоподобных объектов перегружены как операторы подмножеств, вы можете использовать assertGreaterEqual для (возможно) более качественных сообщений об ошибках.

Сравните два теста:

import unittest

class SubsetTestCase(unittest.TestCase):
    def test_dict_1(self):
        a = {1: 1, 2: 2}
        b = {1: 2}
        self.assertTrue(a.items() >= b.items())

    def test_dict_2(self):
        a = {1: 1, 2: 2}
        b = {1: 2}
        self.assertGreaterEqual(a.items(), b.items())

unittest.main()

Результат:

======================================================================
FAIL: test_dict_1 (__main__.SubsetTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 9, in test_dict_1
    self.assertTrue(a.items() >= b.items())
AssertionError: False is not true

======================================================================
FAIL: test_dict_2 (__main__.SubsetTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 15, in test_dict_2
    self.assertGreaterEqual(a.items(), b.items())
AssertionError: dict_items([(1, 1), (2, 2)]) not greater than or equal to dict_items([(1, 2)])

----------------------------------------------------------------------

С помощью assertGreaterEqual вы можете увидеть содержимое двух словарей из сообщения об ошибке.

Ответ 3

Эндрю предложил решение, которое использует assertEqual, как вы и просили. Но для будущих читателей полезно знать два альтернативных решения, которые являются более краткими. Сначала используется метод issubset из набора:

assert set(A.items()).issubset(set(B.items()))

Но есть еще одно более простое, более питонское решение этой проблемы:

set(A.items()) <= set(B.items())

Подводные камни второго решения в том, что вы не будете знать, какие ключи из надмножества отсутствуют в подмножестве.

Тем не менее, оба решения потерпят неудачу, если в ваших значениях есть непересекающиеся переменные (такие как dict) внутри них.