I have some tests in Python written in unittest. I want to check that some of my dictionaries contain at least certain attributes equal to certain values. If there are extra values, that would be fine. assertDictContainsSubset
would be perfect, except that it's deprecated. Is there a better thing that I should be using or should I just recursively assert the contents to be equal if they are in the target dictionary?
The docs recommend using addTypeEqualityFunc
, but I do want to use the normal assertEqual
for dicts in some cases.
On Python 3.9+, use the dictionary union operator.
Change
assertDictContainsSubset(a, b)
to
assertEqual(b, b | a)
On older versions of Python, change it to
assertEqual(b, {**b, **a})
Note the order of the arguments, assertDictContainsSubset
put the "larger" dictionary (b
) second and the subset (a
) first, but it makes more sense to put the larger dictionary (b
) first (which is why assertDictContainsSubset
was removed in the first place).
This creates a copy of b
then iterates over a
, setting any keys to their value in a
and then compares that result against the original b
. If you can add all the keys/values of a
to b
and still have the same dictionary, it means a
doesn't contain any keys that aren't in b
and all the keys it contains have the same values as they do in b
, i.e. a
is a subset of b
.
If you were testing if dict A is a subset of dict B, I think I would write a function that tries to extract the content of dict A from dict B making a new dict C and then assertEqual(A,C).
def extractDictAFromB(A,B):
return dict([(k,B[k]) for k in A.keys() if k in B.keys()])
then you could just do
assertEqual(A,extractDictAFromB(A,B))
Extending on @bman's answer, exploiting that the comparison operators for set-like objects are overloaded as subset operators, you can use assertGreaterEqual
for (arguably) better error messages.
Compare the two tests:
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()
The result is:
======================================================================
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)])
----------------------------------------------------------------------
With assertGreaterEqual
, you can see the contents of the two dictionaries from the error message.
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