Make sure reference and actual align

This commit is contained in:
Jonathan Lange 2015-12-21 19:20:41 +00:00
parent dc3d75cbae
commit 331c6270da
3 changed files with 91 additions and 27 deletions

View File

@ -66,19 +66,35 @@ class _BinaryComparison(object):
class _BinaryMismatch(Mismatch):
"""Two things did not match."""
def __init__(self, expected, mismatch_string, other):
self.expected = expected
def __init__(self, actual, mismatch_string, reference,
reference_on_right=True):
self._actual = actual
self._mismatch_string = mismatch_string
self.other = other
self._reference = reference
self._reference_on_right = reference_on_right
@property
def expected(self):
# XXX: Deprecated.
return self._reference
@property
def other(self):
# XXX: Deprecated.
return self._actual
def describe(self):
left = repr(self.expected)
right = repr(self.other)
if len(left) + len(right) > 70:
actual = repr(self._actual)
reference = repr(self._reference)
if len(actual) + len(reference) > 70:
return "%s:\nreference = %s\nactual = %s\n" % (
self._mismatch_string, _format(self.expected),
_format(self.other))
self._mismatch_string, _format(self._reference),
_format(self._actual))
else:
if self._reference_on_right:
left, right = actual, reference
else:
left, right = reference, actual
return "%s %s %s" % (left, self._mismatch_string, right)
@ -89,6 +105,26 @@ class Equals(_BinaryComparison):
mismatch_string = '!='
class _FlippedEquals(object):
"""Matches if the items are equal.
Exactly like ``Equals`` except that the short mismatch message is "
$reference != $actual" rather than "$actual != $reference". This allows
for ``TestCase.assertEqual`` to use a matcher but still have the order of
items in the error message align with the order of items in the call to
the assertion.
"""
def __init__(self, expected):
self._expected = expected
def match(self, other):
mismatch = Equals(self._expected).match(other)
if not mismatch:
return None
return _BinaryMismatch(other, '!=', self._expected, False)
class NotEquals(_BinaryComparison):
"""Matches if the items are not equal.
@ -143,7 +179,7 @@ class SameMembers(Matcher):
return PostfixedMismatch(
"\nmissing: %s\nextra: %s" % (
_format(expected_only), _format(observed_only)),
_BinaryMismatch(self.expected, 'elements differ', observed))
_BinaryMismatch(observed, 'elements differ', self.expected))
class DoesNotStartWith(Mismatch):

View File

@ -48,6 +48,7 @@ from testtools.matchers import (
Not,
Raises,
)
from testtools.matchers._basic import _FlippedEquals
from testtools.monkey import patch
from testtools.runtest import RunTest
from testtools.testresult import (
@ -346,8 +347,8 @@ class TestCase(unittest.TestCase):
:param observed: The observed value.
:param message: An optional message to include in the error.
"""
matcher = Equals(observed)
self.assertThat(expected, matcher, message)
matcher = _FlippedEquals(expected)
self.assertThat(observed, matcher, message)
failUnlessEqual = assertEquals = assertEqual

View File

@ -55,41 +55,61 @@ class Test_BinaryMismatch(TestCase):
def test_long_bytes(self):
one_line_b = self._long_b.replace(_b("\n"), _b(" "))
mismatch = _BinaryMismatch(one_line_b, "!~", self._long_b)
self.assertEqual(mismatch.describe(),
"%s:\nreference = %s\nactual = %s\n" % ("!~",
self.assertEqual(
mismatch.describe(),
"%s:\nreference = %s\nactual = %s\n" % (
"!~",
text_repr(self._long_b, multiline=True),
text_repr(one_line_b),
text_repr(self._long_b, multiline=True)))
)
)
def test_long_unicode(self):
one_line_u = self._long_u.replace("\n", " ")
mismatch = _BinaryMismatch(one_line_u, "!~", self._long_u)
self.assertEqual(mismatch.describe(),
"%s:\nreference = %s\nactual = %s\n" % ("!~",
self.assertEqual(
mismatch.describe(),
"%s:\nreference = %s\nactual = %s\n" % (
"!~",
text_repr(self._long_u, multiline=True),
text_repr(one_line_u),
text_repr(self._long_u, multiline=True)))
)
)
def test_long_mixed_strings(self):
mismatch = _BinaryMismatch(self._long_b, "!~", self._long_u)
self.assertEqual(mismatch.describe(),
"%s:\nreference = %s\nactual = %s\n" % ("!~",
self.assertEqual(
mismatch.describe(),
"%s:\nreference = %s\nactual = %s\n" % (
"!~",
text_repr(self._long_u, multiline=True),
text_repr(self._long_b, multiline=True),
text_repr(self._long_u, multiline=True)))
)
)
def test_long_bytes_and_object(self):
obj = object()
mismatch = _BinaryMismatch(self._long_b, "!~", obj)
self.assertEqual(mismatch.describe(),
"%s:\nreference = %s\nactual = %s\n" % ("!~",
self.assertEqual(
mismatch.describe(),
"%s:\nreference = %s\nactual = %s\n" % (
"!~",
repr(obj),
text_repr(self._long_b, multiline=True),
repr(obj)))
)
)
def test_long_unicode_and_object(self):
obj = object()
mismatch = _BinaryMismatch(self._long_u, "!~", obj)
self.assertEqual(mismatch.describe(),
"%s:\nreference = %s\nactual = %s\n" % ("!~",
self.assertEqual(
mismatch.describe(),
"%s:\nreference = %s\nactual = %s\n" % (
"!~",
repr(obj),
text_repr(self._long_u, multiline=True),
repr(obj)))
)
)
class TestEqualsInterface(TestCase, TestMatchersInterface):
@ -100,7 +120,14 @@ class TestEqualsInterface(TestCase, TestMatchersInterface):
str_examples = [("Equals(1)", Equals(1)), ("Equals('1')", Equals('1'))]
describe_examples = [("2 != 1", 2, Equals(1))]
describe_examples = [
("2 != 1", 2, Equals(1)),
(("!=:\n"
"reference = 'abcdefghijklmnopqrstuvwxyz0123456789'\n"
"actual = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'\n"),
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
Equals('abcdefghijklmnopqrstuvwxyz0123456789')),
]
class TestNotEqualsInterface(TestCase, TestMatchersInterface):