40

Trying to assert that two dictionaries that have nested contents are equal to each other (order doesn't matter) with pytest. What's the pythonic way to do this?

John Mike
  • 1,475
  • 2
  • 14
  • 23

6 Answers6

38

Don't spend your time writing this logic yourself. Just use the functions provided by the default testing library unittest

from unittest import TestCase
TestCase().assertDictEqual(expected_dict, actual_dict)
Vincent Claes
  • 2,937
  • 3
  • 31
  • 52
26

pytest's magic is clever enough. By writing

assert {'a': {'b': 2, 'c': {'d': 4} } } == {'a': {'b': 2, 'c': {'d': 4} } }

you will have a nested test on equality.

Hawkeye Parker
  • 6,680
  • 7
  • 40
  • 44
linqu
  • 9,900
  • 7
  • 52
  • 62
9

I guess a simple assert equality test should be okay:

>>> d1 = {n: chr(n+65) for n in range(10)}
>>> d2 = {n: chr(n+65) for n in range(10)}
>>> d1 == d2
True
>>> l1 = [1, 2, 3]
>>> l2 = [1, 2, 3]
>>> d2[10] = l2
>>> d1[10] = l1
>>> d1 == d2
True
>>> class Example:
    stub_prop = None
>>> e1 = Example()
>>> e2 = Example()
>>> e2.stub_prop = 10
>>> e1.stub_prop = 'a'
>>> d1[11] = e1
>>> d2[11] = e2
>>> d1 == d2
False
Szabolcs
  • 3,730
  • 14
  • 34
6

General purpose way is to:

import json

# Make sure you sort any lists in the dictionary before dumping to a string

dictA_str = json.dumps(dictA, sort_keys=True)
dictB_str = json.dumps(dictB, sort_keys=True)

assert dictA_str == dictB_str
William
  • 677
  • 6
  • 16
  • 3
    works, but it's very tedious to find the difference between the two objects afterwards – linqu Jan 29 '21 at 20:53
0
assert all(v == actual_dict[k] for k,v expected_dict.items()) and len(expected_dict) == len(actual_dict)
  • 3
    This is unnecessary. If two dicts are equal then necessarily their lengths will be the same, and so will be their elements. Barely `dict1==dict2` does the trick. Also to be rigurous, if item per item check was neccesary, you would need to go over the nested elements too. –  Aug 23 '18 at 21:26
  • Said simple evaluation does exactly a multi-dimension-wise check, as opposed to the `is` operator, that solely checks for the memory pointer. –  Aug 23 '18 at 21:29
-4

your question is not very specific but with what i can understand, you are either trying to check if the length are the same

a = [1,5,3,6,3,2,4]
b = [5,3,2,1,3,5,3]

if (len(a) == len(b)):
    print True
else:
    print false

or checking if the list values are the same

import collections

compare = lambda x, y: collections.Counter(x) == collections.Counter(y)
compare([1,2,3], [1,2,3,3])
print compare #answer would be false
compare([1,2,3], [1,2,3])
print compare #answer would be true

but for dictionaries you could also use

x = dict(a=1, b=2)
y = dict(a=2, b=2)

if(x == y):
    print True
else:
    print False
Adeojo Emmanuel IMM
  • 1,934
  • 1
  • 17
  • 26