Skip to content

Commit afe9fd5

Browse files
committed
Adds does_not_raise context manager
Addressing issues #4324 and #1830
1 parent 16f8cda commit afe9fd5

File tree

4 files changed

+73
-0
lines changed

4 files changed

+73
-0
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Anthony Shaw
2727
Anthony Sottile
2828
Anton Lodder
2929
Antony Lee
30+
Arel Cordero
3031
Armin Rigo
3132
Aron Coyle
3233
Aron Curzon

src/_pytest/python_api.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pprint
55
import sys
66
import warnings
7+
from contextlib import contextmanager
78
from decimal import Decimal
89
from numbers import Number
910

@@ -726,3 +727,32 @@ def __exit__(self, *tp):
726727
if self.match_expr is not None and suppress_exception:
727728
self.excinfo.match(self.match_expr)
728729
return suppress_exception
730+
731+
732+
# builtin pytest.does_not_raise helper
733+
734+
735+
@contextmanager
736+
def does_not_raise():
737+
r"""
738+
This context manager is a complement to ``pytest.raises()`` that does
739+
*not* catch any exceptions raised by the code block.
740+
741+
742+
This is essentially a no-op but is useful when
743+
conditionally parameterizing tests that may or may not
744+
raise an error. For example::
745+
746+
@pytest.mark.parametrize('example_input,expectation', [
747+
(3, does_not_raise()),
748+
(2, does_not_raise()),
749+
(1, does_not_raise()),
750+
(0, raises(ZeroDivisionError)),
751+
])
752+
def test_division(example_input, expectation):
753+
'''Test how much I know division.'''
754+
with expectation:
755+
assert (6 / example_input) is not None
756+
"""
757+
758+
yield

src/pytest.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from _pytest.python import Module
3333
from _pytest.python import Package
3434
from _pytest.python_api import approx
35+
from _pytest.python_api import does_not_raise
3536
from _pytest.python_api import raises
3637
from _pytest.recwarn import deprecated_call
3738
from _pytest.recwarn import warns
@@ -50,6 +51,7 @@
5051
"cmdline",
5152
"Collector",
5253
"deprecated_call",
54+
"does_not_raise",
5355
"exit",
5456
"fail",
5557
"File",

testing/python/raises.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,46 @@ def test_raise_wrong_exception_passes_by():
9494
result = testdir.runpytest()
9595
result.stdout.fnmatch_lines(["*3 passed*"])
9696

97+
def test_does_not_raise(self, testdir):
98+
testdir.makepyfile(
99+
"""
100+
import pytest
101+
import _pytest._code
102+
103+
@pytest.mark.parametrize('example_input,expectation', [
104+
(3, pytest.does_not_raise()),
105+
(2, pytest.does_not_raise()),
106+
(1, pytest.does_not_raise()),
107+
(0, pytest.raises(ZeroDivisionError)),
108+
])
109+
def test_division(example_input, expectation):
110+
'''Test how much I know division.'''
111+
with expectation:
112+
assert (6 / example_input) is not None
113+
"""
114+
)
115+
result = testdir.runpytest()
116+
result.stdout.fnmatch_lines(["*4 passed*"])
117+
118+
def test_does_not_raise_does_raise(self, testdir):
119+
testdir.makepyfile(
120+
"""
121+
import pytest
122+
import _pytest._code
123+
124+
@pytest.mark.parametrize('example_input,expectation', [
125+
(0, pytest.does_not_raise()),
126+
(1, pytest.raises(ZeroDivisionError)),
127+
])
128+
def test_division(example_input, expectation):
129+
'''Test how much I know division.'''
130+
with expectation:
131+
assert (6 / example_input) is not None
132+
"""
133+
)
134+
result = testdir.runpytest()
135+
result.stdout.fnmatch_lines(["*2 failed*"])
136+
97137
def test_noclass(self):
98138
with pytest.raises(TypeError):
99139
pytest.raises("wrong", lambda: None)

0 commit comments

Comments
 (0)