Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions src/_pytest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,7 @@ def pytest_collection(session):

def pytest_runtestloop(session):
if session.testsfailed and not session.config.option.continue_on_collection_errors:
raise session.Interrupted(
"%d error%s during collection"
% (session.testsfailed, "s" if session.testsfailed != 1 else "")
)
raise session.Interrupted("%d errors during collection" % session.testfailed)

if session.config.option.collectonly:
return True
Expand Down
16 changes: 2 additions & 14 deletions src/_pytest/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ def report_collect(self, final=False):
str(self._numcollected) + " item" + ("" if self._numcollected == 1 else "s")
)
if errors:
line += " / %d error%s" % (errors, "s" if errors != 1 else "")
line += " / %d errors" % errors
if deselected:
line += " / %d deselected" % deselected
if skipped:
Expand Down Expand Up @@ -1087,18 +1087,6 @@ def _folded_skips(skipped):
_color_for_type_default = "yellow"


def _make_plural(count, noun):
# No need to pluralize words such as `failed` or `passed`.
if noun not in ["error", "warnings"]:
return count, noun

# The `warnings` key is plural. To avoid API breakage, we keep it that way but
# set it to singular here so we can determine plurality in the same way as we do
# for `error`.
noun = noun.replace("warnings", "warning")

return count, noun + "s" if count != 1 else noun


def _get_main_color(stats) -> Tuple[str, List[str]]:
known_types = (
Expand Down Expand Up @@ -1136,7 +1124,7 @@ def build_summary_stats_line(stats):
)
color = _color_for_type.get(key, _color_for_type_default)
markup = {color: True, "bold": color == main_color}
parts.append(("%d %s" % _make_plural(count, key), markup))
parts.append(("%d %s" % (count, key), markup))

if not parts:
parts = [("no tests ran", {_color_for_type_default: True})]
Expand Down
4 changes: 2 additions & 2 deletions testing/acceptance_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ def test_pyargs_importerror(self, testdir, monkeypatch):
result = testdir.runpytest("--pyargs", "tpkg.test_hello", syspathinsert=True)
assert result.ret != 0

result.stdout.fnmatch_lines(["collected*0*items*/*1*error"])
result.stdout.fnmatch_lines(["collected*0*items*/*1*errors"])

def test_pyargs_only_imported_once(self, testdir):
pkg = testdir.mkpydir("foo")
Expand Down Expand Up @@ -963,7 +963,7 @@ def test_with_failing_collection(self, testdir):
testdir.makepyfile(test_collecterror="""xyz""")
result = testdir.runpytest("--durations=2", "-k test_1")
assert result.ret == 2
result.stdout.fnmatch_lines(["*Interrupted: 1 error during collection*"])
result.stdout.fnmatch_lines(["*Interrupted: 1 errors during collection*"])
# Collection errors abort test execution, therefore no duration is
# output
result.stdout.no_fnmatch_line("*duration*")
Expand Down
2 changes: 1 addition & 1 deletion testing/python/collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@ def test_real():
[
"*collected 1 item*",
"*test_dont_collect_non_function_callable.py:2: *cannot collect 'test_a' because it is not a function*",
"*1 passed, 1 warning in *",
"*1 passed, 1 warnings in *",
]
)

Expand Down
2 changes: 1 addition & 1 deletion testing/python/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -3113,7 +3113,7 @@ def test_3():
*KeyError*
*ERROR*teardown*test_2*
*KeyError*
*3 pass*2 errors*
*3 pass*2 error*
"""
)

Expand Down
2 changes: 1 addition & 1 deletion testing/test_assertrewrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def test_dont_rewrite_plugin(self, testdir):
}
testdir.makepyfile(**contents)
result = testdir.runpytest_subprocess()
assert "warning" not in "".join(result.outlines)
assert "warnings" not in "".join(result.outlines)

def test_rewrites_plugin_as_a_package(self, testdir):
pkgdir = testdir.mkpydir("plugin")
Expand Down
2 changes: 1 addition & 1 deletion testing/test_capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ def test_two(capfd, capsys):
"E*capfd*capsys*same*time*",
"*ERROR*setup*test_two*",
"E*capsys*capfd*same*time*",
"*2 errors*",
"*2 error*",
]
)

Expand Down
6 changes: 3 additions & 3 deletions testing/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,7 @@ def test_continue_on_collection_errors(testdir):
assert res.ret == 1

res.stdout.fnmatch_lines(
["collected 2 items / 2 errors", "*1 failed, 1 passed, 2 errors*"]
["collected 2 items / 2 errors", "*1 failed, 1 passed, 2 error*"]
)


Expand All @@ -925,7 +925,7 @@ def test_continue_on_collection_errors_maxfail(testdir):
res = testdir.runpytest("--continue-on-collection-errors", "--maxfail=3")
assert res.ret == 1

res.stdout.fnmatch_lines(["collected 2 items / 2 errors", "*1 failed, 2 errors*"])
res.stdout.fnmatch_lines(["collected 2 items / 2 errors", "*1 failed, 2 error*"])


def test_fixture_scope_sibling_conftests(testdir):
Expand Down Expand Up @@ -1269,7 +1269,7 @@ def test_collector_respects_tbstyle(testdir):
' File "*/test_collector_respects_tbstyle.py", line 1, in <module>',
" assert 0",
"AssertionError: assert 0",
"*! Interrupted: 1 error during collection !*",
"*! Interrupted: 1 errors during collection !*",
"*= 1 error in *",
]
)
Expand Down
2 changes: 1 addition & 1 deletion testing/test_doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ def test_doctest_unex_importerror_with_module(self, testdir):
[
"*ERROR collecting hello.py*",
"*{e}: No module named *asdals*".format(e=MODULE_NOT_FOUND_ERROR),
"*Interrupted: 1 error during collection*",
"*Interrupted: 1 errors during collection*",
]
)

Expand Down
19 changes: 18 additions & 1 deletion testing/test_pytester.py
Original file line number Diff line number Diff line change
Expand Up @@ -709,9 +709,26 @@ def test_error2(bad_fixture):
result = testdir.runpytest(str(p1))
result.assert_outcomes(error=2)

assert result.parseoutcomes() == {"error": 2}
assert result.parseoutcomes() == {"errors": 2}


def test_testdir_outcomes_with_single_error(testdir):
p1 = testdir.makepyfile(
"""
import pytest

@pytest.fixture
def bad_fixture():
raise Exception("bad")

def test_error1(bad_fixture):
pass
"""
)
result = testdir.runpytest(str(p1))
result.assert_outcomes(error=1)
assert result.parseoutcomes() == {"errors": 1}

def test_makefile_joins_absolute_path(testdir: Testdir) -> None:
absfile = testdir.tmpdir / "absfile"
if sys.platform == "win32":
Expand Down