Merge branch 'okken_12231_xfail_tb' of https://github.com/okken/pytest into okken_12231_xfail_tb
This commit is contained in:
commit
60a58a52ca
|
@ -10,12 +10,7 @@ repos:
|
|||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: fix-encoding-pragma
|
||||
args: [--remove]
|
||||
- id: check-yaml
|
||||
- id: debug-statements
|
||||
exclude: _pytest/(debugging|hookspec).py
|
||||
language_version: python3
|
||||
- repo: https://github.com/adamchainz/blacken-docs
|
||||
rev: 1.16.0
|
||||
hooks:
|
||||
|
@ -50,13 +45,13 @@ repos:
|
|||
additional_dependencies: ["tox>=4.9"]
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: pylint
|
||||
name: pylint
|
||||
entry: pylint
|
||||
language: system
|
||||
types: [python]
|
||||
args: ["-rn", "-sn", "--fail-on=I"]
|
||||
stages: [manual]
|
||||
- id: pylint
|
||||
name: pylint
|
||||
entry: pylint
|
||||
language: system
|
||||
types: [python]
|
||||
args: ["-rn", "-sn", "--fail-on=I"]
|
||||
stages: [manual]
|
||||
- id: rst
|
||||
name: rst
|
||||
entry: rst-lint --encoding utf-8
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Documented using :envvar:`PYTEST_VERSION` to detect if code is running from within a pytest run.
|
|
@ -4,7 +4,7 @@ Add `--xfail-tb` flag, which turns traceback output for XFAIL results.
|
|||
* The style of traceback for XFAIL is set with `--tb`, and can be `auto|long|short|line|native|no`.
|
||||
* Note: Even if you have `--xfail-tb` set, you won't see them if `--tb=no`.
|
||||
|
||||
Some history:
|
||||
Some history:
|
||||
|
||||
* This is a behavior break, but brings default behavior back to pre-8.0.0 behavior.
|
||||
* With this change, default `-rx`/ `-ra` behavior is identical to pre-8.0 with respect to xfail tracebacks.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Fixed progress percentages (the ``[ 87%]`` at the edge of the screen) sometimes not aligning correctly when running with pytest-xdist ``-n``.
|
|
@ -405,35 +405,20 @@ Detect if running from within a pytest run
|
|||
Usually it is a bad idea to make application code
|
||||
behave differently if called from a test. But if you
|
||||
absolutely must find out if your application code is
|
||||
running from a test you can do something like this:
|
||||
running from a test you can do this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of your_module.py
|
||||
import os
|
||||
|
||||
|
||||
_called_from_test = False
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of conftest.py
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
your_module._called_from_test = True
|
||||
|
||||
and then check for the ``your_module._called_from_test`` flag:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if your_module._called_from_test:
|
||||
# called from within a test run
|
||||
if os.environ.get("PYTEST_VERSION") is not None:
|
||||
# Things you want to to do if your code is called by pytest.
|
||||
...
|
||||
else:
|
||||
# called "normally"
|
||||
# Things you want to to do if your code is not called by pytest.
|
||||
...
|
||||
|
||||
accordingly in your application.
|
||||
|
||||
Adding info to test report header
|
||||
--------------------------------------------------------------
|
||||
|
|
|
@ -107,6 +107,7 @@ select = [
|
|||
"PLE", # pylint error
|
||||
"PLW", # pylint warning
|
||||
"PLR1714", # Consider merging multiple comparisons
|
||||
"T100", # flake8-debugger
|
||||
]
|
||||
ignore = [
|
||||
# bugbear ignore
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# mypy: allow-untyped-defs
|
||||
# ruff: noqa: T100
|
||||
"""Interactive debugging with PDB, the Python Debugger."""
|
||||
|
||||
import argparse
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# mypy: allow-untyped-defs
|
||||
# ruff: noqa: T100
|
||||
"""Hook specifications for pytest plugins which are invoked by pytest itself
|
||||
and by builtin plugins."""
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ def pytest_runtest_call(item: Item) -> None:
|
|||
assert e.__traceback__ is not None
|
||||
# Skip *this* frame
|
||||
sys.last_traceback = e.__traceback__.tb_next
|
||||
raise e
|
||||
raise
|
||||
|
||||
|
||||
def pytest_runtest_teardown(item: Item, nextitem: Optional[Item]) -> None:
|
||||
|
@ -512,7 +512,7 @@ class SetupState:
|
|||
col.setup()
|
||||
except TEST_OUTCOME as exc:
|
||||
self.stack[col] = (self.stack[col][0], exc)
|
||||
raise exc
|
||||
raise
|
||||
|
||||
def addfinalizer(self, finalizer: Callable[[], object], node: Node) -> None:
|
||||
"""Attach a finalizer to the given node.
|
||||
|
|
|
@ -439,7 +439,7 @@ class TerminalReporter:
|
|||
char = {"xfailed": "x", "skipped": "s"}.get(char, char)
|
||||
return char in self.reportchars
|
||||
|
||||
def write_fspath_result(self, nodeid: str, res, **markup: bool) -> None:
|
||||
def write_fspath_result(self, nodeid: str, res: str, **markup: bool) -> None:
|
||||
fspath = self.config.rootpath / nodeid.split("::")[0]
|
||||
if self.currentfspath is None or fspath != self.currentfspath:
|
||||
if self.currentfspath is not None and self._show_progress_info:
|
||||
|
@ -572,10 +572,11 @@ class TerminalReporter:
|
|||
def pytest_runtest_logstart(
|
||||
self, nodeid: str, location: Tuple[str, Optional[int], str]
|
||||
) -> None:
|
||||
fspath, lineno, domain = location
|
||||
# Ensure that the path is printed before the
|
||||
# 1st test of a module starts running.
|
||||
if self.showlongtestinfo:
|
||||
line = self._locationline(nodeid, *location)
|
||||
line = self._locationline(nodeid, fspath, lineno, domain)
|
||||
self.write_ensure_prefix(line, "")
|
||||
self.flush()
|
||||
elif self.showfspath:
|
||||
|
@ -598,7 +599,6 @@ class TerminalReporter:
|
|||
if not letter and not word:
|
||||
# Probably passed setup/teardown.
|
||||
return
|
||||
running_xdist = hasattr(rep, "node")
|
||||
if markup is None:
|
||||
was_xfail = hasattr(report, "wasxfail")
|
||||
if rep.passed and not was_xfail:
|
||||
|
@ -611,11 +611,20 @@ class TerminalReporter:
|
|||
markup = {"yellow": True}
|
||||
else:
|
||||
markup = {}
|
||||
self._progress_nodeids_reported.add(rep.nodeid)
|
||||
if self.config.get_verbosity(Config.VERBOSITY_TEST_CASES) <= 0:
|
||||
self._tw.write(letter, **markup)
|
||||
# When running in xdist, the logreport and logfinish of multiple
|
||||
# items are interspersed, e.g. `logreport`, `logreport`,
|
||||
# `logfinish`, `logfinish`. To avoid the "past edge" calculation
|
||||
# from getting confused and overflowing (#7166), do the past edge
|
||||
# printing here and not in logfinish, except for the 100% which
|
||||
# should only be printed after all teardowns are finished.
|
||||
if self._show_progress_info and not self._is_last_item:
|
||||
self._write_progress_information_if_past_edge()
|
||||
else:
|
||||
self._progress_nodeids_reported.add(rep.nodeid)
|
||||
line = self._locationline(rep.nodeid, *rep.location)
|
||||
running_xdist = hasattr(rep, "node")
|
||||
if not running_xdist:
|
||||
self.write_ensure_prefix(line, word, **markup)
|
||||
if rep.skipped or hasattr(report, "wasxfail"):
|
||||
|
@ -655,39 +664,29 @@ class TerminalReporter:
|
|||
assert self._session is not None
|
||||
return len(self._progress_nodeids_reported) == self._session.testscollected
|
||||
|
||||
def pytest_runtest_logfinish(self, nodeid: str) -> None:
|
||||
assert self._session
|
||||
@hookimpl(wrapper=True)
|
||||
def pytest_runtestloop(self) -> Generator[None, object, object]:
|
||||
result = yield
|
||||
|
||||
# Write the final/100% progress -- deferred until the loop is complete.
|
||||
if (
|
||||
self.config.get_verbosity(Config.VERBOSITY_TEST_CASES) <= 0
|
||||
and self._show_progress_info
|
||||
and self._progress_nodeids_reported
|
||||
):
|
||||
if self._show_progress_info == "count":
|
||||
num_tests = self._session.testscollected
|
||||
progress_length = len(f" [{num_tests}/{num_tests}]")
|
||||
else:
|
||||
progress_length = len(" [100%]")
|
||||
self._write_progress_information_filling_space()
|
||||
|
||||
self._progress_nodeids_reported.add(nodeid)
|
||||
|
||||
if self._is_last_item:
|
||||
self._write_progress_information_filling_space()
|
||||
else:
|
||||
main_color, _ = self._get_main_color()
|
||||
w = self._width_of_current_line
|
||||
past_edge = w + progress_length + 1 >= self._screen_width
|
||||
if past_edge:
|
||||
msg = self._get_progress_information_message()
|
||||
self._tw.write(msg + "\n", **{main_color: True})
|
||||
return result
|
||||
|
||||
def _get_progress_information_message(self) -> str:
|
||||
assert self._session
|
||||
collected = self._session.testscollected
|
||||
if self._show_progress_info == "count":
|
||||
if collected:
|
||||
progress = self._progress_nodeids_reported
|
||||
progress = len(self._progress_nodeids_reported)
|
||||
counter_format = f"{{:{len(str(collected))}d}}"
|
||||
format_string = f" [{counter_format}/{{}}]"
|
||||
return format_string.format(len(progress), collected)
|
||||
return format_string.format(progress, collected)
|
||||
return f" [ {collected} / {collected} ]"
|
||||
else:
|
||||
if collected:
|
||||
|
@ -696,6 +695,20 @@ class TerminalReporter:
|
|||
)
|
||||
return " [100%]"
|
||||
|
||||
def _write_progress_information_if_past_edge(self) -> None:
|
||||
w = self._width_of_current_line
|
||||
if self._show_progress_info == "count":
|
||||
assert self._session
|
||||
num_tests = self._session.testscollected
|
||||
progress_length = len(f" [{num_tests}/{num_tests}]")
|
||||
else:
|
||||
progress_length = len(" [100%]")
|
||||
past_edge = w + progress_length + 1 >= self._screen_width
|
||||
if past_edge:
|
||||
main_color, _ = self._get_main_color()
|
||||
msg = self._get_progress_information_message()
|
||||
self._tw.write(msg + "\n", **{main_color: True})
|
||||
|
||||
def _write_progress_information_filling_space(self) -> None:
|
||||
color, _ = self._get_main_color()
|
||||
msg = self._get_progress_information_message()
|
||||
|
@ -944,7 +957,7 @@ class TerminalReporter:
|
|||
line += "[".join(values)
|
||||
return line
|
||||
|
||||
# collect_fspath comes from testid which has a "/"-normalized path.
|
||||
# fspath comes from testid which has a "/"-normalized path.
|
||||
if fspath:
|
||||
res = mkrel(nodeid)
|
||||
if self.verbosity >= 2 and nodeid.split("::")[0] != fspath.replace(
|
||||
|
|
|
@ -2965,7 +2965,7 @@ def test_xfail_tb_true(xfail_testfile, pytester: Pytester) -> None:
|
|||
"*E assert 3 == 4*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
|
||||
def test_xfail_tb_line(xfail_testfile, pytester: Pytester) -> None:
|
||||
result = pytester.runpytest(xfail_testfile, "--xfail-tb", "--tb=line")
|
||||
|
|
Loading…
Reference in New Issue