Merge pull request #7660 from nicoddemus/deprecated-features

This commit is contained in:
Bruno Oliveira 2020-08-19 09:04:10 -03:00 committed by GitHub
commit d69abff2c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 108 additions and 809 deletions

View File

@ -0,0 +1,18 @@
As per our policy, the following features have been deprecated in the 5.X series and are now
removed:
* The ``funcargnames`` read-only property of ``FixtureRequest``, ``Metafunc``, and ``Function`` classes. Use ``fixturenames`` attribute.
* ``@pytest.fixture`` no longer supports positional arguments, pass all arguments by keyword instead.
* Direct construction of ``Node`` subclasses now raise an error, use ``from_parent`` instead.
* The default value for ``junit_family`` has changed to ``xunit2``. If you require the old format, add ``junit_family=xunit1`` to your configuration file.
* The ``TerminalReporter`` no longer has a ``writer`` attribute. Plugin authors may use the public functions of the ``TerminalReporter`` instead of accessing the ``TerminalWriter`` object directly.
* The ``--result-log`` option has been removed. Users are recommended to use the `pytest-reportlog <https://github.com/pytest-dev/pytest-reportlog>`__ plugin instead.
For more information consult
`Deprecations and Removals <https://docs.pytest.org/en/stable/deprecations.html>`__ in the docs.

View File

@ -30,11 +30,19 @@ This hook has an `item` parameter which cannot be serialized by ``pytest-xdist``
Use the ``pytest_warning_recored`` hook instead, which replaces the ``item`` parameter Use the ``pytest_warning_recored`` hook instead, which replaces the ``item`` parameter
by a ``nodeid`` parameter. by a ``nodeid`` parameter.
The ``pytest.collect`` module
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 6.0
The ``pytest.collect`` module is no longer part of the public API, all its names
should now be imported from ``pytest`` directly instead.
The ``pytest._fillfuncargs`` function The ``pytest._fillfuncargs`` function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 5.5 .. deprecated:: 6.0
This function was kept for backward compatibility with an older plugin. This function was kept for backward compatibility with an older plugin.
@ -43,6 +51,11 @@ it, use `function._request._fillfixtures()` instead, though note this is not
a public API and may break in the future. a public API and may break in the future.
Removed Features
----------------
As stated in our :ref:`backwards-compatibility` policy, deprecated features are removed only in major releases after
an appropriate period of deprecation has passed.
``--no-print-logs`` command-line option ``--no-print-logs`` command-line option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -59,38 +72,46 @@ display captured output when tests fail: ``no``, ``stdout``, ``stderr``, ``log``
Node Construction changed to ``Node.from_parent`` Result log (``--result-log``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 5.4 .. deprecated:: 4.0
.. versionremoved:: 6.0
The construction of nodes now should use the named constructor ``from_parent``. The ``--result-log`` option produces a stream of test reports which can be
This limitation in api surface intends to enable better/simpler refactoring of the collection tree. analysed at runtime, but it uses a custom format which requires users to implement their own
parser.
This means that instead of :code:`MyItem(name="foo", parent=collector, obj=42)` The `pytest-reportlog <https://github.com/pytest-dev/pytest-reportlog>`__ plugin provides a ``--report-log`` option, a more standard and extensible alternative, producing
one now has to invoke :code:`MyItem.from_parent(collector, name="foo")`. one JSON object per-line, and should cover the same use cases. Please try it out and provide feedback.
Plugins that wish to support older versions of pytest and suppress the warning can use The ``pytest-reportlog`` plugin might even be merged into the core
`hasattr` to check if `from_parent` exists in that version: at some point, depending on the plans for the plugins and number of users using it.
.. code-block:: python ``pytest_collect_directory`` hook
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def pytest_pycollect_makeitem(collector, name, obj): .. versionremoved:: 6.0
if hasattr(MyItem, "from_parent"):
item = MyItem.from_parent(collector, name="foo")
item.obj = 42
return item
else:
return MyItem(name="foo", parent=collector, obj=42)
Note that ``from_parent`` should only be called with keyword arguments for the parameters. The ``pytest_collect_directory`` has not worked properly for years (it was called
but the results were ignored). Users may consider using :func:`pytest_collection_modifyitems <_pytest.hookspec.pytest_collection_modifyitems>` instead.
TerminalReporter.writer
~~~~~~~~~~~~~~~~~~~~~~~
.. versionremoved:: 6.0
The ``TerminalReporter.writer`` attribute has been deprecated and should no longer be used. This
was inadvertently exposed as part of the public API of that plugin and ties it too much
with ``py.io.TerminalWriter``.
Plugins that used ``TerminalReporter.writer`` directly should instead use ``TerminalReporter``
methods that provide the same functionality.
``junit_family`` default value change to "xunit2" ``junit_family`` default value change to "xunit2"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 5.2 .. versionchanged:: 6.0
The default value of ``junit_family`` option will change to ``xunit2`` in pytest 6.0, which The default value of ``junit_family`` option will change to ``xunit2`` in pytest 6.0, which
is an update of the old ``xunit1`` format and is supported by default in modern tools is an update of the old ``xunit1`` format and is supported by default in modern tools
@ -126,11 +147,44 @@ Services known to support the ``xunit2`` format:
* `Jenkins <https://www.jenkins.io/>`__ with the `JUnit <https://plugins.jenkins.io/junit>`__ plugin. * `Jenkins <https://www.jenkins.io/>`__ with the `JUnit <https://plugins.jenkins.io/junit>`__ plugin.
* `Azure Pipelines <https://azure.microsoft.com/en-us/services/devops/pipelines>`__. * `Azure Pipelines <https://azure.microsoft.com/en-us/services/devops/pipelines>`__.
Node Construction changed to ``Node.from_parent``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionchanged:: 6.0
The construction of nodes now should use the named constructor ``from_parent``.
This limitation in api surface intends to enable better/simpler refactoring of the collection tree.
This means that instead of :code:`MyItem(name="foo", parent=collector, obj=42)`
one now has to invoke :code:`MyItem.from_parent(collector, name="foo")`.
Plugins that wish to support older versions of pytest and suppress the warning can use
`hasattr` to check if `from_parent` exists in that version:
.. code-block:: python
def pytest_pycollect_makeitem(collector, name, obj):
if hasattr(MyItem, "from_parent"):
item = MyItem.from_parent(collector, name="foo")
item.obj = 42
return item
else:
return MyItem(name="foo", parent=collector, obj=42)
Note that ``from_parent`` should only be called with keyword arguments for the parameters.
``pytest.fixture`` arguments are keyword only
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionremoved:: 6.0
Passing arguments to pytest.fixture() as positional arguments has been removed - pass them by keyword instead.
``funcargnames`` alias for ``fixturenames`` ``funcargnames`` alias for ``fixturenames``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 5.0 .. versionremoved:: 6.0
The ``FixtureRequest``, ``Metafunc``, and ``Function`` classes track the names of The ``FixtureRequest``, ``Metafunc``, and ``Function`` classes track the names of
their associated fixtures, with the aptly-named ``fixturenames`` attribute. their associated fixtures, with the aptly-named ``fixturenames`` attribute.
@ -141,42 +195,6 @@ in places where we or plugin authors must distinguish between fixture names and
names supplied by non-fixture things such as ``pytest.mark.parametrize``. names supplied by non-fixture things such as ``pytest.mark.parametrize``.
Result log (``--result-log``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 4.0
The ``--result-log`` option produces a stream of test reports which can be
analysed at runtime, but it uses a custom format which requires users to implement their own
parser.
The `pytest-reportlog <https://github.com/pytest-dev/pytest-reportlog>`__ plugin provides a ``--report-log`` option, a more standard and extensible alternative, producing
one JSON object per-line, and should cover the same use cases. Please try it out and provide feedback.
The plan is remove the ``--result-log`` option in pytest 6.0 if ``pytest-reportlog`` proves satisfactory
to all users and is deemed stable. The ``pytest-reportlog`` plugin might even be merged into the core
at some point, depending on the plans for the plugins and number of users using it.
TerminalReporter.writer
~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 5.4
The ``TerminalReporter.writer`` attribute has been deprecated and should no longer be used. This
was inadvertently exposed as part of the public API of that plugin and ties it too much
with ``py.io.TerminalWriter``.
Plugins that used ``TerminalReporter.writer`` directly should instead use ``TerminalReporter``
methods that provide the same functionality.
Removed Features
----------------
As stated in our :ref:`backwards-compatibility` policy, deprecated features are removed only in major releases after
an appropriate period of deprecation has passed.
``pytest.config`` global ``pytest.config`` global
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -656,7 +656,6 @@ Collection hooks
.. autofunction:: pytest_collection .. autofunction:: pytest_collection
.. autofunction:: pytest_ignore_collect .. autofunction:: pytest_ignore_collect
.. autofunction:: pytest_collect_directory
.. autofunction:: pytest_collect_file .. autofunction:: pytest_collect_file
.. autofunction:: pytest_pycollect_makemodule .. autofunction:: pytest_pycollect_makemodule

View File

@ -239,7 +239,6 @@ default_plugins = essential_plugins + (
"nose", "nose",
"assertion", "assertion",
"junitxml", "junitxml",
"resultlog",
"doctest", "doctest",
"cacheprovider", "cacheprovider",
"freeze_support", "freeze_support",

View File

@ -19,45 +19,12 @@ DEPRECATED_EXTERNAL_PLUGINS = {
"pytest_faulthandler", "pytest_faulthandler",
} }
FUNCARGNAMES = PytestDeprecationWarning(
"The `funcargnames` attribute was an alias for `fixturenames`, "
"since pytest 2.3 - use the newer attribute instead."
)
FILLFUNCARGS = PytestDeprecationWarning( FILLFUNCARGS = PytestDeprecationWarning(
"The `_fillfuncargs` function is deprecated, use " "The `_fillfuncargs` function is deprecated, use "
"function._request._fillfixtures() instead if you cannot avoid reaching into internals." "function._request._fillfixtures() instead if you cannot avoid reaching into internals."
) )
RESULT_LOG = PytestDeprecationWarning(
"--result-log is deprecated, please try the new pytest-reportlog plugin.\n"
"See https://docs.pytest.org/en/stable/deprecations.html#result-log-result-log for more information."
)
FIXTURE_POSITIONAL_ARGUMENTS = PytestDeprecationWarning(
"Passing arguments to pytest.fixture() as positional arguments is deprecated - pass them "
"as a keyword argument instead."
)
NODE_USE_FROM_PARENT = UnformattedWarning(
PytestDeprecationWarning,
"Direct construction of {name} has been deprecated, please use {name}.from_parent.\n"
"See "
"https://docs.pytest.org/en/stable/deprecations.html#node-construction-changed-to-node-from-parent"
" for more details.",
)
JUNIT_XML_DEFAULT_FAMILY = PytestDeprecationWarning(
"The 'junit_family' default value will change to 'xunit2' in pytest 6.0. See:\n"
" https://docs.pytest.org/en/stable/deprecations.html#junit-family-default-value-change-to-xunit2\n"
"for more information."
)
COLLECT_DIRECTORY_HOOK = PytestDeprecationWarning(
"The pytest_collect_directory hook is not working.\n"
"Please use collect_ignore in conftests or pytest_collection_modifyitems."
)
PYTEST_COLLECT_MODULE = UnformattedWarning( PYTEST_COLLECT_MODULE = UnformattedWarning(
PytestDeprecationWarning, PytestDeprecationWarning,
"pytest.collect.{name} was moved to pytest.{name}\n" "pytest.collect.{name} was moved to pytest.{name}\n"
@ -65,12 +32,6 @@ PYTEST_COLLECT_MODULE = UnformattedWarning(
) )
TERMINALWRITER_WRITER = PytestDeprecationWarning(
"The TerminalReporter.writer attribute is deprecated, use TerminalReporter._tw instead at your own risk.\n"
"See https://docs.pytest.org/en/stable/deprecations.html#terminalreporter-writer for more information."
)
MINUS_K_DASH = PytestDeprecationWarning( MINUS_K_DASH = PytestDeprecationWarning(
"The `-k '-expr'` syntax to -k is deprecated.\nUse `-k 'not expr'` instead." "The `-k '-expr'` syntax to -k is deprecated.\nUse `-k 'not expr'` instead."
) )

View File

@ -2,7 +2,6 @@ import functools
import inspect import inspect
import os import os
import sys import sys
import warnings
from collections import defaultdict from collections import defaultdict
from collections import deque from collections import deque
from types import TracebackType from types import TracebackType
@ -46,8 +45,6 @@ from _pytest.compat import TYPE_CHECKING
from _pytest.config import _PluggyPlugin from _pytest.config import _PluggyPlugin
from _pytest.config import Config from _pytest.config import Config
from _pytest.config.argparsing import Parser from _pytest.config.argparsing import Parser
from _pytest.deprecated import FIXTURE_POSITIONAL_ARGUMENTS
from _pytest.deprecated import FUNCARGNAMES
from _pytest.mark import ParameterSet from _pytest.mark import ParameterSet
from _pytest.outcomes import fail from _pytest.outcomes import fail
from _pytest.outcomes import TEST_OUTCOME from _pytest.outcomes import TEST_OUTCOME
@ -457,12 +454,6 @@ class FixtureRequest:
result.extend(set(self._fixture_defs).difference(result)) result.extend(set(self._fixture_defs).difference(result))
return result return result
@property
def funcargnames(self) -> List[str]:
"""Alias attribute for ``fixturenames`` for pre-2.3 compatibility."""
warnings.warn(FUNCARGNAMES, stacklevel=2)
return self.fixturenames
@property @property
def node(self): def node(self):
"""Underlying collection node (depends on current request scope).""" """Underlying collection node (depends on current request scope)."""
@ -1253,7 +1244,7 @@ def fixture( # noqa: F811
def fixture( # noqa: F811 def fixture( # noqa: F811
fixture_function: Optional[_FixtureFunction] = None, fixture_function: Optional[_FixtureFunction] = None,
*args: Any, *,
scope: "Union[_Scope, Callable[[str, Config], _Scope]]" = "function", scope: "Union[_Scope, Callable[[str, Config], _Scope]]" = "function",
params: Optional[Iterable[object]] = None, params: Optional[Iterable[object]] = None,
autouse: bool = False, autouse: bool = False,
@ -1315,53 +1306,6 @@ def fixture( # noqa: F811
name the decorated function ``fixture_<fixturename>`` and then use name the decorated function ``fixture_<fixturename>`` and then use
``@pytest.fixture(name='<fixturename>')``. ``@pytest.fixture(name='<fixturename>')``.
""" """
# Positional arguments backward compatibility.
# If a kwarg is equal to its default, assume it was not explicitly
# passed, i.e. not duplicated. The more correct way is to use a
# **kwargs and check `in`, but that obfuscates the function signature.
if isinstance(fixture_function, str):
# It's actually the first positional argument, scope.
args = (fixture_function, *args) # type: ignore[unreachable]
fixture_function = None
duplicated_args = []
if len(args) > 0:
if scope == "function":
scope = args[0]
else:
duplicated_args.append("scope")
if len(args) > 1:
if params is None:
params = args[1]
else:
duplicated_args.append("params")
if len(args) > 2:
if autouse is False:
autouse = args[2]
else:
duplicated_args.append("autouse")
if len(args) > 3:
if ids is None:
ids = args[3]
else:
duplicated_args.append("ids")
if len(args) > 4:
if name is None:
name = args[4]
else:
duplicated_args.append("name")
if len(args) > 5:
raise TypeError(
"fixture() takes 5 positional arguments but {} were given".format(len(args))
)
if duplicated_args:
raise TypeError(
"The fixture arguments are defined as positional and keyword: {}. "
"Use only keyword arguments.".format(", ".join(duplicated_args))
)
if args:
warnings.warn(FIXTURE_POSITIONAL_ARGUMENTS, stacklevel=2)
# End backward compatiblity.
fixture_marker = FixtureFunctionMarker( fixture_marker = FixtureFunctionMarker(
scope=scope, params=params, autouse=autouse, ids=ids, name=name, scope=scope, params=params, autouse=autouse, ids=ids, name=name,
) )

View File

@ -12,7 +12,6 @@ from typing import Union
import py.path import py.path
from pluggy import HookspecMarker from pluggy import HookspecMarker
from .deprecated import COLLECT_DIRECTORY_HOOK
from _pytest.compat import TYPE_CHECKING from _pytest.compat import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
@ -262,16 +261,6 @@ def pytest_ignore_collect(path: py.path.local, config: "Config") -> Optional[boo
""" """
@hookspec(firstresult=True, warn_on_impl=COLLECT_DIRECTORY_HOOK)
def pytest_collect_directory(path: py.path.local, parent) -> Optional[object]:
"""Called before traversing a directory for collection files.
Stops at first non-None result, see :ref:`firstresult`.
:param py.path.local path: The path to analyze.
"""
def pytest_collect_file(path: py.path.local, parent) -> "Optional[Collector]": def pytest_collect_file(path: py.path.local, parent) -> "Optional[Collector]":
"""Return collection Node or None for the given path. """Return collection Node or None for the given path.

View File

@ -21,7 +21,6 @@ from typing import Tuple
from typing import Union from typing import Union
import pytest import pytest
from _pytest import deprecated
from _pytest import nodes from _pytest import nodes
from _pytest import timing from _pytest import timing
from _pytest._code.code import ExceptionRepr from _pytest._code.code import ExceptionRepr
@ -33,7 +32,6 @@ from _pytest.fixtures import FixtureRequest
from _pytest.reports import TestReport from _pytest.reports import TestReport
from _pytest.store import StoreKey from _pytest.store import StoreKey
from _pytest.terminal import TerminalReporter from _pytest.terminal import TerminalReporter
from _pytest.warnings import _issue_warning_captured
xml_key = StoreKey["LogXML"]() xml_key = StoreKey["LogXML"]()
@ -413,7 +411,9 @@ def pytest_addoption(parser: Parser) -> None:
default="total", default="total",
) # choices=['total', 'call']) ) # choices=['total', 'call'])
parser.addini( parser.addini(
"junit_family", "Emit XML for schema: one of legacy|xunit1|xunit2", default=None "junit_family",
"Emit XML for schema: one of legacy|xunit1|xunit2",
default="xunit2",
) )
@ -422,9 +422,6 @@ def pytest_configure(config: Config) -> None:
# Prevent opening xmllog on worker nodes (xdist). # Prevent opening xmllog on worker nodes (xdist).
if xmlpath and not hasattr(config, "workerinput"): if xmlpath and not hasattr(config, "workerinput"):
junit_family = config.getini("junit_family") junit_family = config.getini("junit_family")
if not junit_family:
_issue_warning_captured(deprecated.JUNIT_XML_DEFAULT_FAMILY, config.hook, 2)
junit_family = "xunit1"
config._store[xml_key] = LogXML( config._store[xml_key] = LogXML(
xmlpath, xmlpath,
config.option.junitprefix, config.option.junitprefix,

View File

@ -26,7 +26,6 @@ from _pytest.compat import TYPE_CHECKING
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ConftestImportFailure from _pytest.config import ConftestImportFailure
from _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH from _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH
from _pytest.deprecated import NODE_USE_FROM_PARENT
from _pytest.fixtures import FixtureDef from _pytest.fixtures import FixtureDef
from _pytest.fixtures import FixtureLookupError from _pytest.fixtures import FixtureLookupError
from _pytest.mark.structures import Mark from _pytest.mark.structures import Mark
@ -97,8 +96,13 @@ _NodeType = TypeVar("_NodeType", bound="Node")
class NodeMeta(type): class NodeMeta(type):
def __call__(self, *k, **kw): def __call__(self, *k, **kw):
warnings.warn(NODE_USE_FROM_PARENT.format(name=self.__name__), stacklevel=2) msg = (
return super().__call__(*k, **kw) "Direct construction of {name} has been deprecated, please use {name}.from_parent.\n"
"See "
"https://docs.pytest.org/en/stable/deprecations.html#node-construction-changed-to-node-from-parent"
" for more details."
).format(name=self.__name__)
fail(msg, pytrace=False)
def _create(self, *k, **kw): def _create(self, *k, **kw):
return super().__call__(*k, **kw) return super().__call__(*k, **kw)
@ -549,8 +553,6 @@ class FSCollector(Collector):
for pat in self._norecursepatterns: for pat in self._norecursepatterns:
if path.check(fnmatch=pat): if path.check(fnmatch=pat):
return False return False
ihook = self.session.gethookproxy(path)
ihook.pytest_collect_directory(path=path, parent=self)
return True return True
def _collectfile( def _collectfile(

View File

@ -53,7 +53,6 @@ from _pytest.config import ExitCode
from _pytest.config import hookimpl from _pytest.config import hookimpl
from _pytest.config.argparsing import Parser from _pytest.config.argparsing import Parser
from _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH from _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH
from _pytest.deprecated import FUNCARGNAMES
from _pytest.fixtures import FuncFixtureInfo from _pytest.fixtures import FuncFixtureInfo
from _pytest.main import Session from _pytest.main import Session
from _pytest.mark import MARK_GEN from _pytest.mark import MARK_GEN
@ -906,12 +905,6 @@ class Metafunc:
self._calls = [] # type: List[CallSpec2] self._calls = [] # type: List[CallSpec2]
self._arg2fixturedefs = fixtureinfo.name2fixturedefs self._arg2fixturedefs = fixtureinfo.name2fixturedefs
@property
def funcargnames(self) -> List[str]:
"""Alias attribute for ``fixturenames`` for pre-2.3 compatibility."""
warnings.warn(FUNCARGNAMES, stacklevel=2)
return self.fixturenames
def parametrize( def parametrize(
self, self,
argnames: Union[str, List[str], Tuple[str, ...]], argnames: Union[str, List[str], Tuple[str, ...]],
@ -1568,12 +1561,6 @@ class Function(PyobjMixin, nodes.Item):
"""(compatonly) for code expecting pytest-2.2 style request objects.""" """(compatonly) for code expecting pytest-2.2 style request objects."""
return self return self
@property
def funcargnames(self) -> List[str]:
"""Alias attribute for ``fixturenames`` for pre-2.3 compatibility."""
warnings.warn(FUNCARGNAMES, stacklevel=2)
return self.fixturenames
def runtest(self) -> None: def runtest(self) -> None:
"""Execute the underlying test function.""" """Execute the underlying test function."""
self.ihook.pytest_pyfunc_call(pyfuncitem=self) self.ihook.pytest_pyfunc_call(pyfuncitem=self)

View File

@ -1,108 +0,0 @@
"""log machine-parseable test session result information to a plain text file."""
import os
from typing import IO
from typing import Union
from _pytest._code.code import ExceptionRepr
from _pytest.config import Config
from _pytest.config.argparsing import Parser
from _pytest.reports import CollectReport
from _pytest.reports import TestReport
from _pytest.store import StoreKey
resultlog_key = StoreKey["ResultLog"]()
def pytest_addoption(parser: Parser) -> None:
group = parser.getgroup("terminal reporting", "resultlog plugin options")
group.addoption(
"--resultlog",
"--result-log",
action="store",
metavar="path",
default=None,
help="DEPRECATED path for machine-readable result log.",
)
def pytest_configure(config: Config) -> None:
resultlog = config.option.resultlog
# Prevent opening resultlog on worker nodes (xdist).
if resultlog and not hasattr(config, "workerinput"):
dirname = os.path.dirname(os.path.abspath(resultlog))
if not os.path.isdir(dirname):
os.makedirs(dirname)
logfile = open(resultlog, "w", 1) # line buffered
config._store[resultlog_key] = ResultLog(config, logfile)
config.pluginmanager.register(config._store[resultlog_key])
from _pytest.deprecated import RESULT_LOG
from _pytest.warnings import _issue_warning_captured
_issue_warning_captured(RESULT_LOG, config.hook, stacklevel=2)
def pytest_unconfigure(config: Config) -> None:
resultlog = config._store.get(resultlog_key, None)
if resultlog:
resultlog.logfile.close()
del config._store[resultlog_key]
config.pluginmanager.unregister(resultlog)
class ResultLog:
def __init__(self, config: Config, logfile: IO[str]) -> None:
self.config = config
self.logfile = logfile # preferably line buffered
def write_log_entry(self, testpath: str, lettercode: str, longrepr: str) -> None:
print("{} {}".format(lettercode, testpath), file=self.logfile)
for line in longrepr.splitlines():
print(" %s" % line, file=self.logfile)
def log_outcome(
self, report: Union[TestReport, CollectReport], lettercode: str, longrepr: str
) -> None:
testpath = getattr(report, "nodeid", None)
if testpath is None:
testpath = report.fspath
self.write_log_entry(testpath, lettercode, longrepr)
def pytest_runtest_logreport(self, report: TestReport) -> None:
if report.when != "call" and report.passed:
return
res = self.config.hook.pytest_report_teststatus(
report=report, config=self.config
)
code = res[1] # type: str
if code == "x":
longrepr = str(report.longrepr)
elif code == "X":
longrepr = ""
elif report.passed:
longrepr = ""
elif report.skipped:
assert isinstance(report.longrepr, tuple)
longrepr = str(report.longrepr[2])
else:
longrepr = str(report.longrepr)
self.log_outcome(report, code, longrepr)
def pytest_collectreport(self, report: CollectReport) -> None:
if not report.passed:
if report.failed:
code = "F"
longrepr = str(report.longrepr)
else:
assert report.skipped
code = "S"
longrepr = "%s:%d: %s" % report.longrepr # type: ignore
self.log_outcome(report, code, longrepr)
def pytest_internalerror(self, excrepr: ExceptionRepr) -> None:
if excrepr.reprcrash is not None:
path = excrepr.reprcrash.path
else:
path = "cwd:%s" % os.getcwd()
self.write_log_entry(path, "!", str(excrepr))

View File

@ -31,7 +31,6 @@ from _pytest import nodes
from _pytest import timing from _pytest import timing
from _pytest._code import ExceptionInfo from _pytest._code import ExceptionInfo
from _pytest._code.code import ExceptionRepr from _pytest._code.code import ExceptionRepr
from _pytest._io import TerminalWriter
from _pytest._io.wcwidth import wcswidth from _pytest._io.wcwidth import wcswidth
from _pytest.compat import order_preserving_dict from _pytest.compat import order_preserving_dict
from _pytest.compat import TYPE_CHECKING from _pytest.compat import TYPE_CHECKING
@ -39,7 +38,6 @@ from _pytest.config import _PluggyPlugin
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ExitCode from _pytest.config import ExitCode
from _pytest.config.argparsing import Parser from _pytest.config.argparsing import Parser
from _pytest.deprecated import TERMINALWRITER_WRITER
from _pytest.nodes import Item from _pytest.nodes import Item
from _pytest.nodes import Node from _pytest.nodes import Node
from _pytest.reports import BaseReport from _pytest.reports import BaseReport
@ -335,16 +333,6 @@ class TerminalReporter:
self._already_displayed_warnings = None # type: Optional[int] self._already_displayed_warnings = None # type: Optional[int]
self._keyboardinterrupt_memo = None # type: Optional[ExceptionRepr] self._keyboardinterrupt_memo = None # type: Optional[ExceptionRepr]
@property
def writer(self) -> TerminalWriter:
warnings.warn(TERMINALWRITER_WRITER, stacklevel=2)
return self._tw
@writer.setter
def writer(self, value: TerminalWriter) -> None:
warnings.warn(TERMINALWRITER_WRITER, stacklevel=2)
self._tw = value
def _determine_show_progress_info(self) -> "Literal['progress', 'count', False]": def _determine_show_progress_info(self) -> "Literal['progress', 'count', False]":
"""Return whether we should display progress information based on the current config.""" """Return whether we should display progress information based on the current config."""
# do not show progress if we are not capturing output (#3038) # do not show progress if we are not capturing output (#3038)

View File

@ -104,8 +104,6 @@ def catch_warnings_for_item(
warnings.filterwarnings("always", category=DeprecationWarning) warnings.filterwarnings("always", category=DeprecationWarning)
warnings.filterwarnings("always", category=PendingDeprecationWarning) warnings.filterwarnings("always", category=PendingDeprecationWarning)
warnings.filterwarnings("error", category=pytest.PytestDeprecationWarning)
# Filters should have this precedence: mark, cmdline options, ini. # Filters should have this precedence: mark, cmdline options, ini.
# Filters should be applied in the inverse order of precedence. # Filters should be applied in the inverse order of precedence.
for arg in inifilters: for arg in inifilters:

View File

@ -223,13 +223,12 @@ class TestGeneralUsage:
"E {}: No module named 'qwerty'".format(exc_name), "E {}: No module named 'qwerty'".format(exc_name),
] ]
@pytest.mark.filterwarnings("ignore::pytest.PytestDeprecationWarning")
def test_early_skip(self, testdir): def test_early_skip(self, testdir):
testdir.mkdir("xyz") testdir.mkdir("xyz")
testdir.makeconftest( testdir.makeconftest(
""" """
import pytest import pytest
def pytest_collect_directory(): def pytest_collect_file():
pytest.skip("early") pytest.skip("early")
""" """
) )

View File

@ -1,35 +1,11 @@
import copy
import inspect
import warnings import warnings
from unittest import mock from unittest import mock
import pytest import pytest
from _pytest import deprecated from _pytest import deprecated
from _pytest import nodes
from _pytest.config import Config
from _pytest.pytester import Testdir from _pytest.pytester import Testdir
@pytest.mark.filterwarnings("default")
def test_resultlog_is_deprecated(testdir):
result = testdir.runpytest("--help")
result.stdout.fnmatch_lines(["*DEPRECATED path for machine-readable result log*"])
testdir.makepyfile(
"""
def test():
pass
"""
)
result = testdir.runpytest("--result-log=%s" % testdir.tmpdir.join("result.log"))
result.stdout.fnmatch_lines(
[
"*--result-log is deprecated, please try the new pytest-reportlog plugin.",
"*See https://docs.pytest.org/en/stable/deprecations.html#result-log-result-log for more information*",
]
)
@pytest.mark.skip(reason="should be reintroduced in 6.1: #7361") @pytest.mark.skip(reason="should be reintroduced in 6.1: #7361")
@pytest.mark.parametrize("attribute", pytest.collect.__all__) # type: ignore @pytest.mark.parametrize("attribute", pytest.collect.__all__) # type: ignore
# false positive due to dynamic attribute # false positive due to dynamic attribute
@ -38,35 +14,6 @@ def test_pytest_collect_module_deprecated(attribute):
getattr(pytest.collect, attribute) getattr(pytest.collect, attribute)
def test_terminal_reporter_writer_attr(pytestconfig: Config) -> None:
"""Check that TerminalReporter._tw is also available as 'writer' (#2984)
This attribute has been deprecated in 5.4.
"""
try:
import xdist # noqa
pytest.skip("xdist workers disable the terminal reporter plugin")
except ImportError:
pass
terminal_reporter = pytestconfig.pluginmanager.get_plugin("terminalreporter")
original_tw = terminal_reporter._tw
with pytest.warns(pytest.PytestDeprecationWarning) as cw:
assert terminal_reporter.writer is original_tw
assert len(cw) == 1
assert cw[0].filename == __file__
new_tw = copy.copy(original_tw)
with pytest.warns(pytest.PytestDeprecationWarning) as cw:
terminal_reporter.writer = new_tw
try:
assert terminal_reporter._tw is new_tw
finally:
terminal_reporter.writer = original_tw
assert len(cw) == 2
assert cw[0].filename == cw[1].filename == __file__
@pytest.mark.parametrize("plugin", sorted(deprecated.DEPRECATED_EXTERNAL_PLUGINS)) @pytest.mark.parametrize("plugin", sorted(deprecated.DEPRECATED_EXTERNAL_PLUGINS))
@pytest.mark.filterwarnings("default") @pytest.mark.filterwarnings("default")
def test_external_plugins_integrated(testdir, plugin): def test_external_plugins_integrated(testdir, plugin):
@ -77,49 +24,6 @@ def test_external_plugins_integrated(testdir, plugin):
testdir.parseconfig("-p", plugin) testdir.parseconfig("-p", plugin)
@pytest.mark.parametrize("junit_family", [None, "legacy", "xunit2"])
def test_warn_about_imminent_junit_family_default_change(testdir, junit_family):
"""Show a warning if junit_family is not defined and --junitxml is used (#6179)"""
testdir.makepyfile(
"""
def test_foo():
pass
"""
)
if junit_family:
testdir.makeini(
"""
[pytest]
junit_family={junit_family}
""".format(
junit_family=junit_family
)
)
result = testdir.runpytest("--junit-xml=foo.xml")
warning_msg = (
"*PytestDeprecationWarning: The 'junit_family' default value will change*"
)
if junit_family:
result.stdout.no_fnmatch_line(warning_msg)
else:
result.stdout.fnmatch_lines([warning_msg])
def test_node_direct_ctor_warning() -> None:
class MockConfig:
pass
ms = MockConfig()
with pytest.warns(
DeprecationWarning,
match="Direct construction of .* has been deprecated, please use .*.from_parent.*",
) as w:
nodes.Node(name="test", config=ms, session=ms, nodeid="None") # type: ignore
assert w[0].lineno == inspect.currentframe().f_lineno - 1 # type: ignore
assert w[0].filename == __file__
@pytest.mark.skip(reason="should be reintroduced in 6.1: #7361") @pytest.mark.skip(reason="should be reintroduced in 6.1: #7361")
def test_fillfuncargs_is_deprecated() -> None: def test_fillfuncargs_is_deprecated() -> None:
with pytest.warns( with pytest.warns(

View File

@ -815,28 +815,6 @@ class TestRequestBasic:
result = testdir.runpytest() result = testdir.runpytest()
result.stdout.fnmatch_lines(["*1 passed*"]) result.stdout.fnmatch_lines(["*1 passed*"])
def test_funcargnames_compatattr(self, testdir):
testdir.makepyfile(
"""
import pytest
def pytest_generate_tests(metafunc):
with pytest.warns(pytest.PytestDeprecationWarning):
assert metafunc.funcargnames == metafunc.fixturenames
@pytest.fixture
def fn(request):
with pytest.warns(pytest.PytestDeprecationWarning):
assert request._pyfuncitem.funcargnames == \
request._pyfuncitem.fixturenames
with pytest.warns(pytest.PytestDeprecationWarning):
return request.funcargnames, request.fixturenames
def test_hello(fn):
assert fn[0] == fn[1]
"""
)
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
def test_setupdecorator_and_xunit(self, testdir): def test_setupdecorator_and_xunit(self, testdir):
testdir.makepyfile( testdir.makepyfile(
""" """
@ -4152,73 +4130,6 @@ def test_fixture_named_request(testdir):
) )
def test_fixture_duplicated_arguments() -> None:
"""Raise error if there are positional and keyword arguments for the same parameter (#1682)."""
with pytest.raises(TypeError) as excinfo:
@pytest.fixture("session", scope="session") # type: ignore[call-overload]
def arg(arg):
pass
assert (
str(excinfo.value)
== "The fixture arguments are defined as positional and keyword: scope. "
"Use only keyword arguments."
)
with pytest.raises(TypeError) as excinfo:
@pytest.fixture( # type: ignore[call-overload]
"function",
["p1"],
True,
["id1"],
"name",
scope="session",
params=["p1"],
autouse=True,
ids=["id1"],
name="name",
)
def arg2(request):
pass
assert (
str(excinfo.value)
== "The fixture arguments are defined as positional and keyword: scope, params, autouse, ids, name. "
"Use only keyword arguments."
)
def test_fixture_with_positionals() -> None:
"""Raise warning, but the positionals should still works (#1682)."""
from _pytest.deprecated import FIXTURE_POSITIONAL_ARGUMENTS
with pytest.warns(pytest.PytestDeprecationWarning) as warnings:
@pytest.fixture("function", [0], True) # type: ignore[call-overload]
def fixture_with_positionals():
pass
assert str(warnings[0].message) == str(FIXTURE_POSITIONAL_ARGUMENTS)
assert fixture_with_positionals._pytestfixturefunction.scope == "function"
assert fixture_with_positionals._pytestfixturefunction.params == (0,)
assert fixture_with_positionals._pytestfixturefunction.autouse
def test_fixture_with_too_many_positionals() -> None:
with pytest.raises(TypeError) as excinfo:
@pytest.fixture("function", [0], True, ["id"], "name", "extra") # type: ignore[call-overload]
def fixture_with_positionals():
pass
assert (
str(excinfo.value) == "fixture() takes 5 positional arguments but 6 were given"
)
def test_indirect_fixture_does_not_break_scope(testdir): def test_indirect_fixture_does_not_break_scope(testdir):
"""Ensure that fixture scope is respected when using indirect fixtures (#570)""" """Ensure that fixture scope is respected when using indirect fixtures (#570)"""
testdir.makepyfile( testdir.makepyfile(

View File

@ -257,20 +257,6 @@ class TestCollectPluginHookRelay:
assert len(wascalled) == 1 assert len(wascalled) == 1
assert wascalled[0].ext == ".abc" assert wascalled[0].ext == ".abc"
@pytest.mark.filterwarnings("ignore:.*pytest_collect_directory.*")
def test_pytest_collect_directory(self, testdir):
wascalled = []
class Plugin:
def pytest_collect_directory(self, path):
wascalled.append(path.basename)
testdir.mkdir("hello")
testdir.mkdir("world")
pytest.main(testdir.tmpdir, plugins=[Plugin()])
assert "hello" in wascalled
assert "world" in wascalled
class TestPrunetraceback: class TestPrunetraceback:
def test_custom_repr_failure(self, testdir): def test_custom_repr_failure(self, testdir):

View File

@ -306,21 +306,6 @@ def test_no_conftest(testdir):
assert result.ret == ExitCode.USAGE_ERROR assert result.ret == ExitCode.USAGE_ERROR
def test_conftest_existing_resultlog(testdir):
x = testdir.mkdir("tests")
x.join("conftest.py").write(
textwrap.dedent(
"""\
def pytest_addoption(parser):
parser.addoption("--xyz", action="store_true")
"""
)
)
testdir.makefile(ext=".log", result="") # Writes result.log
result = testdir.runpytest("-h", "--resultlog", "result.log")
result.stdout.fnmatch_lines(["*--xyz*"])
def test_conftest_existing_junitxml(testdir): def test_conftest_existing_junitxml(testdir):
x = testdir.mkdir("tests") x = testdir.mkdir("tests")
x.join("conftest.py").write( x.join("conftest.py").write(

View File

@ -1,256 +0,0 @@
import os
from io import StringIO
from typing import List
import _pytest._code
import pytest
from _pytest.pytester import Testdir
from _pytest.resultlog import pytest_configure
from _pytest.resultlog import pytest_unconfigure
from _pytest.resultlog import ResultLog
from _pytest.resultlog import resultlog_key
pytestmark = pytest.mark.filterwarnings("ignore:--result-log is deprecated")
def test_write_log_entry() -> None:
reslog = ResultLog(None, None) # type: ignore[arg-type]
reslog.logfile = StringIO()
reslog.write_log_entry("name", ".", "")
entry = reslog.logfile.getvalue()
assert entry[-1] == "\n"
entry_lines = entry.splitlines()
assert len(entry_lines) == 1
assert entry_lines[0] == ". name"
reslog.logfile = StringIO()
reslog.write_log_entry("name", "s", "Skipped")
entry = reslog.logfile.getvalue()
assert entry[-1] == "\n"
entry_lines = entry.splitlines()
assert len(entry_lines) == 2
assert entry_lines[0] == "s name"
assert entry_lines[1] == " Skipped"
reslog.logfile = StringIO()
reslog.write_log_entry("name", "s", "Skipped\n")
entry = reslog.logfile.getvalue()
assert entry[-1] == "\n"
entry_lines = entry.splitlines()
assert len(entry_lines) == 2
assert entry_lines[0] == "s name"
assert entry_lines[1] == " Skipped"
reslog.logfile = StringIO()
longrepr = " tb1\n tb 2\nE tb3\nSome Error"
reslog.write_log_entry("name", "F", longrepr)
entry = reslog.logfile.getvalue()
assert entry[-1] == "\n"
entry_lines = entry.splitlines()
assert len(entry_lines) == 5
assert entry_lines[0] == "F name"
assert entry_lines[1:] == [" " + line for line in longrepr.splitlines()]
class TestWithFunctionIntegration:
# XXX (hpk) i think that the resultlog plugin should
# provide a Parser object so that one can remain
# ignorant regarding formatting details.
def getresultlog(self, testdir: Testdir, arg: str) -> List[str]:
resultlog = testdir.tmpdir.join("resultlog")
testdir.plugins.append("resultlog")
args = ["--resultlog=%s" % resultlog] + [arg]
testdir.runpytest(*args)
return [x for x in resultlog.readlines(cr=0) if x]
def test_collection_report(self, testdir: Testdir) -> None:
ok = testdir.makepyfile(test_collection_ok="")
fail = testdir.makepyfile(test_collection_fail="XXX")
lines = self.getresultlog(testdir, ok)
assert not lines
lines = self.getresultlog(testdir, fail)
assert lines
assert lines[0].startswith("F ")
assert lines[0].endswith("test_collection_fail.py"), lines[0]
for x in lines[1:]:
assert x.startswith(" ")
assert "XXX" in "".join(lines[1:])
def test_log_test_outcomes(self, testdir: Testdir) -> None:
mod = testdir.makepyfile(
test_mod="""
import pytest
def test_pass(): pass
def test_skip(): pytest.skip("hello")
def test_fail(): raise ValueError("FAIL")
@pytest.mark.xfail
def test_xfail(): raise ValueError("XFAIL")
@pytest.mark.xfail
def test_xpass(): pass
"""
)
lines = self.getresultlog(testdir, mod)
assert len(lines) >= 3
assert lines[0].startswith(". ")
assert lines[0].endswith("test_pass")
assert lines[1].startswith("s "), lines[1]
assert lines[1].endswith("test_skip")
assert lines[2].find("hello") != -1
assert lines[3].startswith("F ")
assert lines[3].endswith("test_fail")
tb = "".join(lines[4:8])
assert tb.find('raise ValueError("FAIL")') != -1
assert lines[8].startswith("x ")
tb = "".join(lines[8:14])
assert tb.find('raise ValueError("XFAIL")') != -1
assert lines[14].startswith("X ")
assert len(lines) == 15
@pytest.mark.parametrize("style", ("native", "long", "short"))
def test_internal_exception(self, style) -> None:
# they are produced for example by a teardown failing
# at the end of the run or a failing hook invocation
try:
raise ValueError
except ValueError:
excinfo = _pytest._code.ExceptionInfo.from_current()
file = StringIO()
reslog = ResultLog(None, file) # type: ignore[arg-type]
reslog.pytest_internalerror(excinfo.getrepr(style=style))
entry = file.getvalue()
entry_lines = entry.splitlines()
assert entry_lines[0].startswith("! ")
if style != "native":
assert os.path.basename(__file__)[:-9] in entry_lines[0] # .pyc/class
assert entry_lines[-1][0] == " "
assert "ValueError" in entry
def test_generic(testdir: Testdir, LineMatcher) -> None:
testdir.plugins.append("resultlog")
testdir.makepyfile(
"""
import pytest
def test_pass():
pass
def test_fail():
assert 0
def test_skip():
pytest.skip("")
@pytest.mark.xfail
def test_xfail():
assert 0
@pytest.mark.xfail(run=False)
def test_xfail_norun():
assert 0
"""
)
testdir.runpytest("--resultlog=result.log")
lines = testdir.tmpdir.join("result.log").readlines(cr=0)
LineMatcher(lines).fnmatch_lines(
[
". *:test_pass",
"F *:test_fail",
"s *:test_skip",
"x *:test_xfail",
"x *:test_xfail_norun",
]
)
def test_makedir_for_resultlog(testdir: Testdir, LineMatcher) -> None:
"""--resultlog should automatically create directories for the log file"""
testdir.plugins.append("resultlog")
testdir.makepyfile(
"""
import pytest
def test_pass():
pass
"""
)
testdir.runpytest("--resultlog=path/to/result.log")
lines = testdir.tmpdir.join("path/to/result.log").readlines(cr=0)
LineMatcher(lines).fnmatch_lines([". *:test_pass"])
def test_no_resultlog_on_workers(testdir: Testdir) -> None:
config = testdir.parseconfig("-p", "resultlog", "--resultlog=resultlog")
assert resultlog_key not in config._store
pytest_configure(config)
assert resultlog_key in config._store
pytest_unconfigure(config)
assert resultlog_key not in config._store
config.workerinput = {} # type: ignore[attr-defined]
pytest_configure(config)
assert resultlog_key not in config._store
pytest_unconfigure(config)
assert resultlog_key not in config._store
def test_unknown_teststatus(testdir: Testdir) -> None:
"""Ensure resultlog correctly handles unknown status from pytest_report_teststatus
Inspired on pytest-rerunfailures.
"""
testdir.makepyfile(
"""
def test():
assert 0
"""
)
testdir.makeconftest(
"""
import pytest
def pytest_report_teststatus(report):
if report.outcome == 'rerun':
return "rerun", "r", "RERUN"
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport():
res = yield
report = res.get_result()
if report.when == "call":
report.outcome = 'rerun'
"""
)
result = testdir.runpytest("--resultlog=result.log")
result.stdout.fnmatch_lines(
["test_unknown_teststatus.py r *[[]100%[]]", "* 1 rerun *"]
)
lines = testdir.tmpdir.join("result.log").readlines(cr=0)
assert lines[0] == "r test_unknown_teststatus.py::test"
def test_failure_issue380(testdir: Testdir) -> None:
testdir.makeconftest(
"""
import pytest
class MyCollector(pytest.File):
def collect(self):
raise ValueError()
def repr_failure(self, excinfo):
return "somestring"
def pytest_collect_file(path, parent):
return MyCollector(parent=parent, fspath=path)
"""
)
testdir.makepyfile(
"""
def test_func():
pass
"""
)
result = testdir.runpytest("--resultlog=log")
assert result.ret == 2

View File

@ -513,6 +513,9 @@ class TestDeprecationWarningsByDefault:
@pytest.mark.parametrize("change_default", [None, "ini", "cmdline"]) @pytest.mark.parametrize("change_default", [None, "ini", "cmdline"])
@pytest.mark.skip(
reason="This test should be enabled again before pytest 7.0 is released"
)
def test_deprecation_warning_as_error(testdir, change_default): def test_deprecation_warning_as_error(testdir, change_default):
"""This ensures that PytestDeprecationWarnings raised by pytest are turned into errors. """This ensures that PytestDeprecationWarnings raised by pytest are turned into errors.
@ -737,31 +740,6 @@ class TestStackLevel:
assert "config{sep}__init__.py".format(sep=os.sep) in file assert "config{sep}__init__.py".format(sep=os.sep) in file
assert func == "import_plugin" assert func == "import_plugin"
def test_issue4445_resultlog(self, testdir, capwarn):
"""#4445: Make sure the warning points to a reasonable location
See origin of _issue_warning_captured at: _pytest.resultlog.py:35
"""
testdir.makepyfile(
"""
def test_dummy():
pass
"""
)
# Use parseconfigure() because the warning in resultlog.py is triggered in
# the pytest_configure hook
testdir.parseconfigure(
"--result-log={dir}".format(dir=testdir.tmpdir.join("result.log"))
)
# with stacklevel=2 the warning originates from resultlog.pytest_configure
# and is thrown when --result-log is used
warning, location = capwarn.captured.pop()
file, _, func = location
assert "--result-log is deprecated" in str(warning.message)
assert "resultlog.py" in file
assert func == "pytest_configure"
def test_issue4445_issue5928_mark_generator(self, testdir): def test_issue4445_issue5928_mark_generator(self, testdir):
"""#4445 and #5928: Make sure the warning from an unknown mark points to """#4445 and #5928: Make sure the warning from an unknown mark points to
the test file where this mark is used. the test file where this mark is used.