Custom Matchers¶
Introduction¶
Expects can be extended by defining new matchers.
The matchers
module contains the bases for building
custom matchers.
Tutorial¶
The easiest way to define a new matcher is to extend the
Matcher
class and override the Matcher._match()
method.
For example, to define a matcher to check if a request object contains a given header takes <10 lines of code:
from expects.matchers import Matcher
class have_header(Matcher):
def __init__(self, expected):
self._expected = expected
def _match(self, request):
return self._expected in request.headers
An then you only need to import the new defined matcher and write your expectation:
from expects import expect
from my_custom_matchers import have_header
expect(my_request).to(have_header('Content-Type'))
Advanced¶
For more complex matchers you can override the Matcher
methods in order to achieve the needed behavior.
-
class
expects.matchers.
Matcher
¶ The
Matcher
class is the base class for all Expects matchers.It defines a set of methods to ease writting new matchers.
-
_description
(subject)¶ This method receives the subject of the expectation and returns a string with the description of the matcher to be used in failure messages.
By default returns a string with the following format:
'{name} {expected}'
Where name is based on the matcher class name and expected is the value passed to the constructor.
Parameters: subject – The target value of the expectation. Return type: a string
-
_failure_message
(subject)¶ This method will be called from an expectation only when the expectation is going to fail. It should return a string with the failure message.
By default returns a failure message with the following format:
'Expected {subject} to {description}'
With the passed subject and the result of calling the
_description()
method.Parameters: subject – The target value of the expectation. Return type: a string
-
_failure_message_negated
(subject)¶ Like the
_failure_message()
method but will be called when a negated expectation is going to fail. It should return a string with the failure message for the negated expectation.By default returns a failure message with the following format:
'Expected {subject} not to {description}'
Parameters: subject – The target value of the expectation. Return type: a string
-
_match
(subject)¶ This method will be called when the matcher is used in an expectation. It should be overwritten to implement the matcher logic. If not raises
NotImplementedError
.Receives the expectation subject as the unique positional argument and should return
True
if the matcher matches the subject andFalse
if it does not.Parameters: subject – The target value of the expectation. Return type: a boolean
-
_match_negated
(subject)¶ Like
_match()
but will be called when used in a negated expectation. It can be used to implement a custom logic for negated expectations.By default returns the result of
not self._match(subject)
.Parameters: subject – The target value of the expectation. Return type: a boolean
-
_match_value
(matcher, value)¶ This method receives a
Matcher
instance and a value to be matched as first and second arguments respectively, and returnsTrue
orFalse
depending on whether the value matches.If the argument passed as matcher does not implements the
Matcher
interface then theequal
built-in matcher is used.Examples:
>>> self._match_value('foo', 'foo') True >>> self._match_value('foo', 'bar') False >>> self._match_value(match('\w+'), 'foo') True
Parameters: - matcher – A matcher that will be used to match the given value.
- value – A value to test if matches.
Return type:
-
Testing¶
The testing
module provides helpers to ease the testing
of your custom matchers.
-
class
expects.testing.
failure
(message)¶ The
failure
context manager can be used to build assertions of your expectation failures. It tests that the code inside the context manager raises anAssertionError
and matches the given message (whether any has been specified).Parameters: message (an expects.matchers.Matcher
or string) – should match the failure message. If a string is passed, theend_with
matcher will be used by default.Raises: AssertionError
when no AssertionError was raised, the failure message didn’t match or another exception raised.Note
The
failure
context manager can be used without being called (for example, if you don’t want to specify a failure message).Examples:
>>> with failure: ... expect(object()).to(have_property('foo'))
>>> with failure("to have property 'foo'"): ... expect(object()).to(have_property('foo'))
>>> with failure(end_with("have property 'foo'")): ... expect(object()).to(have_property('foo'))
>>> with failure("to have property '__class__'"): ... expect(object()).to(have_property('__class__')) Traceback (most recent call last): File "<stdin>", line 2, in <module> File "expects/testing.py", line 40, in __exit__ raise AssertionError('Expected AssertionError to be raised') AssertionError: Expected AssertionError to be raised