Python unittest's assertDictContainsSubset recommended alternative [duplicate] Python unittest's assertDictContainsSubset recommended alternative [duplicate] python-3.x python-3.x

Python unittest's assertDictContainsSubset recommended alternative [duplicate]


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))


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.


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 unittestclass 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.