Merge pull request #7364 from nicoddemus/parseoutcomes-plural-6505

assertoutcomes() only accepts plural forms
This commit is contained in:
Bruno Oliveira 2020-06-15 20:27:40 -03:00 committed by GitHub
commit db00612b84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 12 deletions

View File

@ -0,0 +1,20 @@
``Testdir.run().parseoutcomes()`` now always returns the parsed nouns in plural form.
Originally ``parseoutcomes()`` would always returns the nouns in plural form, but a change
meant to improve the terminal summary by using singular form single items (``1 warning`` or ``1 error``)
caused an unintended regression by changing the keys returned by ``parseoutcomes()``.
Now the API guarantees to always return the plural form, so calls like this:
.. code-block:: python
result = testdir.runpytest()
result.assert_outcomes(error=1)
Need to be changed to:
.. code-block:: python
result = testdir.runpytest()
result.assert_outcomes(errors=1)

View File

@ -452,28 +452,47 @@ class RunResult:
) )
def parseoutcomes(self) -> Dict[str, int]: def parseoutcomes(self) -> Dict[str, int]:
"""Return a dictionary of outcomestring->num from parsing the terminal """Return a dictionary of outcome noun -> count from parsing the terminal
output that the test process produced. output that the test process produced.
The returned nouns will always be in plural form::
======= 1 failed, 1 passed, 1 warning, 1 error in 0.13s ====
Will return ``{"failed": 1, "passed": 1, "warnings": 1, "errors": 1}``
""" """
for line in reversed(self.outlines): return self.parse_summary_nouns(self.outlines)
@classmethod
def parse_summary_nouns(cls, lines) -> Dict[str, int]:
"""Extracts the nouns from a pytest terminal summary line.
It always returns the plural noun for consistency::
======= 1 failed, 1 passed, 1 warning, 1 error in 0.13s ====
Will return ``{"failed": 1, "passed": 1, "warnings": 1, "errors": 1}``
"""
for line in reversed(lines):
if rex_session_duration.search(line): if rex_session_duration.search(line):
outcomes = rex_outcome.findall(line) outcomes = rex_outcome.findall(line)
ret = {noun: int(count) for (count, noun) in outcomes} ret = {noun: int(count) for (count, noun) in outcomes}
break break
else: else:
raise ValueError("Pytest terminal summary report not found") raise ValueError("Pytest terminal summary report not found")
if "errors" in ret:
assert "error" not in ret to_plural = {
ret["error"] = ret.pop("errors") "warning": "warnings",
return ret "error": "errors",
}
return {to_plural.get(k, k): v for k, v in ret.items()}
def assert_outcomes( def assert_outcomes(
self, self,
passed: int = 0, passed: int = 0,
skipped: int = 0, skipped: int = 0,
failed: int = 0, failed: int = 0,
error: int = 0, errors: int = 0,
xpassed: int = 0, xpassed: int = 0,
xfailed: int = 0, xfailed: int = 0,
) -> None: ) -> None:
@ -487,7 +506,7 @@ class RunResult:
"passed": d.get("passed", 0), "passed": d.get("passed", 0),
"skipped": d.get("skipped", 0), "skipped": d.get("skipped", 0),
"failed": d.get("failed", 0), "failed": d.get("failed", 0),
"error": d.get("error", 0), "errors": d.get("errors", 0),
"xpassed": d.get("xpassed", 0), "xpassed": d.get("xpassed", 0),
"xfailed": d.get("xfailed", 0), "xfailed": d.get("xfailed", 0),
} }
@ -495,7 +514,7 @@ class RunResult:
"passed": passed, "passed": passed,
"skipped": skipped, "skipped": skipped,
"failed": failed, "failed": failed,
"error": error, "errors": errors,
"xpassed": xpassed, "xpassed": xpassed,
"xfailed": xfailed, "xfailed": xfailed,
} }

View File

@ -4344,6 +4344,6 @@ def test_yield_fixture_with_no_value(testdir):
) )
expected = "E ValueError: custom did not yield a value" expected = "E ValueError: custom did not yield a value"
result = testdir.runpytest() result = testdir.runpytest()
result.assert_outcomes(error=1) result.assert_outcomes(errors=1)
result.stdout.fnmatch_lines([expected]) result.stdout.fnmatch_lines([expected])
assert result.ret == ExitCode.TESTS_FAILED assert result.ret == ExitCode.TESTS_FAILED

View File

@ -763,9 +763,38 @@ def test_testdir_outcomes_with_multiple_errors(testdir):
""" """
) )
result = testdir.runpytest(str(p1)) result = testdir.runpytest(str(p1))
result.assert_outcomes(error=2) result.assert_outcomes(errors=2)
assert result.parseoutcomes() == {"error": 2} assert result.parseoutcomes() == {"errors": 2}
def test_parse_summary_line_always_plural():
"""Parsing summaries always returns plural nouns (#6505)"""
lines = [
"some output 1",
"some output 2",
"======= 1 failed, 1 passed, 1 warning, 1 error in 0.13s ====",
"done.",
]
assert pytester.RunResult.parse_summary_nouns(lines) == {
"errors": 1,
"failed": 1,
"passed": 1,
"warnings": 1,
}
lines = [
"some output 1",
"some output 2",
"======= 1 failed, 1 passed, 2 warnings, 2 errors in 0.13s ====",
"done.",
]
assert pytester.RunResult.parse_summary_nouns(lines) == {
"errors": 2,
"failed": 1,
"passed": 1,
"warnings": 2,
}
def test_makefile_joins_absolute_path(testdir: Testdir) -> None: def test_makefile_joins_absolute_path(testdir: Testdir) -> None: