Merge pull request #5034 from blueyed/run-last-failure-report

run-last-failure: improve reporting
This commit is contained in:
Daniel Hahler 2019-04-04 00:40:40 +02:00 committed by GitHub
commit 0d4636b056
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 24 deletions

View File

@ -0,0 +1 @@
Improve reporting with ``--lf`` and ``--ff`` (run-last-failure).

View File

@ -157,18 +157,11 @@ class LFPlugin(object):
self.active = any(config.getoption(key) for key in active_keys)
self.lastfailed = config.cache.get("cache/lastfailed", {})
self._previously_failed_count = None
self._no_failures_behavior = self.config.getoption("last_failed_no_failures")
self._report_status = None
def pytest_report_collectionfinish(self):
if self.active and self.config.getoption("verbose") >= 0:
if not self._previously_failed_count:
return None
noun = "failure" if self._previously_failed_count == 1 else "failures"
suffix = " first" if self.config.getoption("failedfirst") else ""
mode = "rerun previous {count} {noun}{suffix}".format(
count=self._previously_failed_count, suffix=suffix, noun=noun
)
return "run-last-failure: %s" % mode
return "run-last-failure: %s" % self._report_status
def pytest_runtest_logreport(self, report):
if (report.when == "call" and report.passed) or report.skipped:
@ -196,18 +189,35 @@ class LFPlugin(object):
else:
previously_passed.append(item)
self._previously_failed_count = len(previously_failed)
if not previously_failed:
# running a subset of all tests with recorded failures outside
# of the set of tests currently executing
return
if self.config.getoption("lf"):
items[:] = previously_failed
config.hook.pytest_deselected(items=previously_passed)
# Running a subset of all tests with recorded failures
# only outside of it.
self._report_status = "%d known failures not in selected tests" % (
len(self.lastfailed),
)
else:
items[:] = previously_failed + previously_passed
elif self._no_failures_behavior == "none":
config.hook.pytest_deselected(items=items)
items[:] = []
if self.config.getoption("lf"):
items[:] = previously_failed
config.hook.pytest_deselected(items=previously_passed)
else: # --failedfirst
items[:] = previously_failed + previously_passed
noun = (
"failure" if self._previously_failed_count == 1 else "failures"
)
suffix = " first" if self.config.getoption("failedfirst") else ""
self._report_status = "rerun previous {count} {noun}{suffix}".format(
count=self._previously_failed_count, suffix=suffix, noun=noun
)
else:
self._report_status = "no previously failed tests, "
if self.config.getoption("last_failed_no_failures") == "none":
self._report_status += "deselecting all items."
config.hook.pytest_deselected(items=items)
items[:] = []
else:
self._report_status += "not deselecting items."
def pytest_sessionfinish(self, session):
config = self.config
@ -303,8 +313,7 @@ def pytest_addoption(parser):
dest="last_failed_no_failures",
choices=("all", "none"),
default="all",
help="change the behavior when no test failed in the last run or no "
"information about the last failures was found in the cache",
help="which tests to run with no previously (known) failures.",
)

View File

@ -10,6 +10,7 @@ import textwrap
import py
import pytest
from _pytest.main import EXIT_NOTESTSCOLLECTED
pytest_plugins = ("pytester",)
@ -251,7 +252,13 @@ class TestLastFailed(object):
result = testdir.runpytest("--lf")
result.stdout.fnmatch_lines(["*2 passed*1 desel*"])
result = testdir.runpytest("--lf")
result.stdout.fnmatch_lines(["*1 failed*2 passed*"])
result.stdout.fnmatch_lines(
[
"collected 3 items",
"run-last-failure: no previously failed tests, not deselecting items.",
"*1 failed*2 passed*",
]
)
result = testdir.runpytest("--lf", "--cache-clear")
result.stdout.fnmatch_lines(["*1 failed*2 passed*"])
@ -425,7 +432,13 @@ class TestLastFailed(object):
)
result = testdir.runpytest(test_a, "--lf")
result.stdout.fnmatch_lines(["collected 2 items", "*2 passed in*"])
result.stdout.fnmatch_lines(
[
"collected 2 items",
"run-last-failure: 2 known failures not in selected tests",
"*2 passed in*",
]
)
result = testdir.runpytest(test_b, "--lf")
result.stdout.fnmatch_lines(
@ -721,7 +734,14 @@ class TestLastFailed(object):
result = testdir.runpytest("--lf", "--lfnf", "all")
result.stdout.fnmatch_lines(["*2 passed*"])
result = testdir.runpytest("--lf", "--lfnf", "none")
result.stdout.fnmatch_lines(["*2 desel*"])
result.stdout.fnmatch_lines(
[
"collected 2 items / 2 deselected",
"run-last-failure: no previously failed tests, deselecting all items.",
"* 2 deselected in *",
]
)
assert result.ret == EXIT_NOTESTSCOLLECTED
def test_lastfailed_no_failures_behavior_empty_cache(self, testdir):
testdir.makepyfile(