Deprecation of `msg=` for both `pytest.skip()` and `pytest.fail()`. (#8950)
* porting pytest.skip() to use reason=, adding tests * avoid adding **kwargs, it breaks other functionality, use optional msg= instead * deprecation of `pytest.fail(msg=...)` * fix bug with not capturing the returned reason value * pass reason= in acceptance async tests instead of msg= * finalising deprecations of `msg` in `pytest.skip()` and `pytest.fail()` * Update doc/en/deprecations.rst Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com> * Update doc/en/deprecations.rst Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com> * fix failing test after upstream merge * adding deprecation to `pytest.exit(msg=...)` * add docs for pytest.exit deprecations * finalising deprecation of msg for pytest.skip, pytest.exit and pytest.fail * hold a reference to the Scope instance to please mypy Co-authored-by: Bruno Oliveira <nicoddemus@gmail.com>
This commit is contained in:
parent
b7603fa730
commit
eb6c4493b2
|
@ -0,0 +1,5 @@
|
||||||
|
:func:`pytest.skip(msg=...) <pytest.skip>`, :func:`pytest.fail(msg=...) <pytest.fail>` and :func:`pytest.exit(msg=...) <pytest.exit>`
|
||||||
|
signatures now accept a ``reason`` argument instead of ``msg``. Using ``msg`` still works, but is deprecated and will be removed in a future release.
|
||||||
|
|
||||||
|
This was changed for consistency with :func:`pytest.mark.skip <pytest.mark.skip>` and :func:`pytest.mark.xfail <pytest.mark.xfail>` which both accept
|
||||||
|
``reason`` as an argument.
|
|
@ -56,6 +56,38 @@ In order to support the transition from ``py.path.local`` to :mod:`pathlib`, the
|
||||||
The accompanying ``py.path.local`` based paths have been deprecated: plugins which manually invoke those hooks should only pass the new ``pathlib.Path`` arguments, and users should change their hook implementations to use the new ``pathlib.Path`` arguments.
|
The accompanying ``py.path.local`` based paths have been deprecated: plugins which manually invoke those hooks should only pass the new ``pathlib.Path`` arguments, and users should change their hook implementations to use the new ``pathlib.Path`` arguments.
|
||||||
|
|
||||||
|
|
||||||
|
Passing ``msg=`` to ``pytest.skip``, ``pytest.fail`` or ``pytest.exit``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. deprecated:: 7.0
|
||||||
|
|
||||||
|
Passing the keyword argument ``msg`` to :func:`pytest.skip`, :func:`pytest.fail` or :func:`pytest.exit`
|
||||||
|
is now deprecated and ``reason`` should be used instead. This change is to bring consistency between these
|
||||||
|
functions and the``@pytest.mark.skip`` and ``@pytest.mark.xfail`` markers which already accept a ``reason`` argument.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def test_fail_example():
|
||||||
|
# old
|
||||||
|
pytest.fail(msg="foo")
|
||||||
|
# new
|
||||||
|
pytest.fail(reason="bar")
|
||||||
|
|
||||||
|
|
||||||
|
def test_skip_example():
|
||||||
|
# old
|
||||||
|
pytest.skip(msg="foo")
|
||||||
|
# new
|
||||||
|
pytest.skip(reason="bar")
|
||||||
|
|
||||||
|
|
||||||
|
def test_exit_example():
|
||||||
|
# old
|
||||||
|
pytest.exit(msg="foo")
|
||||||
|
# new
|
||||||
|
pytest.exit(reason="bar")
|
||||||
|
|
||||||
|
|
||||||
Implementing the ``pytest_cmdline_preparse`` hook
|
Implementing the ``pytest_cmdline_preparse`` hook
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -22,12 +22,12 @@ pytest.fail
|
||||||
|
|
||||||
**Tutorial**: :ref:`skipping`
|
**Tutorial**: :ref:`skipping`
|
||||||
|
|
||||||
.. autofunction:: pytest.fail
|
.. autofunction:: pytest.fail(reason, [pytrace=True, msg=None])
|
||||||
|
|
||||||
pytest.skip
|
pytest.skip
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
.. autofunction:: pytest.skip(msg, [allow_module_level=False])
|
.. autofunction:: pytest.skip(reason, [allow_module_level=False, msg=None])
|
||||||
|
|
||||||
.. _`pytest.importorskip ref`:
|
.. _`pytest.importorskip ref`:
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ pytest.xfail
|
||||||
pytest.exit
|
pytest.exit
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
.. autofunction:: pytest.exit
|
.. autofunction:: pytest.exit(reason, [returncode=False, msg=None])
|
||||||
|
|
||||||
pytest.main
|
pytest.main
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
|
@ -20,9 +20,6 @@ from typing import Union
|
||||||
import attr
|
import attr
|
||||||
import py
|
import py
|
||||||
|
|
||||||
from _pytest.outcomes import fail
|
|
||||||
from _pytest.outcomes import TEST_OUTCOME
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import NoReturn
|
from typing import NoReturn
|
||||||
from typing_extensions import Final
|
from typing_extensions import Final
|
||||||
|
@ -152,6 +149,8 @@ def getfuncargnames(
|
||||||
try:
|
try:
|
||||||
parameters = signature(function).parameters
|
parameters = signature(function).parameters
|
||||||
except (ValueError, TypeError) as e:
|
except (ValueError, TypeError) as e:
|
||||||
|
from _pytest.outcomes import fail
|
||||||
|
|
||||||
fail(
|
fail(
|
||||||
f"Could not determine arguments of {function!r}: {e}",
|
f"Could not determine arguments of {function!r}: {e}",
|
||||||
pytrace=False,
|
pytrace=False,
|
||||||
|
@ -324,6 +323,8 @@ def safe_getattr(object: Any, name: str, default: Any) -> Any:
|
||||||
are derived from BaseException instead of Exception (for more details
|
are derived from BaseException instead of Exception (for more details
|
||||||
check #2707).
|
check #2707).
|
||||||
"""
|
"""
|
||||||
|
from _pytest.outcomes import TEST_OUTCOME
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return getattr(object, name, default)
|
return getattr(object, name, default)
|
||||||
except TEST_OUTCOME:
|
except TEST_OUTCOME:
|
||||||
|
|
|
@ -114,6 +114,11 @@ WARNS_NONE_ARG = PytestDeprecationWarning(
|
||||||
" Replace pytest.warns(None) by simply pytest.warns()."
|
" Replace pytest.warns(None) by simply pytest.warns()."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
KEYWORD_MSG_ARG = UnformattedWarning(
|
||||||
|
PytestDeprecationWarning,
|
||||||
|
"pytest.{func}(msg=...) is now deprecated, use pytest.{func}(reason=...) instead",
|
||||||
|
)
|
||||||
|
|
||||||
# You want to make some `__init__` or function "private".
|
# You want to make some `__init__` or function "private".
|
||||||
#
|
#
|
||||||
# def my_private_function(some, args):
|
# def my_private_function(some, args):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""Exception classes and constants handling test outcomes as well as
|
"""Exception classes and constants handling test outcomes as well as
|
||||||
functions creating them."""
|
functions creating them."""
|
||||||
import sys
|
import sys
|
||||||
|
import warnings
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
@ -8,6 +9,8 @@ from typing import Optional
|
||||||
from typing import Type
|
from typing import Type
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
|
|
||||||
|
from _pytest.deprecated import KEYWORD_MSG_ARG
|
||||||
|
|
||||||
TYPE_CHECKING = False # Avoid circular import through compat.
|
TYPE_CHECKING = False # Avoid circular import through compat.
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
@ -110,28 +113,56 @@ def _with_exception(exception_type: _ET) -> Callable[[_F], _WithException[_F, _E
|
||||||
|
|
||||||
|
|
||||||
@_with_exception(Exit)
|
@_with_exception(Exit)
|
||||||
def exit(msg: str, returncode: Optional[int] = None) -> "NoReturn":
|
def exit(
|
||||||
|
reason: str = "", returncode: Optional[int] = None, *, msg: Optional[str] = None
|
||||||
|
) -> "NoReturn":
|
||||||
"""Exit testing process.
|
"""Exit testing process.
|
||||||
|
|
||||||
:param str msg: Message to display upon exit.
|
:param reason:
|
||||||
:param int returncode: Return code to be used when exiting pytest.
|
The message to show as the reason for exiting pytest. reason has a default value
|
||||||
|
only because `msg` is deprecated.
|
||||||
|
|
||||||
|
:param returncode:
|
||||||
|
Return code to be used when exiting pytest.
|
||||||
|
|
||||||
|
:param msg:
|
||||||
|
Same as ``reason``, but deprecated. Will be removed in a future version, use ``reason`` instead.
|
||||||
"""
|
"""
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
raise Exit(msg, returncode)
|
from _pytest.config import UsageError
|
||||||
|
|
||||||
|
if reason and msg:
|
||||||
|
raise UsageError(
|
||||||
|
"cannot pass reason and msg to exit(), `msg` is deprecated, use `reason`."
|
||||||
|
)
|
||||||
|
if not reason:
|
||||||
|
if msg is None:
|
||||||
|
raise UsageError("exit() requires a reason argument")
|
||||||
|
warnings.warn(KEYWORD_MSG_ARG.format(func="exit"), stacklevel=2)
|
||||||
|
reason = msg
|
||||||
|
raise Exit(reason, returncode)
|
||||||
|
|
||||||
|
|
||||||
@_with_exception(Skipped)
|
@_with_exception(Skipped)
|
||||||
def skip(msg: str = "", *, allow_module_level: bool = False) -> "NoReturn":
|
def skip(
|
||||||
|
reason: str = "", *, allow_module_level: bool = False, msg: Optional[str] = None
|
||||||
|
) -> "NoReturn":
|
||||||
"""Skip an executing test with the given message.
|
"""Skip an executing test with the given message.
|
||||||
|
|
||||||
This function should be called only during testing (setup, call or teardown) or
|
This function should be called only during testing (setup, call or teardown) or
|
||||||
during collection by using the ``allow_module_level`` flag. This function can
|
during collection by using the ``allow_module_level`` flag. This function can
|
||||||
be called in doctests as well.
|
be called in doctests as well.
|
||||||
|
|
||||||
:param bool allow_module_level:
|
:param reason:
|
||||||
|
The message to show the user as reason for the skip.
|
||||||
|
|
||||||
|
:param allow_module_level:
|
||||||
Allows this function to be called at module level, skipping the rest
|
Allows this function to be called at module level, skipping the rest
|
||||||
of the module. Defaults to False.
|
of the module. Defaults to False.
|
||||||
|
|
||||||
|
:param msg:
|
||||||
|
Same as ``reason``, but deprecated. Will be removed in a future version, use ``reason`` instead.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
It is better to use the :ref:`pytest.mark.skipif ref` marker when
|
It is better to use the :ref:`pytest.mark.skipif ref` marker when
|
||||||
possible to declare a test to be skipped under certain conditions
|
possible to declare a test to be skipped under certain conditions
|
||||||
|
@ -140,21 +171,66 @@ def skip(msg: str = "", *, allow_module_level: bool = False) -> "NoReturn":
|
||||||
to skip a doctest statically.
|
to skip a doctest statically.
|
||||||
"""
|
"""
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
raise Skipped(msg=msg, allow_module_level=allow_module_level)
|
reason = _resolve_msg_to_reason("skip", reason, msg)
|
||||||
|
raise Skipped(msg=reason, allow_module_level=allow_module_level)
|
||||||
|
|
||||||
|
|
||||||
@_with_exception(Failed)
|
@_with_exception(Failed)
|
||||||
def fail(msg: str = "", pytrace: bool = True) -> "NoReturn":
|
def fail(
|
||||||
|
reason: str = "", pytrace: bool = True, msg: Optional[str] = None
|
||||||
|
) -> "NoReturn":
|
||||||
"""Explicitly fail an executing test with the given message.
|
"""Explicitly fail an executing test with the given message.
|
||||||
|
|
||||||
:param str msg:
|
:param reason:
|
||||||
The message to show the user as reason for the failure.
|
The message to show the user as reason for the failure.
|
||||||
:param bool pytrace:
|
|
||||||
|
:param pytrace:
|
||||||
If False, msg represents the full failure information and no
|
If False, msg represents the full failure information and no
|
||||||
python traceback will be reported.
|
python traceback will be reported.
|
||||||
|
|
||||||
|
:param msg:
|
||||||
|
Same as ``reason``, but deprecated. Will be removed in a future version, use ``reason`` instead.
|
||||||
"""
|
"""
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
raise Failed(msg=msg, pytrace=pytrace)
|
reason = _resolve_msg_to_reason("fail", reason, msg)
|
||||||
|
raise Failed(msg=reason, pytrace=pytrace)
|
||||||
|
|
||||||
|
|
||||||
|
def _resolve_msg_to_reason(
|
||||||
|
func_name: str, reason: str, msg: Optional[str] = None
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
Handles converting the deprecated msg parameter if provided into
|
||||||
|
reason, raising a deprecation warning. This function will be removed
|
||||||
|
when the optional msg argument is removed from here in future.
|
||||||
|
|
||||||
|
:param str func_name:
|
||||||
|
The name of the offending function, this is formatted into the deprecation message.
|
||||||
|
|
||||||
|
:param str reason:
|
||||||
|
The reason= passed into either pytest.fail() or pytest.skip()
|
||||||
|
|
||||||
|
:param str msg:
|
||||||
|
The msg= passed into either pytest.fail() or pytest.skip(). This will
|
||||||
|
be converted into reason if it is provided to allow pytest.skip(msg=) or
|
||||||
|
pytest.fail(msg=) to continue working in the interim period.
|
||||||
|
|
||||||
|
:returns:
|
||||||
|
The value to use as reason.
|
||||||
|
|
||||||
|
"""
|
||||||
|
__tracebackhide__ = True
|
||||||
|
if msg is not None:
|
||||||
|
|
||||||
|
if reason:
|
||||||
|
from pytest import UsageError
|
||||||
|
|
||||||
|
raise UsageError(
|
||||||
|
f"Passing both ``reason`` and ``msg`` to pytest.{func_name}(...) is not permitted."
|
||||||
|
)
|
||||||
|
warnings.warn(KEYWORD_MSG_ARG.format(func=func_name), stacklevel=3)
|
||||||
|
reason = msg
|
||||||
|
return reason
|
||||||
|
|
||||||
|
|
||||||
class XFailed(Failed):
|
class XFailed(Failed):
|
||||||
|
|
|
@ -175,7 +175,7 @@ def async_warn_and_skip(nodeid: str) -> None:
|
||||||
msg += " - pytest-trio\n"
|
msg += " - pytest-trio\n"
|
||||||
msg += " - pytest-twisted"
|
msg += " - pytest-twisted"
|
||||||
warnings.warn(PytestUnhandledCoroutineWarning(msg.format(nodeid)))
|
warnings.warn(PytestUnhandledCoroutineWarning(msg.format(nodeid)))
|
||||||
skip(msg="async def function and no async plugin installed (see warnings)")
|
skip(reason="async def function and no async plugin installed (see warnings)")
|
||||||
|
|
||||||
|
|
||||||
@hookimpl(trylast=True)
|
@hookimpl(trylast=True)
|
||||||
|
|
|
@ -71,7 +71,8 @@ class Scope(Enum):
|
||||||
from _pytest.outcomes import fail
|
from _pytest.outcomes import fail
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return Scope(scope_name)
|
# Holding this reference is necessary for mypy at the moment.
|
||||||
|
scope = Scope(scope_name)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
fail(
|
fail(
|
||||||
"{} {}got an unexpected scope value '{}'".format(
|
"{} {}got an unexpected scope value '{}'".format(
|
||||||
|
@ -79,6 +80,7 @@ class Scope(Enum):
|
||||||
),
|
),
|
||||||
pytrace=False,
|
pytrace=False,
|
||||||
)
|
)
|
||||||
|
return scope
|
||||||
|
|
||||||
|
|
||||||
_ALL_SCOPES = list(Scope)
|
_ALL_SCOPES = list(Scope)
|
||||||
|
|
|
@ -200,6 +200,64 @@ def test_warns_none_is_deprecated():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TestSkipMsgArgumentDeprecated:
|
||||||
|
def test_skip_with_msg_is_deprecated(self, pytester: Pytester) -> None:
|
||||||
|
p = pytester.makepyfile(
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_skipping_msg():
|
||||||
|
pytest.skip(msg="skippedmsg")
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result = pytester.runpytest(p)
|
||||||
|
result.stdout.fnmatch_lines(
|
||||||
|
[
|
||||||
|
"*PytestDeprecationWarning: pytest.skip(msg=...) is now deprecated, "
|
||||||
|
"use pytest.skip(reason=...) instead",
|
||||||
|
'*pytest.skip(msg="skippedmsg")*',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
result.assert_outcomes(skipped=1, warnings=1)
|
||||||
|
|
||||||
|
def test_fail_with_msg_is_deprecated(self, pytester: Pytester) -> None:
|
||||||
|
p = pytester.makepyfile(
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_failing_msg():
|
||||||
|
pytest.fail(msg="failedmsg")
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result = pytester.runpytest(p)
|
||||||
|
result.stdout.fnmatch_lines(
|
||||||
|
[
|
||||||
|
"*PytestDeprecationWarning: pytest.fail(msg=...) is now deprecated, "
|
||||||
|
"use pytest.fail(reason=...) instead",
|
||||||
|
'*pytest.fail(msg="failedmsg")',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
result.assert_outcomes(failed=1, warnings=1)
|
||||||
|
|
||||||
|
def test_exit_with_msg_is_deprecated(self, pytester: Pytester) -> None:
|
||||||
|
p = pytester.makepyfile(
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_exit_msg():
|
||||||
|
pytest.exit(msg="exitmsg")
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result = pytester.runpytest(p)
|
||||||
|
result.stdout.fnmatch_lines(
|
||||||
|
[
|
||||||
|
"*PytestDeprecationWarning: pytest.exit(msg=...) is now deprecated, "
|
||||||
|
"use pytest.exit(reason=...) instead",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
result.assert_outcomes(warnings=1)
|
||||||
|
|
||||||
|
|
||||||
def test_deprecation_of_cmdline_preparse(pytester: Pytester) -> None:
|
def test_deprecation_of_cmdline_preparse(pytester: Pytester) -> None:
|
||||||
pytester.makeconftest(
|
pytester.makeconftest(
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -70,7 +70,7 @@ def test_wrap_session_exit_sessionfinish(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
def pytest_sessionfinish():
|
def pytest_sessionfinish():
|
||||||
pytest.exit(msg="exit_pytest_sessionfinish", returncode={returncode})
|
pytest.exit(reason="exit_pytest_sessionfinish", returncode={returncode})
|
||||||
""".format(
|
""".format(
|
||||||
returncode=returncode
|
returncode=returncode
|
||||||
)
|
)
|
||||||
|
|
|
@ -1444,3 +1444,92 @@ def test_relpath_rootdir(pytester: Pytester) -> None:
|
||||||
result.stdout.fnmatch_lines(
|
result.stdout.fnmatch_lines(
|
||||||
["SKIPPED [[]1[]] tests/test_1.py:2: unconditional skip"]
|
["SKIPPED [[]1[]] tests/test_1.py:2: unconditional skip"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_skip_using_reason_works_ok(pytester: Pytester) -> None:
|
||||||
|
p = pytester.makepyfile(
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_skipping_reason():
|
||||||
|
pytest.skip(reason="skippedreason")
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result = pytester.runpytest(p)
|
||||||
|
result.stdout.no_fnmatch_line("*PytestDeprecationWarning*")
|
||||||
|
result.assert_outcomes(skipped=1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_fail_using_reason_works_ok(pytester: Pytester) -> None:
|
||||||
|
p = pytester.makepyfile(
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_failing_reason():
|
||||||
|
pytest.fail(reason="failedreason")
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result = pytester.runpytest(p)
|
||||||
|
result.stdout.no_fnmatch_line("*PytestDeprecationWarning*")
|
||||||
|
result.assert_outcomes(failed=1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_fail_fails_with_msg_and_reason(pytester: Pytester) -> None:
|
||||||
|
p = pytester.makepyfile(
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_fail_both_arguments():
|
||||||
|
pytest.fail(reason="foo", msg="bar")
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result = pytester.runpytest(p)
|
||||||
|
result.stdout.fnmatch_lines(
|
||||||
|
"*UsageError: Passing both ``reason`` and ``msg`` to pytest.fail(...) is not permitted.*"
|
||||||
|
)
|
||||||
|
result.assert_outcomes(failed=1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_skip_fails_with_msg_and_reason(pytester: Pytester) -> None:
|
||||||
|
p = pytester.makepyfile(
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_skip_both_arguments():
|
||||||
|
pytest.skip(reason="foo", msg="bar")
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result = pytester.runpytest(p)
|
||||||
|
result.stdout.fnmatch_lines(
|
||||||
|
"*UsageError: Passing both ``reason`` and ``msg`` to pytest.skip(...) is not permitted.*"
|
||||||
|
)
|
||||||
|
result.assert_outcomes(failed=1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_exit_with_msg_and_reason_fails(pytester: Pytester) -> None:
|
||||||
|
p = pytester.makepyfile(
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_exit_both_arguments():
|
||||||
|
pytest.exit(reason="foo", msg="bar")
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result = pytester.runpytest(p)
|
||||||
|
result.stdout.fnmatch_lines(
|
||||||
|
"*UsageError: cannot pass reason and msg to exit(), `msg` is deprecated, use `reason`.*"
|
||||||
|
)
|
||||||
|
result.assert_outcomes(failed=1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_exit_with_reason_works_ok(pytester: Pytester) -> None:
|
||||||
|
p = pytester.makepyfile(
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_exit_reason_only():
|
||||||
|
pytest.exit(reason="foo")
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result = pytester.runpytest(p)
|
||||||
|
result.stdout.fnmatch_lines("*_pytest.outcomes.Exit: foo*")
|
||||||
|
|
Loading…
Reference in New Issue