Skip to content

Instantly share code, notes, and snippets.

@mgedmin

mgedmin/conftest.py

Created Sep 9, 2020
Embed
What would you like to do?
How to get a pytest progress bar in xterm title
# Put this in your top-level conftest.py
class XTermProgress:
def __init__(self, stdout=sys.stdout):
self.init(stdout)
self.session = None
self.reported = set()
self.args = []
def init(self, stdout):
self.stdout = stdout
self.enabled = os.environ.get('TERM', '').startswith('xterm') and stdout.isatty()
def ready(self, session):
self.session = session
def set_args(self, args):
self.args = list(args)
@property
def finished_tests(self):
return len(self.reported)
@property
def total_tests(self):
return self.session.testscollected
@property
def progress(self):
if self.total_tests == 0:
return '0%'
else:
return f'{100 * self.finished_tests / self.total_tests:.1f}%'
def logreport(self, report):
if self.enabled:
self.reported.add(report.nodeid)
message = f"{self.progress} - {' '.join(['pytest'] + self.args)}"
self.stdout.write(f"\033]0;{message}\a")
self.stdout.flush()
TERMINAL_PROGRESS = XTermProgress()
@pytest.mark.trylast
def pytest_configure(config):
standard_reporter = config.pluginmanager.getplugin('terminalreporter')
if hasattr(getattr(standard_reporter, '_tw', None), '_file'):
# XXX: I was unable to find a blessed way of getting the real stdout
# stream from pytest APIs, and I can't use standard_reporter.write() because
# it sprinkles extraneous newlines everywhere!
TERMINAL_PROGRESS.init(standard_reporter._tw._file)
if hasattr(config, 'invocation_params'): # pytest 5.1 required
TERMINAL_PROGRESS.set_args(config.invocation_params.args)
def pytest_collection(session):
TERMINAL_PROGRESS.ready(session)
def pytest_runtest_logreport(report):
TERMINAL_PROGRESS.logreport(report)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment