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.

Andrew has offered a solution that uses assertEqual. But, it is useful for future readers, to know two alternative solutions that are more concise. First one uses issubset method of a set:

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

But there is yet another simpler more Pythonic way to do this:

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

The pitfall of the second solution is that you would not know which keys of the superset are missing from the subset.

However, both solutions would fail if your values have unhashable variables (such as dict) inside them.