Skip to content

Commit

Permalink
Adds does_not_raise context manager
Browse files Browse the repository at this point in the history
Addressing issues pytest-dev#4324 and pytest-dev#1830
  • Loading branch information
arel committed Jan 24, 2019
1 parent 9905a73 commit 286a7b3
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 0 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Anthony Shaw
Anthony Sottile
Anton Lodder
Antony Lee
Arel Cordero
Armin Rigo
Aron Coyle
Aron Curzon
Expand Down
30 changes: 30 additions & 0 deletions src/_pytest/python_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pprint
import sys
import warnings
from contextlib import contextmanager
from decimal import Decimal
from numbers import Number

Expand Down Expand Up @@ -726,3 +727,32 @@ def __exit__(self, *tp):
if self.match_expr is not None and suppress_exception:
self.excinfo.match(self.match_expr)
return suppress_exception


# builtin pytest.does_not_raise helper


@contextmanager
def does_not_raise():
r"""
This context manager is a complement to ``pytest.raises()`` that does
*not* catch any exceptions raised by the code block.
This is essentially a no-op but is useful when
conditionally parameterizing tests that may or may not
raise an error. For example::
@pytest.mark.parametrize('example_input,expectation', [
(3, does_not_raise()),
(2, does_not_raise()),
(1, does_not_raise()),
(0, raises(ZeroDivisionError)),
])
def test_division(example_input, expectation):
'''Test how much I know division.'''
with expectation:
assert (6 / example_input) is not None
"""

yield
2 changes: 2 additions & 0 deletions src/pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from _pytest.python import Module
from _pytest.python import Package
from _pytest.python_api import approx
from _pytest.python_api import does_not_raise
from _pytest.python_api import raises
from _pytest.recwarn import deprecated_call
from _pytest.recwarn import warns
Expand All @@ -50,6 +51,7 @@
"cmdline",
"Collector",
"deprecated_call",
"does_not_raise",
"exit",
"fail",
"File",
Expand Down
40 changes: 40 additions & 0 deletions testing/python/raises.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,46 @@ def test_raise_wrong_exception_passes_by():
result = testdir.runpytest()
result.stdout.fnmatch_lines(["*3 passed*"])

def test_does_not_raise(self, testdir):
testdir.makepyfile(
"""
import pytest
import _pytest._code
@pytest.mark.parametrize('example_input,expectation', [
(3, pytest.does_not_raise()),
(2, pytest.does_not_raise()),
(1, pytest.does_not_raise()),
(0, pytest.raises(ZeroDivisionError)),
])
def test_division(example_input, expectation):
'''Test how much I know division.'''
with expectation:
assert (6 / example_input) is not None
"""
)
result = testdir.runpytest()
result.stdout.fnmatch_lines(["*4 passed*"])

def test_does_not_raise_does_raise(self, testdir):
testdir.makepyfile(
"""
import pytest
import _pytest._code
@pytest.mark.parametrize('example_input,expectation', [
(0, pytest.does_not_raise()),
(1, pytest.raises(ZeroDivisionError)),
])
def test_division(example_input, expectation):
'''Test how much I know division.'''
with expectation:
assert (6 / example_input) is not None
"""
)
result = testdir.runpytest()
result.stdout.fnmatch_lines(["*2 failed*"])

def test_noclass(self):
with pytest.raises(TypeError):
pytest.raises("wrong", lambda: None)
Expand Down

0 comments on commit 286a7b3

Please sign in to comment.