Merge pull request #4682 from arel/parameterize-conditional-raises-document-only
Document parametrizing conditional raises
This commit is contained in:
commit
2264db7f4a
1
AUTHORS
1
AUTHORS
|
@ -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
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Document how to use ``raises`` and ``does_not_raise`` to write parametrized tests with conditional raises.
|
|
@ -565,3 +565,50 @@ As the result:
|
||||||
- The test ``test_eval[1+7-8]`` passed, but the name is autogenerated and confusing.
|
- The test ``test_eval[1+7-8]`` passed, but the name is autogenerated and confusing.
|
||||||
- The test ``test_eval[basic_2+4]`` passed.
|
- The test ``test_eval[basic_2+4]`` passed.
|
||||||
- The test ``test_eval[basic_6*9]`` was expected to fail and did fail.
|
- The test ``test_eval[basic_6*9]`` was expected to fail and did fail.
|
||||||
|
|
||||||
|
.. _`parametrizing_conditional_raising`:
|
||||||
|
|
||||||
|
Parametrizing conditional raising
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
Use :func:`pytest.raises` with the
|
||||||
|
:ref:`pytest.mark.parametrize ref` decorator to write parametrized tests
|
||||||
|
in which some tests raise exceptions and others do not.
|
||||||
|
|
||||||
|
It is helpful to define a no-op context manager ``does_not_raise`` to serve
|
||||||
|
as a complement to ``raises``. For example::
|
||||||
|
|
||||||
|
from contextlib import contextmanager
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def does_not_raise():
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('example_input,expectation', [
|
||||||
|
(3, does_not_raise()),
|
||||||
|
(2, does_not_raise()),
|
||||||
|
(1, 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
|
||||||
|
|
||||||
|
In the example above, the first three test cases should run unexceptionally,
|
||||||
|
while the fourth should raise ``ZeroDivisionError``.
|
||||||
|
|
||||||
|
If you're only supporting Python 3.7+, you can simply use ``nullcontext``
|
||||||
|
to define ``does_not_raise``::
|
||||||
|
|
||||||
|
from contextlib import nullcontext as does_not_raise
|
||||||
|
|
||||||
|
Or, if you're supporting Python 3.3+ you can use::
|
||||||
|
|
||||||
|
from contextlib import ExitStack as does_not_raise
|
||||||
|
|
||||||
|
Or, if desired, you can ``pip install contextlib2`` and use::
|
||||||
|
|
||||||
|
from contextlib2 import ExitStack as does_not_raise
|
||||||
|
|
|
@ -621,6 +621,14 @@ def raises(expected_exception, *args, **kwargs):
|
||||||
...
|
...
|
||||||
>>> assert exc_info.type is ValueError
|
>>> assert exc_info.type is ValueError
|
||||||
|
|
||||||
|
**Using with** ``pytest.mark.parametrize``
|
||||||
|
|
||||||
|
When using :ref:`pytest.mark.parametrize ref`
|
||||||
|
it is possible to parametrize tests such that
|
||||||
|
some runs raise an exception and others do not.
|
||||||
|
|
||||||
|
See :ref:`parametrizing_conditional_raising` for an example.
|
||||||
|
|
||||||
**Legacy form**
|
**Legacy form**
|
||||||
|
|
||||||
It is possible to specify a callable by passing a to-be-called lambda::
|
It is possible to specify a callable by passing a to-be-called lambda::
|
||||||
|
|
|
@ -94,6 +94,54 @@ 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(
|
||||||
|
"""
|
||||||
|
from contextlib import contextmanager
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def does_not_raise():
|
||||||
|
yield
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('example_input,expectation', [
|
||||||
|
(3, does_not_raise()),
|
||||||
|
(2, does_not_raise()),
|
||||||
|
(1, 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(
|
||||||
|
"""
|
||||||
|
from contextlib import contextmanager
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def does_not_raise():
|
||||||
|
yield
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('example_input,expectation', [
|
||||||
|
(0, 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)
|
||||||
|
|
Loading…
Reference in New Issue