Skip to content

Commit 4dbd342

Browse files
committed
Test utils: add assertDictMatches
1 parent 9ac7d79 commit 4dbd342

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

tests/utils.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from contextlib import contextmanager
99
from io import StringIO
1010
from unittest import TestCase
11+
from unittest.util import safe_repr
1112

1213
from django.test import Client
1314

@@ -72,6 +73,38 @@ def sample_email_content(filename=SAMPLE_EMAIL_FILENAME):
7273
class AnymailTestMixin(TestCase):
7374
"""Helpful additional methods for Anymail tests"""
7475

76+
def assertDictMatches(self, expected, actual, msg=None):
77+
"""
78+
Tests that dict `expected` is a subset of `actual`. (That expected
79+
is *in* actual. Note the args are in the same needle, haystack
80+
order as assertIn.)
81+
"""
82+
# This is just assertDictContainsSubset, and the code is copied in from there.
83+
# (That was deprecated because apparently the arg order was confusing given the
84+
# name. The "matches" terminology is borrowed from several JS expect packages.)
85+
missing = []
86+
mismatched = []
87+
for key, value in expected.items():
88+
if key not in actual:
89+
missing.append(key)
90+
elif value != actual[key]:
91+
mismatched.append('%s, expected: %s, actual: %s' %
92+
(safe_repr(key), safe_repr(value),
93+
safe_repr(actual[key])))
94+
95+
if not (missing or mismatched):
96+
return
97+
98+
standardMsg = ''
99+
if missing:
100+
standardMsg = 'Missing: %s' % ','.join(safe_repr(m) for m in missing)
101+
if mismatched:
102+
if standardMsg:
103+
standardMsg += '; '
104+
standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
105+
106+
self.fail(self._formatMessage(msg, standardMsg))
107+
75108
@contextmanager
76109
def assertDoesNotWarn(self, disallowed_warning=Warning):
77110
"""Makes test error (rather than fail) if disallowed_warning occurs.

0 commit comments

Comments
 (0)