Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement ExceptionInfo.match() method #1502

Merged
merged 2 commits into from
Apr 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Michael Birtwell
Michael Droettboom
Mike Lundy
Nicolas Delaby
Omar Kohl
Pieter Mulder
Piotr Banaszkiewicz
Punyashloka Biswal
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
* New Add ability to add global properties in the final xunit output file.
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.

*

Expand All @@ -38,13 +42,16 @@
.. _@kalekundert: https://github.com/kalekundert
.. _@tareqalayan: https://github.com/tareqalayan
.. _@palaviv: https://github.com/palaviv
.. _@omarkohl: https://github.com/omarkohl

.. _#1428: https://github.com/pytest-dev/pytest/pull/1428
.. _#1444: https://github.com/pytest-dev/pytest/pull/1444
.. _#1441: https://github.com/pytest-dev/pytest/pull/1441
.. _#1454: https://github.com/pytest-dev/pytest/pull/1454
.. _#1468: https://github.com/pytest-dev/pytest/pull/1468
.. _#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
Expand Down
14 changes: 14 additions & 0 deletions _pytest/_code/code.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sys
from inspect import CO_VARARGS, CO_VARKEYWORDS
import re

import py

Expand Down Expand Up @@ -427,6 +428,19 @@ def __unicode__(self):
loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
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):
""" presenting information about failing Functions and Generators. """
Expand Down
18 changes: 18 additions & 0 deletions doc/en/assert.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,24 @@ exceptions your own code is deliberately raising, whereas using
like documenting unfixed bugs (where the test describes what "should" happen)
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`:

Expand Down
19 changes: 19 additions & 0 deletions testing/code/test_excinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,25 @@ def test_codepath_Queue_example():
assert path.basename.lower() == "queue.py"
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:
def pytest_funcarg__importasmod(self, request):
def importasmod(source):
Expand Down