Skip to content

Commit

Permalink
add matching the error message to pytest.raises
Browse files Browse the repository at this point in the history
  • Loading branch information
Kriechi committed Feb 1, 2017
1 parent 3b47cb4 commit cfb7bec
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ New Features
* ``pytest.warns`` now checks for subclass relationship rather than
class equality. Thanks `@lesteve`_ for the PR (`#2166`_)

* ``pytest.raises`` now assert that the error message contains a certain text
with the `match_info` keyword argument. Thanks `@Kriechi`_ for the PR.


Changes
-------
Expand Down Expand Up @@ -56,6 +59,7 @@ Changes
.. _@fogo: https://github.com/fogo
.. _@mandeep: https://github.com/mandeep
.. _@unsignedint: https://github.com/unsignedint
.. _@Kriechi: https://github.com/Kriechi

.. _#1512: https://github.com/pytest-dev/pytest/issues/1512
.. _#1874: https://github.com/pytest-dev/pytest/pull/1874
Expand Down
17 changes: 15 additions & 2 deletions _pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,12 @@ def raises(expected_exception, *args, **kwargs):
...
>>> assert str(exc_info.value) == "value must be <= 10"
Or you can use the keyword argument ``match_info`` to assert that the
exception contains a certain text::
>>> with raises(ValueError, match_info='must be 0'):
... if value != 0:
... raise ValueError("value must be 0 or None")
Or you can specify a callable by passing a to-be-called lambda::
Expand Down Expand Up @@ -1194,11 +1200,15 @@ def raises(expected_exception, *args, **kwargs):
raise TypeError(msg % type(expected_exception))

message = "DID NOT RAISE {0}".format(expected_exception)
match_info = None

if not args:
if "message" in kwargs:
message = kwargs.pop("message")
return RaisesContext(expected_exception, message)
if "match_info" in kwargs:
match_info = kwargs.pop("match_info")
message += " with text '{0}'".format(match_info)
return RaisesContext(expected_exception, message, match_info)
elif isinstance(args[0], str):
code, = args
assert isinstance(code, str)
Expand All @@ -1222,9 +1232,10 @@ def raises(expected_exception, *args, **kwargs):
pytest.fail(message)

class RaisesContext(object):
def __init__(self, expected_exception, message):
def __init__(self, expected_exception, message, match_info):
self.expected_exception = expected_exception
self.message = message
self.match_info = match_info
self.excinfo = None

def __enter__(self):
Expand All @@ -1243,6 +1254,8 @@ def __exit__(self, *tp):
exc_type, value, traceback = tp
tp = exc_type, exc_type(value), traceback
self.excinfo.__init__(tp)
if self.match_info and not self.match_info.lower() in str(self.excinfo).lower():
pytest.fail(self.message)
suppress_exception = issubclass(self.excinfo.type, self.expected_exception)
if sys.version_info[0] == 2 and suppress_exception:
sys.exc_clear()
Expand Down
13 changes: 13 additions & 0 deletions testing/python/raises.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,16 @@ def __call__(self):
for o in gc.get_objects():
assert type(o) is not T


def test_raises_match_info(self):
msg = "with base 10"
with pytest.raises(ValueError, match_info=msg):
int('asdf')

try:
with pytest.raises(ValueError, match_info=msg):
int('asdf', base=16)
except pytest.raises.Exception as e:
assert e.msg == "DID NOT RAISE {0} with text '{1}'".format(repr(ValueError), msg)
else:
assert False, "Expected pytest.raises.Exception"

0 comments on commit cfb7bec

Please sign in to comment.