-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Console progress output #2858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Console progress output #2858
Changes from all commits
7a7cb8c
dab8893
8b92527
3441084
3a5dbab
2455f86
f05333a
1d26f37
dc574c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,6 +51,10 @@ def pytest_addoption(parser): | |
choices=['yes', 'no', 'auto'], | ||
help="color terminal output (yes/no/auto).") | ||
|
||
parser.addini("console_output_style", | ||
help="console output: classic or with additional progress information (classic|progress).", | ||
default='progress') | ||
|
||
|
||
def pytest_configure(config): | ||
config.option.verbose -= config.option.quiet | ||
|
@@ -135,16 +139,20 @@ def __init__(self, config, file=None): | |
self.showfspath = self.verbosity >= 0 | ||
self.showlongtestinfo = self.verbosity > 0 | ||
self._numcollected = 0 | ||
self._session = None | ||
|
||
self.stats = {} | ||
self.startdir = py.path.local() | ||
if file is None: | ||
file = sys.stdout | ||
self._writer = _pytest.config.create_terminal_writer(config, file) | ||
self._screen_width = self.writer.fullwidth | ||
self.currentfspath = None | ||
self.reportchars = getreportopt(config) | ||
self.hasmarkup = self.writer.hasmarkup | ||
self.isatty = file.isatty() | ||
self._progress_items_reported = 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we really have no way already to get how many tests have run so far? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not that I know of; usually this is not really tracked by pytest explicitly, each |
||
self._show_progress_info = self.config.getini('console_output_style') == 'progress' | ||
|
||
@property | ||
def writer(self): | ||
|
@@ -163,6 +171,8 @@ def hasopt(self, char): | |
def write_fspath_result(self, nodeid, res): | ||
fspath = self.config.rootdir.join(nodeid.split("::")[0]) | ||
if fspath != self.currentfspath: | ||
if self.currentfspath is not None: | ||
self._write_progress_information_filling_space() | ||
self.currentfspath = fspath | ||
fspath = self.startdir.bestrelpath(fspath) | ||
self.writer.line() | ||
|
@@ -177,6 +187,7 @@ def write_ensure_prefix(self, prefix, extra="", **kwargs): | |
if extra: | ||
self.writer.write(extra, **kwargs) | ||
self.currentfspath = -2 | ||
self._write_progress_information_filling_space() | ||
|
||
def ensure_newline(self): | ||
if self.currentfspath: | ||
|
@@ -203,7 +214,7 @@ def rewrite(self, line, **markup): | |
""" | ||
erase = markup.pop('erase', False) | ||
if erase: | ||
fill_count = self.writer.fullwidth - len(line) | ||
fill_count = self.writer.fullwidth - len(line) - 1 | ||
fill = ' ' * fill_count | ||
else: | ||
fill = '' | ||
|
@@ -256,20 +267,25 @@ def pytest_runtest_logreport(self, report): | |
rep = report | ||
res = self.config.hook.pytest_report_teststatus(report=rep) | ||
cat, letter, word = res | ||
if isinstance(word, tuple): | ||
word, markup = word | ||
else: | ||
markup = None | ||
self.stats.setdefault(cat, []).append(rep) | ||
self._tests_ran = True | ||
if not letter and not word: | ||
# probably passed setup/teardown | ||
return | ||
running_xdist = hasattr(rep, 'node') | ||
self._progress_items_reported += 1 | ||
if self.verbosity <= 0: | ||
if not hasattr(rep, 'node') and self.showfspath: | ||
if not running_xdist and self.showfspath: | ||
self.write_fspath_result(rep.nodeid, letter) | ||
else: | ||
self.writer.write(letter) | ||
self._write_progress_if_past_edge() | ||
else: | ||
if isinstance(word, tuple): | ||
word, markup = word | ||
else: | ||
if markup is None: | ||
if rep.passed: | ||
markup = {'green': True} | ||
elif rep.failed: | ||
|
@@ -279,17 +295,45 @@ def pytest_runtest_logreport(self, report): | |
else: | ||
markup = {} | ||
line = self._locationline(rep.nodeid, *rep.location) | ||
if not hasattr(rep, 'node'): | ||
if not running_xdist: | ||
self.write_ensure_prefix(line, word, **markup) | ||
# self.writer.write(word, **markup) | ||
else: | ||
self.ensure_newline() | ||
if hasattr(rep, 'node'): | ||
self.writer.write("[%s] " % rep.node.gateway.id) | ||
self.writer.write("[%s]" % rep.node.gateway.id) | ||
if self._show_progress_info: | ||
self.writer.write(self._get_progress_information_message() + " ", cyan=True) | ||
else: | ||
self.writer.write(' ') | ||
self.writer.write(word, **markup) | ||
self.writer.write(" " + line) | ||
self.currentfspath = -2 | ||
|
||
def _write_progress_if_past_edge(self): | ||
if not self._show_progress_info: | ||
return | ||
last_item = self._progress_items_reported == self._session.testscollected | ||
if last_item: | ||
self._write_progress_information_filling_space() | ||
return | ||
|
||
past_edge = self.writer.chars_on_current_line + self._PROGRESS_LENGTH + 1 >= self._screen_width | ||
if past_edge: | ||
msg = self._get_progress_information_message() | ||
self.writer.write(msg + '\n', cyan=True) | ||
|
||
_PROGRESS_LENGTH = len(' [100%]') | ||
|
||
def _get_progress_information_message(self): | ||
progress = self._progress_items_reported * 100 // self._session.testscollected | ||
return ' [{:3d}%]'.format(progress) | ||
|
||
def _write_progress_information_filling_space(self): | ||
if not self._show_progress_info: | ||
return | ||
msg = self._get_progress_information_message() | ||
fill = ' ' * (self.writer.fullwidth - self.writer.chars_on_current_line - len(msg) - 1) | ||
self.write(fill + msg, cyan=True) | ||
|
||
def pytest_collection(self): | ||
if not self.isatty and self.config.option.verbose >= 1: | ||
self.write("collecting ... ", bold=True) | ||
|
@@ -332,6 +376,7 @@ def pytest_collection_modifyitems(self): | |
|
||
@pytest.hookimpl(trylast=True) | ||
def pytest_sessionstart(self, session): | ||
self._session = session | ||
self._sessionstarttime = time.time() | ||
if not self.showheader: | ||
return | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Now pytest displays the total progress percentage while running tests. The previous output style can be set by setting the new ``console_output_style`` to ``classic``. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to cache this otherwise I noticed a good 20% performance penalty. We probably need to fix this in
py
somehow, which we have tried to do in the past.