Adds `does_not_raise` context manager

Addressing issues #4324 and #1830
This commit is contained in:
Arel Cordero 2019-01-24 21:53:14 +00:00
parent 16f8cdac95
commit afe9fd5ffd
4 changed files with 73 additions and 0 deletions

View File

@ -27,6 +27,7 @@ Anthony Shaw
Anthony Sottile Anthony Sottile
Anton Lodder Anton Lodder
Antony Lee Antony Lee
Arel Cordero
Armin Rigo Armin Rigo
Aron Coyle Aron Coyle
Aron Curzon Aron Curzon

View File

@ -4,6 +4,7 @@ import math
import pprint import pprint
import sys import sys
import warnings import warnings
from contextlib import contextmanager
from decimal import Decimal from decimal import Decimal
from numbers import Number from numbers import Number
@ -726,3 +727,32 @@ class RaisesContext(object):
if self.match_expr is not None and suppress_exception: if self.match_expr is not None and suppress_exception:
self.excinfo.match(self.match_expr) self.excinfo.match(self.match_expr)
return suppress_exception 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

View File

@ -32,6 +32,7 @@ from _pytest.python import Instance
from _pytest.python import Module from _pytest.python import Module
from _pytest.python import Package from _pytest.python import Package
from _pytest.python_api import approx from _pytest.python_api import approx
from _pytest.python_api import does_not_raise
from _pytest.python_api import raises from _pytest.python_api import raises
from _pytest.recwarn import deprecated_call from _pytest.recwarn import deprecated_call
from _pytest.recwarn import warns from _pytest.recwarn import warns
@ -50,6 +51,7 @@ __all__ = [
"cmdline", "cmdline",
"Collector", "Collector",
"deprecated_call", "deprecated_call",
"does_not_raise",
"exit", "exit",
"fail", "fail",
"File", "File",

View File

@ -94,6 +94,46 @@ class TestRaises(object):
result = testdir.runpytest() result = testdir.runpytest()
result.stdout.fnmatch_lines(["*3 passed*"]) 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): def test_noclass(self):
with pytest.raises(TypeError): with pytest.raises(TypeError):
pytest.raises("wrong", lambda: None) pytest.raises("wrong", lambda: None)