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.