From 3ad58ae21f0064692a30f185aada96af5e6e91a5 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 27 Sep 2010 16:13:56 +0200 Subject: [PATCH] fix distributed testing reporting details --- testing/acceptance_test.py | 27 ++++++--------- xdist/dsession.py | 70 +++++++++++++++++--------------------- xdist/gwmanage.py | 3 +- xdist/remote.py | 15 ++++++-- 4 files changed, 57 insertions(+), 58 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 578cb58..4ff3e33 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -51,8 +51,7 @@ class TestDistribution: ) result = testdir.runpytest(p1, "-v", '-d', '--tx=popen', '--tx=popen') result.stdout.fnmatch_lines([ - "*0*popen*Python*", - "*1*popen*Python*", + "*1*Python*", "*2 failed, 1 passed, 1 skipped*", ]) assert result.ret == 1 @@ -89,9 +88,7 @@ class TestDistribution: """) result = testdir.runpytest(p1, '-d', "-v") result.stdout.fnmatch_lines([ - "*0*popen*Python*", - "*1*popen*Python*", - "*2*popen*Python*", + "*2*Python*", "*2 failed, 1 passed, 1 skipped*", ]) assert result.ret == 1 @@ -120,8 +117,8 @@ class TestDistribution: ) result = testdir.runpytest(p1, "-v", '-d', '-n1') result.stdout.fnmatch_lines([ - "*popen*Python*", - "*test_ok*PASS*", + "*Python*", + "*PASS**test_ok*", "*node*down*", "*3 failed, 1 passed, 1 skipped*" ]) @@ -139,7 +136,7 @@ class TestDistribution: "--tx=popen//chdir=%(dest)s" % locals(), p) assert result.ret == 0 result.stdout.fnmatch_lines([ - "*0* *popen*platform*", + "*0* *cwd*", #"RSyncStart: [G1]", #"RSyncFinished: [G1]", "*1 passed*" @@ -196,7 +193,7 @@ class TestDistribution: p1 = testdir.makepyfile("def test_func(): pass") result = testdir.runpytest("-v", p1, '-d', '--tx=popen') result.stdout.fnmatch_lines([ - "*popen*Python*", + "*0*Python*", "*calculated result is 49*", "*1 passed*" ]) @@ -251,15 +248,13 @@ class TestTerminalReporting: assert 0 """) result = testdir.runpytest("-n1", "-v") - expected = [ + result.stdout.fnmatch_lines_random([ "*PASS*test_pass_skip_fail.py:2: *test_ok*", "*SKIP*test_pass_skip_fail.py:4: *test_skip*", "*FAIL*test_pass_skip_fail.py:6: *test_func*", - ] - for line in expected: - result.stdout.fnmatch_lines([line]) + ]) result.stdout.fnmatch_lines([ - " def test_func():", + "*def test_func():", "> assert 0", "E assert 0", ]) @@ -272,8 +267,8 @@ class TestTerminalReporting: result = testdir.runpytest("-n1", "-v") result.stdout.fnmatch_lines([ "*FAIL*test_fail_platinfo.py:1: *test_func*", - "*popen*Python*", - " def test_func():", + "*0*Python*", + "*def test_func():", "> assert 0", "E assert 0", ]) diff --git a/xdist/dsession.py b/xdist/dsession.py index 4d11c40..4056ee1 100644 --- a/xdist/dsession.py +++ b/xdist/dsession.py @@ -156,7 +156,11 @@ class DSession: exitstatus=exitstatus,) return exitstatus - def slave_slaveready(self, node): + def slave_slaveready(self, node, slaveinfo): + node.slaveinfo = slaveinfo + node.slaveinfo['id'] = node.gateway.id + node.slaveinfo['spec'] = node.gateway.spec + self.config.hook.pytest_testnodeready(node=node) self.sched.addnode(node) if self.shuttingdown: node.shutdown() @@ -173,7 +177,7 @@ class DSession: self.session_finished = True def slave_errordown(self, node, error): - self.report_line("node %r down on error: %s" %(node.gateway.id, error,)) + self.config.hook.pytest_testnodedown(node=node, error=error) crashitem = self.sched.remove_node(node) if crashitem: self.handle_crashitem(crashitem, node) @@ -197,11 +201,13 @@ class DSession: def slave_testreport(self, node, rep): self.sched.remove_item(node, rep.nodeid) #self.report_line("testreport %s: %s" %(rep.id, rep.status)) + enrich_report_with_platform_data(rep, node) self.config.hook.pytest_runtest_logreport(report=rep) self._handlefailures(rep) def slave_collectreport(self, node, rep): #self.report_line("collectreport %s: %s" %(rep.id, rep.status)) + #rep.node = node self._handlefailures(rep) def _handlefailures(self, rep): @@ -263,6 +269,7 @@ class DSession: msg = "Slave %r crashed while running %r" %(slave.gateway.id, nodeid) rep = runner.TestReport(nodeid, (), fspath, (fspath, None, fspath), (), "failed", msg, "???") + enrich_report_with_platform_data(rep, slave) self.config.hook.pytest_runtest_logreport(report=rep) def setup(self): @@ -279,52 +286,39 @@ class DSession: class TerminalDistReporter: def __init__(self, config): - self.gateway2info = {} self.config = config - self.tplugin = config.pluginmanager.getplugin("terminal") self.tr = config.pluginmanager.getplugin("terminalreporter") def write_line(self, msg): self.tr.write_line(msg) - def pytest_itemstart(self, __multicall__): - try: - __multicall__.methods.remove(self.tr.pytest_itemstart) - except KeyError: - pass - - def pytest_runtest_logreport(self, report): - if hasattr(report, 'node'): - report.headerlines.append(self.gateway2info.get( - report.node.gateway, - "node %r (platinfo not found? strange)")) - - def pytest_gwmanage_newgateway(self, gateway, platinfo): - #self.write_line("%s instantiated gateway from spec %r" %(gateway.id, gateway.spec._spec)) - d = {} - d['version'] = self.tplugin.repr_pythonversion(platinfo.version_info) - d['id'] = gateway.id - d['spec'] = gateway.spec._spec - d['platform'] = platinfo.platform - if self.config.option.verbose: - d['extra'] = "- " + platinfo.executable - else: - d['extra'] = "" - d['cwd'] = platinfo.cwd - infoline = ("[%(id)s] %(spec)s -- platform %(platform)s, " - "Python %(version)s " - "cwd: %(cwd)s" - "%(extra)s" % d) + def pytest_gwmanage_newgateway(self, gateway): + rinfo = gateway._rinfo() if self.config.getvalue("verbose"): - self.write_line(infoline) - self.gateway2info[gateway] = infoline + version = "%s.%s.%s" %rinfo.version_info[:3] + self.write_line("[%s] %s Python %s cwd: %s" % ( + gateway.id, rinfo.platform, version, rinfo.cwd)) def pytest_testnodeready(self, node): - if self.config.getvalue("verbose"): - self.write_line( - "[%s] txnode ready to receive tests" %(node.gateway.id,)) + if self.config.getvalue("debug"): + d = node.slaveinfo + infoline = "[%s] -- Python %s" %( + d['id'], + d['version'].replace('\n', ' -- '),) + self.write_line(infoline) def pytest_testnodedown(self, node, error): if not error: return - self.write_line("[%s] node down, error: %s" %(node.gateway.id, error)) + self.write_line("[%s] node down: %s" %(node.gateway.id, error)) + +def enrich_report_with_platform_data(rep, node): + rep.node = node + if hasattr(rep, 'node') and rep.longrepr: + d = node.slaveinfo + ver = "%s.%s.%s" % d['version_info'][:3] + infoline = "[%s] %s -- Python %s %s" % ( + d['id'], d['sysplatform'], ver, d['executable']) + # XXX more structured longrepr? + rep.longrepr = infoline + "\n\n" + str(rep.longrepr) + diff --git a/xdist/gwmanage.py b/xdist/gwmanage.py index fdc5480..780ace9 100644 --- a/xdist/gwmanage.py +++ b/xdist/gwmanage.py @@ -25,8 +25,7 @@ class GatewayManager: assert not list(self.group) for spec in self.specs: gw = self.group.makegateway(spec) - self.hook.pytest_gwmanage_newgateway( - gateway=gw, platinfo=gw._rinfo()) + self.hook.pytest_gwmanage_newgateway(gateway=gw) def rsync(self, source, notify=None, verbose=False, ignores=None): """ perform rsync to all remote hosts. diff --git a/xdist/remote.py b/xdist/remote.py index 92b557f..ff85084 100644 --- a/xdist/remote.py +++ b/xdist/remote.py @@ -103,7 +103,7 @@ class SlaveController(object): if eventname in ("collectionstart"): self.log("ignoring %s(%s)" %(eventname, kwargs)) elif eventname == "slaveready": - self.notify_inproc(eventname, node=self) + self.notify_inproc(eventname, node=self, **kwargs) elif eventname == "slavefinished": self._down = True self.slaveoutput = kwargs['slaveoutput'] @@ -166,7 +166,8 @@ class SlaveInteractor: def pytest_sessionstart(self, session): self.session = session self.collection = session.collection - self.sendevent("slaveready") + slaveinfo = getinfodict() + self.sendevent("slaveready", slaveinfo=slaveinfo) def pytest_sessionfinish(self, __multicall__, exitstatus): self.config.slaveoutput['exitstatus'] = exitstatus @@ -225,3 +226,13 @@ def unserialize_report(reportdict): else: return runner.TestReport(**d) +def getinfodict(): + import os, sys, platform + return dict( + version = sys.version, + version_info = tuple(sys.version_info), + sysplatform = sys.platform, + platform = platform.platform(), + executable = sys.executable, + cwd = os.getcwd(), + )