Как утверждать, что диктат содержит другой диктовку без AssertDictContainsSubset в Python?
-
22-12-2019 - |
Вопрос
Я знаю assertDictContainsSubset
можно сделать это в Python 2.7, но по какой-то причине это устарело в Python 3.2.Итак, есть ли способ утверждать, что один диктат содержит другой без assertDictContainsSubset
?
Кажется, это нехорошо:
for item in dic2:
self.assertIn(item, dic)
какой-нибудь другой хороший способ?Спасибо
Решение
>>> d1 = dict(a=1, b=2, c=3, d=4)
>>> d2 = dict(a=1, b=2)
>>> set(d2.items()).issubset( set(d1.items()) )
True
.
и наоборот вокруг:
>>> set(d1.items()).issubset( set(d2.items()) )
False
.
Ограничение: Словарь значений должны быть хмарированы.
Другие советы
Хотя я использую pteest, я нашел следующую идею в Комментарий .Это было очень здорово для меня, поэтому я подумал, что это может быть полезно здесь:
assert dict1.items() <= dict2.items()
.
для python 3 и
assert dict1.viewitems() <= dict2.viewitems()
.
для python 2.
Это работает с немашиными элементами, но вы не можете точно знать, какой элемент в конечном итоге не удается.
Большая проблема с принятым ответом заключается в том, что она не работает, если у вас есть нематериальные значения в значениях объектов.Во-вторых, что вы не получаете полезного вывода - тест проходит или не удается, но не говорит вам, какое поле внутри объекта отличается.
Как таковое легче просто создать подмножество словаря, то тестируйте это.Таким образом, вы можете использовать метод TestCase.assertDictEquals()
, который даст вам очень полезный отформатированный выход в ваш тестовый бегун, показывающий различие между фактическим и ожидаемым.
Я думаю, что самый приятный и пифитонический способ сделать это с простым словарем пониманием как таковой:
from unittest import TestCase
actual = {}
expected = {}
subset = {k:v for k, v in actual.items() if k in expected}
TestCase().assertDictEqual(subset, expected)
.
Примечание. Очевидно, что если вы управляете тестом в методе, который принадлежит дочерному классу, который наследует от тестирования (как вы почти наверняка должны быть), то это просто self.assertDictEqual(subset, expected)
Решение John1024 сработало для меня.Однако в случае сбоя он сообщит вам только False
вместо того, чтобы показывать вам, какие ключи не совпадают.Итак, я попытался избежать устаревшего метода утверждения, используя другие методы утверждения, которые выдают полезные сообщения об ошибках:
expected = {}
response_keys = set(response.data.keys())
for key in input_dict.keys():
self.assertIn(key, response_keys)
expected[key] = response.data[key]
self.assertDictEqual(input_dict, expected)
Вот сравнение, которое работает, даже если у вас есть списки в словарях:
superset = {'a': 1, 'b': 2}
subset = {'a': 1}
common = { key: superset[key] for key in set(superset.keys()).intersection(set(subset.keys())) }
self.assertEquals(common, subset)
. Это отвечает на немного более широкий вопрос, чем вы задаете, но я использую это в своих тестовых тестах, чтобы увидеть, соответствует ли container
словарь содержит нечто, похожее на contained
словарь.При этом проверяются ключи и значения.Кроме того, вы можете использовать ключевое слово 'ANYTHING'
чтобы показать, что вам все равно, как это сочетается.
def contains(container, contained):
'''ensure that `contained` is present somewhere in `container`
EXAMPLES:
contains(
{'a': 3, 'b': 4},
{'a': 3}
) # True
contains(
{'a': [3, 4, 5]},
{'a': 3},
) # True
contains(
{'a': 4, 'b': {'a':3}},
{'a': 3}
) # True
contains(
{'a': 4, 'b': {'a':3, 'c': 5}},
{'a': 3, 'c': 5}
) # True
# if an `contained` has a list, then every item from that list must be present
# in the corresponding `container` list
contains(
{'a': [{'b':1}, {'b':2}, {'b':3}], 'c':4},
{'a': [{'b':1},{'b':2}], 'c':4},
) # True
# You can also use the string literal 'ANYTHING' to match anything
contains(
{'a': [{'b':3}]},
{'a': 'ANYTHING'},
) # True
# You can use 'ANYTHING' as a dict key and it indicates to match the corresponding value anywhere
# below the current point
contains(
{'a': [ {'x':1,'b1':{'b2':{'c':'SOMETHING'}}}]},
{'a': {'ANYTHING': 'SOMETHING', 'x':1}},
) # True
contains(
{'a': [ {'x':1, 'b':'SOMETHING'}]},
{'a': {'ANYTHING': 'SOMETHING', 'x':1}},
) # True
contains(
{'a': [ {'x':1,'b1':{'b2':{'c':'SOMETHING'}}}]},
{'a': {'ANYTHING': 'SOMETHING', 'x':1}},
) # True
'''
ANYTHING = 'ANYTHING'
if contained == ANYTHING:
return True
if container == contained:
return True
if isinstance(container, list):
if not isinstance(contained, list):
contained = [contained]
true_count = 0
for contained_item in contained:
for item in container:
if contains(item, contained_item):
true_count += 1
break
if true_count == len(contained):
return True
if isinstance(contained, dict) and isinstance(container, dict):
contained_keys = set(contained.keys())
if ANYTHING in contained_keys:
contained_keys.remove(ANYTHING)
if not contains(container, contained[ANYTHING]):
return False
container_keys = set(container.keys())
if len(contained_keys - container_keys) == 0:
# then all the contained keys are in this container ~ recursive check
if all(
contains(container[key], contained[key])
for key in contained_keys
):
return True
# well, we're here, so I guess we didn't find a match yet
if isinstance(container, dict):
for value in container.values():
if contains(value, contained):
return True
return False
users = {'id': 28027, 'email': 'chungs.lama@gmail.com','created_at': '2005-02-13'}
data = {"email": "chungs.lama@gmail.com"}
self.assertGreaterEqual(user.items(), data.items())
. в Python 3 и Python 2.7, вы можете создать набор «представление элемента» диктома, не копируя какие-либо данные.Это позволяет вам использовать операторы сравнения для проверки для подмножества отношений.
в Python 3, это выглядит как:
# Test if d1 is a sub-dict of d2
d1.items() <= d2.items()
# Get items in d1 not found in d2
difference = d1.items() - d2.items()
.
в Python 2.7. Вы можете использовать метод viewitems()
вместо items()
для достижения того же результата.
в Python 2.6 и ниже, ваша лучшая ставка состоит в том, чтобы повторить ключевые ключи в первом диктоме и проверять на включение во второй.
# Test if d1 is a subset of d2
all(k in d2 and d2[k] == d1[k] for k in d1)
.