Skip to content

Commit a605ad4

Browse files
authored
Merge pull request #3880 from jeffreyrack/3829-progress_display_mode
#3829 -- Add the ability to show test progress as number of tests completed instead of a percent.
2 parents 80eef29 + 4b94760 commit a605ad4

File tree

4 files changed

+65
-8
lines changed

4 files changed

+65
-8
lines changed

changelog/3829.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added the ``count`` option to ``console_output_style`` to enable displaying the progress as a count instead of a percentage.

doc/en/reference.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,7 @@ passed multiple times. The expected format is ``name=value``. For example::
940940

941941
* ``classic``: classic pytest output.
942942
* ``progress``: like classic pytest output, but with a progress indicator.
943+
* ``count``: like progress, but shows progress as the number of tests completed instead of a percent.
943944

944945
The default is ``progress``, but you can fallback to ``classic`` if you prefer or
945946
the new mode is causing unexpected problems:

src/_pytest/terminal.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ def _determine_show_progress_info(self):
254254
# do not show progress if we are showing fixture setup/teardown
255255
if self.config.getoption("setupshow"):
256256
return False
257-
return self.config.getini("console_output_style") == "progress"
257+
return self.config.getini("console_output_style") in ("progress", "count")
258258

259259
def hasopt(self, char):
260260
char = {"xfailed": "x", "skipped": "s"}.get(char, char)
@@ -404,6 +404,12 @@ def pytest_runtest_logreport(self, report):
404404
self.currentfspath = -2
405405

406406
def pytest_runtest_logfinish(self, nodeid):
407+
if self.config.getini("console_output_style") == "count":
408+
num_tests = self._session.testscollected
409+
progress_length = len(" [{}/{}]".format(str(num_tests), str(num_tests)))
410+
else:
411+
progress_length = len(" [100%]")
412+
407413
if self.verbosity <= 0 and self._show_progress_info:
408414
self._progress_nodeids_reported.add(nodeid)
409415
last_item = (
@@ -413,23 +419,29 @@ def pytest_runtest_logfinish(self, nodeid):
413419
self._write_progress_information_filling_space()
414420
else:
415421
past_edge = (
416-
self._tw.chars_on_current_line + self._PROGRESS_LENGTH + 1
422+
self._tw.chars_on_current_line + progress_length + 1
417423
>= self._screen_width
418424
)
419425
if past_edge:
420426
msg = self._get_progress_information_message()
421427
self._tw.write(msg + "\n", cyan=True)
422428

423-
_PROGRESS_LENGTH = len(" [100%]")
424-
425429
def _get_progress_information_message(self):
426430
if self.config.getoption("capture") == "no":
427431
return ""
428432
collected = self._session.testscollected
429-
if collected:
430-
progress = len(self._progress_nodeids_reported) * 100 // collected
431-
return " [{:3d}%]".format(progress)
432-
return " [100%]"
433+
if self.config.getini("console_output_style") == "count":
434+
if collected:
435+
progress = self._progress_nodeids_reported
436+
counter_format = "{{:{}d}}".format(len(str(collected)))
437+
format_string = " [{}/{{}}]".format(counter_format)
438+
return format_string.format(len(progress), collected)
439+
return " [ {} / {} ]".format(collected, collected)
440+
else:
441+
if collected:
442+
progress = len(self._progress_nodeids_reported) * 100 // collected
443+
return " [{:3d}%]".format(progress)
444+
return " [100%]"
433445

434446
def _write_progress_information_filling_space(self):
435447
msg = self._get_progress_information_message()

testing/test_terminal.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,22 @@ def test_normal(self, many_tests_files, testdir):
11831183
]
11841184
)
11851185

1186+
def test_count(self, many_tests_files, testdir):
1187+
testdir.makeini(
1188+
"""
1189+
[pytest]
1190+
console_output_style = count
1191+
"""
1192+
)
1193+
output = testdir.runpytest()
1194+
output.stdout.re_match_lines(
1195+
[
1196+
r"test_bar.py \.{10} \s+ \[10/20\]",
1197+
r"test_foo.py \.{5} \s+ \[15/20\]",
1198+
r"test_foobar.py \.{5} \s+ \[20/20\]",
1199+
]
1200+
)
1201+
11861202
def test_verbose(self, many_tests_files, testdir):
11871203
output = testdir.runpytest("-v")
11881204
output.stdout.re_match_lines(
@@ -1193,11 +1209,38 @@ def test_verbose(self, many_tests_files, testdir):
11931209
]
11941210
)
11951211

1212+
def test_verbose_count(self, many_tests_files, testdir):
1213+
testdir.makeini(
1214+
"""
1215+
[pytest]
1216+
console_output_style = count
1217+
"""
1218+
)
1219+
output = testdir.runpytest("-v")
1220+
output.stdout.re_match_lines(
1221+
[
1222+
r"test_bar.py::test_bar\[0\] PASSED \s+ \[ 1/20\]",
1223+
r"test_foo.py::test_foo\[4\] PASSED \s+ \[15/20\]",
1224+
r"test_foobar.py::test_foobar\[4\] PASSED \s+ \[20/20\]",
1225+
]
1226+
)
1227+
11961228
def test_xdist_normal(self, many_tests_files, testdir):
11971229
pytest.importorskip("xdist")
11981230
output = testdir.runpytest("-n2")
11991231
output.stdout.re_match_lines([r"\.{20} \s+ \[100%\]"])
12001232

1233+
def test_xdist_normal_count(self, many_tests_files, testdir):
1234+
pytest.importorskip("xdist")
1235+
testdir.makeini(
1236+
"""
1237+
[pytest]
1238+
console_output_style = count
1239+
"""
1240+
)
1241+
output = testdir.runpytest("-n2")
1242+
output.stdout.re_match_lines([r"\.{20} \s+ \[20/20\]"])
1243+
12011244
def test_xdist_verbose(self, many_tests_files, testdir):
12021245
pytest.importorskip("xdist")
12031246
output = testdir.runpytest("-n2", "-v")

0 commit comments

Comments
 (0)