Implement ExceptionInfo.match() to match regexp on str(exception)

This implements similar functionality to
unittest.TestCase.assertRegexpMatches()

closes #372
This commit is contained in:
Omar Kohl 2016-04-02 17:24:08 +02:00
parent fed89ef549
commit c578226d43
4 changed files with 58 additions and 0 deletions

View File

@ -18,6 +18,10 @@
* New Add ability to add global properties in the final xunit output file. * New Add ability to add global properties in the final xunit output file.
Thanks `@tareqalayan`_ for the complete PR `#1454`_). Thanks `@tareqalayan`_ for the complete PR `#1454`_).
* New ``ExceptionInfo.match()`` method to match a regular expression on the
string representation of an exception. Closes proposal `#372`_.
Thanks `@omarkohl`_ for the complete PR (`#1502`_) and `@nicoddemus`_ for the
implementation tips.
* *
@ -38,6 +42,7 @@
.. _@kalekundert: https://github.com/kalekundert .. _@kalekundert: https://github.com/kalekundert
.. _@tareqalayan: https://github.com/tareqalayan .. _@tareqalayan: https://github.com/tareqalayan
.. _@palaviv: https://github.com/palaviv .. _@palaviv: https://github.com/palaviv
.. _@omarkohl: https://github.com/omarkohl
.. _#1428: https://github.com/pytest-dev/pytest/pull/1428 .. _#1428: https://github.com/pytest-dev/pytest/pull/1428
.. _#1444: https://github.com/pytest-dev/pytest/pull/1444 .. _#1444: https://github.com/pytest-dev/pytest/pull/1444
@ -45,6 +50,8 @@
.. _#1454: https://github.com/pytest-dev/pytest/pull/1454 .. _#1454: https://github.com/pytest-dev/pytest/pull/1454
.. _#1468: https://github.com/pytest-dev/pytest/pull/1468 .. _#1468: https://github.com/pytest-dev/pytest/pull/1468
.. _#1474: https://github.com/pytest-dev/pytest/pull/1474 .. _#1474: https://github.com/pytest-dev/pytest/pull/1474
.. _#1502: https://github.com/pytest-dev/pytest/pull/1502
.. _#372: https://github.com/pytest-dev/pytest/issues/372
2.9.2.dev1 2.9.2.dev1

View File

@ -1,5 +1,6 @@
import sys import sys
from inspect import CO_VARARGS, CO_VARKEYWORDS from inspect import CO_VARARGS, CO_VARKEYWORDS
import re
import py import py
@ -427,6 +428,19 @@ class ExceptionInfo(object):
loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly()) loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
return unicode(loc) return unicode(loc)
def match(self, regexp):
"""
Match the regular expression 'regexp' on the string representation of
the exception. If it matches then True is returned (so that it is
possible to write 'assert excinfo.match()'). If it doesn't match an
AssertionError is raised.
"""
__tracebackhide__ = True
if not re.search(regexp, str(self.value)):
assert 0, "Pattern '{0!s}' not found in '{1!s}'".format(
regexp, self.value)
return True
class FormattedExcinfo(object): class FormattedExcinfo(object):
""" presenting information about failing Functions and Generators. """ """ presenting information about failing Functions and Generators. """

View File

@ -110,6 +110,24 @@ exceptions your own code is deliberately raising, whereas using
like documenting unfixed bugs (where the test describes what "should" happen) like documenting unfixed bugs (where the test describes what "should" happen)
or bugs in dependencies. or bugs in dependencies.
If you want to test that a regular expression matches on the string
representation of an exception (like the ``TestCase.assertRaisesRegexp`` method
from ``unittest``) you can use the ``ExceptionInfo.match`` method::
import pytest
def myfunc():
raise ValueError("Exception 123 raised")
def test_match():
with pytest.raises(ValueError) as excinfo:
myfunc()
excinfo.match(r'.* 123 .*')
The regexp parameter of the ``match`` method is matched with the ``re.search``
function. So in the above example ``excinfo.match('123')`` would have worked as
well.
.. _`assertwarns`: .. _`assertwarns`:

View File

@ -323,6 +323,25 @@ def test_codepath_Queue_example():
assert path.basename.lower() == "queue.py" assert path.basename.lower() == "queue.py"
assert path.check() assert path.check()
def test_match_succeeds():
with pytest.raises(ZeroDivisionError) as excinfo:
0 / 0
excinfo.match(r'.*zero.*')
def test_match_raises_error(testdir):
testdir.makepyfile("""
import pytest
def test_division_zero():
with pytest.raises(ZeroDivisionError) as excinfo:
0 / 0
excinfo.match(r'[123]+')
""")
result = testdir.runpytest()
assert result.ret != 0
result.stdout.fnmatch_lines([
"*AssertionError*Pattern*[123]*not found*",
])
class TestFormattedExcinfo: class TestFormattedExcinfo:
def pytest_funcarg__importasmod(self, request): def pytest_funcarg__importasmod(self, request):
def importasmod(source): def importasmod(source):