Skip to content

Commit

Permalink
feat: add --fold-skipped=yes|no cli option
Browse files Browse the repository at this point in the history
This controlls how the skipped tests are display in the short summary.

- yes (default): keeps the current behavior that folds the skipped tests
  together
- no: each skipped test is on its own line, display as any other status

Resolves: #9876
Signed-off-by: Pavel Březina <[email protected]>
  • Loading branch information
pbrezina committed Jul 4, 2024
1 parent ac41898 commit 86c80da
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 1 deletion.
7 changes: 7 additions & 0 deletions changelog/12567.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Added ``--no-fold-skipped`` command line option

If this option is set, then skipped tests in short summary are no longer grouped
by reason but all tests are printed individually with correct nodeid in the same
way as other statuses.

-- by :user:`pbrezina`
5 changes: 5 additions & 0 deletions doc/en/how-to/output.rst
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,11 @@ captured output:
PASSED test_example.py::test_ok
== 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12s ===
.. note::

By default, parametrized variants of skipped tests are grouped together if
they share the same skip reason. You can use ``--no-fold-skipped`` to print each skipped test separately.

Creating resultlog format files
--------------------------------------------------

Expand Down
35 changes: 34 additions & 1 deletion src/_pytest/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@ def pytest_addoption(parser: Parser) -> None:
dest="no_summary",
help="Disable summary",
)
group._addoption(
"--no-fold-skipped",
action="store_false",
dest="fold_skipped",
default=True,
help="Do not fold skipped tests in short summary.",
)
group._addoption(
"-q",
"--quiet",
Expand Down Expand Up @@ -371,6 +378,7 @@ def __init__(self, config: Config, file: TextIO | None = None) -> None:
self._screen_width = self._tw.fullwidth
self.currentfspath: None | Path | str | int = None
self.reportchars = getreportopt(config)
self.foldskipped = config.option.fold_skipped
self.hasmarkup = self._tw.hasmarkup
self.isatty = file.isatty()
self._progress_nodeids_reported: set[str] = set()
Expand Down Expand Up @@ -1232,7 +1240,7 @@ def show_xpassed(lines: list[str]) -> None:
line += " - " + str(reason)
lines.append(line)

def show_skipped(lines: list[str]) -> None:
def show_skipped_folded(lines: list[str]) -> None:
skipped: list[CollectReport] = self.stats.get("skipped", [])
fskips = _folded_skips(self.startpath, skipped) if skipped else []
if not fskips:
Expand All @@ -1252,6 +1260,31 @@ def show_skipped(lines: list[str]) -> None:
else:
lines.append("%s [%d] %s: %s" % (markup_word, num, fspath, reason))

def show_skipped_unfolded(lines: list[str]) -> None:
skipped: list[CollectReport] = self.stats.get("skipped", [])

for rep in skipped:
assert rep.longrepr is not None
assert isinstance(rep.longrepr, tuple), (rep, rep.longrepr)
assert len(rep.longrepr) == 3, (rep, rep.longrepr)

verbose_word, verbose_markup = rep._get_verbose_word_with_markup(
self.config, {_color_for_type["warnings"]: True}
)
markup_word = self._tw.markup(verbose_word, **verbose_markup)
nodeid = _get_node_id_with_markup(self._tw, self.config, rep)
line = f"{markup_word} {nodeid}"
reason = rep.longrepr[2]
if reason:
line += " - " + str(reason)
lines.append(line)

def show_skipped(lines: list[str]) -> None:
if self.foldskipped:
show_skipped_folded(lines)
else:
show_skipped_unfolded(lines)

REPORTCHAR_ACTIONS: Mapping[str, Callable[[list[str]], None]] = {
"x": show_xfailed,
"X": show_xpassed,
Expand Down
38 changes: 38 additions & 0 deletions testing/test_terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,44 @@ def test():
result.stdout.fnmatch_lines([expected])
assert result.stdout.lines.count(expected) == 1

def test_summary_s_folded(self, pytester: Pytester) -> None:
"""Test that skipped tests are correctly folded"""
pytester.makepyfile(
"""
import pytest
@pytest.mark.parametrize("param", [True, False])
@pytest.mark.skip("Some reason")
def test(param):
pass
"""
)
result = pytester.runpytest("-rs")
expected = "SKIPPED [2] test_summary_s_folded.py:3: Some reason"
result.stdout.fnmatch_lines([expected])
assert result.stdout.lines.count(expected) == 1

def test_summary_s_unfolded(self, pytester: Pytester) -> None:
"""Test that skipped tests are not folded if --no-fold-skipped is set"""
pytester.makepyfile(
"""
import pytest
@pytest.mark.parametrize("param", [True, False])
@pytest.mark.skip("Some reason")
def test(param):
pass
"""
)
result = pytester.runpytest("-rs", "--no-fold-skipped")
expected = [
"SKIPPED test_summary_s_unfolded.py::test[True] - Skipped: Some reason",
"SKIPPED test_summary_s_unfolded.py::test[False] - Skipped: Some reason",
]
result.stdout.fnmatch_lines(expected)
assert result.stdout.lines.count(expected[0]) == 1
assert result.stdout.lines.count(expected[1]) == 1


@pytest.mark.parametrize(
("use_ci", "expected_message"),
Expand Down

0 comments on commit 86c80da

Please sign in to comment.