From d53572a710e4e6947d7b316e6536d5d5ddea1ac8 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 12 Jan 2010 21:43:25 +0100 Subject: [PATCH] introduce a new pytest_report_header(hook) hook to add additional test-run relevant information to the header of a test report. --HG-- branch : trunk --- CHANGELOG | 3 +++ ISSUES.txt | 8 ------ py/plugin/hookspec.py | 3 +++ py/plugin/pytest_helpconfig.py | 23 +++++++++++++++++ py/plugin/pytest_terminal.py | 35 ++++++++------------------ testing/plugin/test_pytest_terminal.py | 16 ++++++++++++ 6 files changed, 56 insertions(+), 32 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 224c6a215..da4173f03 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -21,6 +21,9 @@ Changes between 1.X and 1.1.1 - new "pytestconfig" funcarg allows access to test config object +- new "pytest_report_header" hook can return additional lines + to be displayed at the header of a test run. + - (experimental) allow "py.test path::name1::name2::..." for pointing to a test within a test collection directly. This might eventually evolve as a full substitute to "-k" specifications. diff --git a/ISSUES.txt b/ISSUES.txt index c0ee45d7c..b1db4ead0 100644 --- a/ISSUES.txt +++ b/ISSUES.txt @@ -16,14 +16,6 @@ With 1.1.1 py.test fails at least on windows if an import is relative and compared against an absolute conftest.py path. Normalize. -allow plugins/conftests to show extra header information --------------------------------------------------------- -tags: feature 1.2 - -The test-report header should optionally show information -about the under-test package and versions/locations of -involved packages. - make node._checkcollectable more robust ------------------------------------------------- tags: bug 1.2 diff --git a/py/plugin/hookspec.py b/py/plugin/hookspec.py index 73a4e4126..426412708 100644 --- a/py/plugin/hookspec.py +++ b/py/plugin/hookspec.py @@ -109,6 +109,9 @@ def pytest_sessionfinish(session, exitstatus): # hooks for influencing reporting (invoked from pytest_terminal) # ------------------------------------------------------------------------- +def pytest_report_header(config): + """ return a string to be displayed as header info for terminal reporting.""" + def pytest_report_teststatus(report): """ return result-category, shortletter and verbose word for reporting.""" pytest_report_teststatus.firstresult = True diff --git a/py/plugin/pytest_helpconfig.py b/py/plugin/pytest_helpconfig.py index 9d0860ab3..0bdd9775b 100644 --- a/py/plugin/pytest_helpconfig.py +++ b/py/plugin/pytest_helpconfig.py @@ -10,9 +10,19 @@ def pytest_addoption(parser): group._addoption('-p', action="append", dest="plugins", default = [], metavar="name", help="early-load given plugin (multi-allowed).") + group.addoption('--traceconfig', + action="store_true", dest="traceconfig", default=False, + help="trace considerations of conftest.py files."), + group._addoption('--nomagic', + action="store_true", dest="nomagic", default=False, + help="don't reinterpret asserts, no traceback cutting. ") + group.addoption('--debug', + action="store_true", dest="debug", default=False, + help="generate and show internal debugging information.") group.addoption("--help-config", action="store_true", dest="helpconfig", help="show available conftest.py and ENV-variable names.") + def pytest_configure(__multicall__, config): if config.option.version: p = py.path.local(py.__file__).dirpath() @@ -65,6 +75,19 @@ conftest_options = ( ('rsyncdirs', 'to-be-rsynced directories for dist-testing'), ) +def pytest_report_header(config): + lines = [] + if config.option.debug or config.option.traceconfig: + lines.append("using py lib: %s" % (py.path.local(py.__file__).dirpath())) + if config.option.traceconfig: + lines.append("active plugins:") + plugins = [] + items = config.pluginmanager._name2plugin.items() + for name, plugin in items: + lines.append(" %-20s: %s" %(name, repr(plugin))) + return lines + + # ===================================================== # validate plugin syntax and hooks # ===================================================== diff --git a/py/plugin/pytest_terminal.py b/py/plugin/pytest_terminal.py index 237849993..1c7acbaf6 100644 --- a/py/plugin/pytest_terminal.py +++ b/py/plugin/pytest_terminal.py @@ -24,17 +24,6 @@ def pytest_addoption(parser): action="store_true", dest="fulltrace", default=False, help="don't cut any tracebacks (default is to cut).") - group = parser.getgroup("debugconfig") - group.addoption('--traceconfig', - action="store_true", dest="traceconfig", default=False, - help="trace considerations of conftest.py files."), - group._addoption('--nomagic', - action="store_true", dest="nomagic", default=False, - help="don't reinterpret asserts, no traceback cutting. ") - group.addoption('--debug', - action="store_true", dest="debug", default=False, - help="generate and show internal debugging information.") - def pytest_configure(config): if config.option.collectonly: @@ -260,19 +249,10 @@ class TerminalReporter: if self.config.option.verbose or self.config.option.debug or getattr(self.config.option, 'pastebin', None): msg += " -- " + str(sys.executable) self.write_line(msg) - - if self.config.option.debug or self.config.option.traceconfig: - self.write_line("using py lib: %s" % (py.path.local(py.__file__).dirpath())) - if self.config.option.traceconfig: - self.write_line("active plugins:") - plugins = [] - items = self.config.pluginmanager._name2plugin.items() - for name, plugin in items: - repr_plugin = repr(plugin) - fullwidth = getattr(self._tw, 'fullwidth', 65000) - if len(repr_plugin)+26 > fullwidth: - repr_plugin = repr_plugin[:(fullwidth-30)] + '...' - self.write_line(" %-20s: %s" %(name, repr_plugin)) + lines = self.config.hook.pytest_report_header(config=self.config) + lines.reverse() + for line in flatten(lines): + self.write_line(line) for i, testarg in enumerate(self.config.args): self.write_line("test object %d: %s" %(i+1, testarg)) @@ -463,3 +443,10 @@ def repr_pythonversion(v=None): except (TypeError, ValueError): return str(v) +def flatten(l): + for x in l: + if isinstance(x, (list, tuple)): + for y in flatten(x): + yield y + else: + yield x diff --git a/testing/plugin/test_pytest_terminal.py b/testing/plugin/test_pytest_terminal.py index da58c5310..6ffebbd6b 100644 --- a/testing/plugin/test_pytest_terminal.py +++ b/testing/plugin/test_pytest_terminal.py @@ -289,6 +289,22 @@ class TestTerminal: ]) result.stdout.fnmatch_lines(['*KEYBOARD INTERRUPT*']) + def test_pytest_report_header(self, testdir): + testdir.makeconftest(""" + def pytest_report_header(config): + return "hello: info" + """) + testdir.mkdir("a").join("conftest.py").write("""if 1: + def pytest_report_header(config): + return ["line1", "line2"] + """) + result = testdir.runpytest("a") + result.stdout.fnmatch_lines([ + "*hello: info*", + "line1", + "line2", + ]) + class TestCollectonly: def test_collectonly_basic(self, testdir, linecomp):