def test_verbose_description(self): matchee = 2 matcher = Equals(3) mismatch = matcher.match(2) e = MismatchError(matchee, matcher, mismatch, True) expected = ( "Match failed. Matchee: %r\n" "Matcher: %s\n" "Difference: %s\n" % (matchee, matcher, matcher.match(matchee).describe()) ) self.assertEqual(expected, str(e))
def test_verbose_description(self): matchee = 2 matcher = Equals(3) mismatch = matcher.match(2) e = MismatchError(matchee, matcher, mismatch, True) expected = ('Match failed. Matchee: %r\n' 'Matcher: %s\n' 'Difference: %s\n' % ( matchee, matcher, matcher.match(matchee).describe(), )) self.assertEqual(expected, str(e))
class FileContains(Matcher): """Matches if the given file has the specified contents. This differs from testtools' matcher in that it is strict about binary and text; a comparison of text must be done with an encoding. """ def __init__(self, contents=None, matcher=None, encoding=None): """Construct a ``FileContains`` matcher. Can be used in a basic mode where the file contents are compared for equality against the expected file contents (by passing ``contents``). Can also be used in a more advanced way where the file contents are matched against an arbitrary matcher (by passing ``matcher`` instead). :param contents: If specified, match the contents of the file with these contents. :param matcher: If specified, match the contents of the file against this matcher. :param encoding: If specified, the file is read in text mode with the given encoding; ``contents`` should be a Unicode string, or ``matcher`` should expect to compare against one. If ``encoding`` is not specified or is ``None``, the comparison is done byte-wise; ``contents`` should be a byte string, or ``matcher`` should expect to compare against one. """ if contents is None and matcher is None: raise AssertionError( "Must provide one of `contents` or `matcher`.") if contents is not None and matcher is not None: raise AssertionError( "Must provide either `contents` or `matcher`, not both.") if matcher is None: self.matcher = Equals(contents) else: self.matcher = matcher self.encoding = encoding def match(self, path): mismatch = PathExists().match(path) if mismatch is not None: return mismatch if self.encoding is None: # Binary match. with open(path, "rb") as fd: actual_contents = fd.read() else: # Text/Unicode match. with open(path, "r", encoding=self.encoding) as fd: actual_contents = fd.read() return self.matcher.match(actual_contents) def __str__(self): if self.encoding is None: return ("File at path exists and its contents (unencoded; raw) " "match %s" % (self.matcher, )) else: return ("File at path exists and its contents (encoded as %s) " "match %s" % (self.encoding, self.matcher))
def test_assertThat_verbose_output(self): matchee = "foo" matcher = Equals("bar") expected = ( "Match failed. Matchee: %r\n" "Matcher: %s\n" "Difference: %s\n" % (matchee, matcher, matcher.match(matchee).describe()) ) self.assertFails(expected, self.assertThat, matchee, matcher, verbose=True)
def test_assertThat_verbose_output(self): matchee = 'foo' matcher = Equals('bar') expected = ( 'Match failed. Matchee: %r\n' 'Matcher: %s\n' 'Difference: %s\n' % ( matchee, matcher, matcher.match(matchee).describe(), )) self.assertFails( expected, self.assertThat, matchee, matcher, verbose=True)
def test_file_exists_content_mismatch(self, observed, expected): """ If the file exists, the content is matched against the given matcher. If it mismatches, the message includes both the filename and the message from the underlying matcher. """ assume(observed != expected) matcher = Equals(expected) path = self.make_temporary_path() path.setContent(observed) mismatch = file_contents(matcher).match(path) self.assertThat( mismatch.describe(), Equals('%s has unexpected contents:\n%s' % (path.path, matcher.match(observed).describe())))
def test_verbose_unicode(self): # When assertThat is given matchees or matchers that contain non-ASCII # unicode strings, we can still provide a meaningful error. matchee = '\xa7' matcher = Equals('a') mismatch = matcher.match(matchee) expected = ('Match failed. Matchee: %s\n' 'Matcher: %s\n' 'Difference: %s\n' % ( text_repr(matchee), matcher, mismatch.describe(), )) e = MismatchError(matchee, matcher, mismatch, True) self.assertEqual(expected, str(e))
def test_file_exists_content_mismatch(self, observed, expected): """ If the file exists, the content is matched against the given matcher. If it mismatches, the message includes both the filename and the message from the underlying matcher. """ assume(observed != expected) matcher = Equals(expected) path = self.make_temporary_path() path.setContent(observed) mismatch = file_contents(matcher).match(path) self.assertThat( mismatch.describe(), Equals( '%s has unexpected contents:\n%s' % (path.path, matcher.match(observed).describe())))
def test_assertThat_verbose_unicode(self): # When assertThat is given matchees or matchers that contain non-ASCII # unicode strings, we can still provide a meaningful error. matchee = _u('\xa7') matcher = Equals(_u('a')) expected = ( 'Match failed. Matchee: %s\n' 'Matcher: %s\n' 'Difference: %s\n\n' % ( repr(matchee).replace("\\xa7", matchee), matcher, matcher.match(matchee).describe(), )) e = self.assertRaises( self.failureException, self.assertThat, matchee, matcher, verbose=True) self.assertEqual(expected, self.get_error_string(e))
def test_verbose_unicode(self): # When assertThat is given matchees or matchers that contain non-ASCII # unicode strings, we can still provide a meaningful error. matchee = _u("\xa7") matcher = Equals(_u("a")) mismatch = matcher.match(matchee) expected = ( "Match failed. Matchee: %s\n" "Matcher: %s\n" "Difference: %s\n" % (text_repr(matchee), matcher, mismatch.describe()) ) e = MismatchError(matchee, matcher, mismatch, True) if str_is_unicode: actual = str(e) else: actual = unicode(e) # Using str() should still work, and return ascii only self.assertEqual(expected.replace(matchee, matchee.encode("unicode-escape")), str(e).decode("ascii")) self.assertEqual(expected, actual)
class IsResponse(Matcher): def __init__(self, expected_content, expected_code=200, decode=None): """Construct a new IsResponse matcher. :param expected_content: The content you want to match against the response body. This can either be a matcher, a string, or a bytestring. :param expected_code: Tht HTTP status code you want to match against. :param decode: Whether to decode the response data according to the response charset. This can either be set implicitly or explicitly. If the 'expected_content' parameter is a string, this will implicitly be set to True. If 'expected_content' is a bytestring, this will be set to False. If 'expected_content' is a matcher, this will be set to True. Setting this parameter to a value explicitly disables this implicit behavior. """ if isinstance(expected_content, str): self._decode = True expected_content = Equals(expected_content) elif isinstance(expected_content, bytes): self._decode = False expected_content = Equals(expected_content) else: self._decode = decode or True self.expected_content = expected_content self.expected_code = Equals(expected_code) def match(self, response): mismatch = self.expected_code.match(response.status_code) if mismatch: return mismatch data = response.data if self._decode: data = data.decode(response.charset) return self.expected_content.match(data) def __str__(self): return "IsResponse(%r, %r)" % ( self.expected_content, self.expected_code)
def test_verbose_unicode(self): # When assertThat is given matchees or matchers that contain non-ASCII # unicode strings, we can still provide a meaningful error. matchee = _u('\xa7') matcher = Equals(_u('a')) mismatch = matcher.match(matchee) expected = ('Match failed. Matchee: %s\n' 'Matcher: %s\n' 'Difference: %s\n' % ( text_repr(matchee), matcher, mismatch.describe(), )) e = MismatchError(matchee, matcher, mismatch, True) if str_is_unicode: actual = str(e) else: actual = unicode(e) # Using str() should still work, and return ascii only self.assertEqual( expected.replace(matchee, matchee.encode("unicode-escape")), str(e).decode("ascii")) self.assertEqual(expected, actual)
def test_assertThat_output(self): matchee = 'foo' matcher = Equals('bar') expected = matcher.match(matchee).describe() self.assertFails(expected, self.assertThat, matchee, matcher)
def test_default_description_unicode(self): matchee = '\xa7' matcher = Equals('a') mismatch = matcher.match(matchee) e = MismatchError(matchee, matcher, mismatch) self.assertEqual(mismatch.describe(), str(e))
def test_assertThat_output(self): matchee = 'foo' matcher = Equals('bar') expected = matcher.match(matchee).describe() self.assertFails(expected, self.assert_that_callable, matchee, matcher)
def test_default_description_unicode(self): matchee = _u('\xa7') matcher = Equals(_u('a')) mismatch = matcher.match(matchee) e = MismatchError(matchee, matcher, mismatch) self.assertEqual(mismatch.describe(), str(e))
def wait_for(self, expected_value, timeout=10): """Wait up to 10 seconds for our value to change to *expected_value*. *expected_value* can be a testtools.matcher. Matcher subclass (like LessThan, for example), or an ordinary value. This works by refreshing the value using repeated dbus calls. :raises AssertionError: if the attribute was not equal to the expected value after 10 seconds. :raises RuntimeError: if the attribute you called this on was not constructed as part of an object. """ # It's guaranteed that our value is up to date, since __getattr__ # calls refresh_state. This if statement stops us waiting if the # value is already what we expect: if self == expected_value: return if self.name is None or self.parent is None: raise RuntimeError( "This variable was not constructed as part of " "an object. The wait_for method cannot be used.") def make_unicode(value): if isinstance(value, bytes): return value.decode('utf8') return value if hasattr(expected_value, 'expected'): expected_value.expected = make_unicode(expected_value.expected) # unfortunately not all testtools matchers derive from the Matcher # class, so we can't use issubclass, isinstance for this: match_fun = getattr(expected_value, 'match', None) is_matcher = match_fun and callable(match_fun) if not is_matcher: expected_value = Equals(expected_value) time_left = timeout while True: # TODO: These next three lines are duplicated from the parent... # can we just have this code once somewhere? _, new_state = self.parent._get_new_state() new_state = translate_state_keys(new_state) new_value = new_state[self.name][1:] if len(new_value) == 1: new_value = make_unicode(new_value[0]) # Support for testtools.matcher classes: mismatch = expected_value.match(new_value) if mismatch: failure_msg = mismatch.describe() else: self.parent._set_properties(new_state) return if time_left >= 1: sleep(1) time_left -= 1 else: sleep(time_left) break raise AssertionError( "After %.1f seconds test on %s.%s failed: %s" % (timeout, self.parent.__class__.__name__, self.name, failure_msg))