fix distributed testing reporting details

This commit is contained in:
holger krekel
2010-09-27 16:13:56 +02:00
parent 749faf5e7c
commit 3ad58ae21f
4 changed files with 57 additions and 58 deletions

View File

@@ -51,8 +51,7 @@ class TestDistribution:
) )
result = testdir.runpytest(p1, "-v", '-d', '--tx=popen', '--tx=popen') result = testdir.runpytest(p1, "-v", '-d', '--tx=popen', '--tx=popen')
result.stdout.fnmatch_lines([ result.stdout.fnmatch_lines([
"*0*popen*Python*", "*1*Python*",
"*1*popen*Python*",
"*2 failed, 1 passed, 1 skipped*", "*2 failed, 1 passed, 1 skipped*",
]) ])
assert result.ret == 1 assert result.ret == 1
@@ -89,9 +88,7 @@ class TestDistribution:
""") """)
result = testdir.runpytest(p1, '-d', "-v") result = testdir.runpytest(p1, '-d', "-v")
result.stdout.fnmatch_lines([ result.stdout.fnmatch_lines([
"*0*popen*Python*", "*2*Python*",
"*1*popen*Python*",
"*2*popen*Python*",
"*2 failed, 1 passed, 1 skipped*", "*2 failed, 1 passed, 1 skipped*",
]) ])
assert result.ret == 1 assert result.ret == 1
@@ -120,8 +117,8 @@ class TestDistribution:
) )
result = testdir.runpytest(p1, "-v", '-d', '-n1') result = testdir.runpytest(p1, "-v", '-d', '-n1')
result.stdout.fnmatch_lines([ result.stdout.fnmatch_lines([
"*popen*Python*", "*Python*",
"*test_ok*PASS*", "*PASS**test_ok*",
"*node*down*", "*node*down*",
"*3 failed, 1 passed, 1 skipped*" "*3 failed, 1 passed, 1 skipped*"
]) ])
@@ -139,7 +136,7 @@ class TestDistribution:
"--tx=popen//chdir=%(dest)s" % locals(), p) "--tx=popen//chdir=%(dest)s" % locals(), p)
assert result.ret == 0 assert result.ret == 0
result.stdout.fnmatch_lines([ result.stdout.fnmatch_lines([
"*0* *popen*platform*", "*0* *cwd*",
#"RSyncStart: [G1]", #"RSyncStart: [G1]",
#"RSyncFinished: [G1]", #"RSyncFinished: [G1]",
"*1 passed*" "*1 passed*"
@@ -196,7 +193,7 @@ class TestDistribution:
p1 = testdir.makepyfile("def test_func(): pass") p1 = testdir.makepyfile("def test_func(): pass")
result = testdir.runpytest("-v", p1, '-d', '--tx=popen') result = testdir.runpytest("-v", p1, '-d', '--tx=popen')
result.stdout.fnmatch_lines([ result.stdout.fnmatch_lines([
"*popen*Python*", "*0*Python*",
"*calculated result is 49*", "*calculated result is 49*",
"*1 passed*" "*1 passed*"
]) ])
@@ -251,15 +248,13 @@ class TestTerminalReporting:
assert 0 assert 0
""") """)
result = testdir.runpytest("-n1", "-v") result = testdir.runpytest("-n1", "-v")
expected = [ result.stdout.fnmatch_lines_random([
"*PASS*test_pass_skip_fail.py:2: *test_ok*", "*PASS*test_pass_skip_fail.py:2: *test_ok*",
"*SKIP*test_pass_skip_fail.py:4: *test_skip*", "*SKIP*test_pass_skip_fail.py:4: *test_skip*",
"*FAIL*test_pass_skip_fail.py:6: *test_func*", "*FAIL*test_pass_skip_fail.py:6: *test_func*",
] ])
for line in expected:
result.stdout.fnmatch_lines([line])
result.stdout.fnmatch_lines([ result.stdout.fnmatch_lines([
" def test_func():", "*def test_func():",
"> assert 0", "> assert 0",
"E assert 0", "E assert 0",
]) ])
@@ -272,8 +267,8 @@ class TestTerminalReporting:
result = testdir.runpytest("-n1", "-v") result = testdir.runpytest("-n1", "-v")
result.stdout.fnmatch_lines([ result.stdout.fnmatch_lines([
"*FAIL*test_fail_platinfo.py:1: *test_func*", "*FAIL*test_fail_platinfo.py:1: *test_func*",
"*popen*Python*", "*0*Python*",
" def test_func():", "*def test_func():",
"> assert 0", "> assert 0",
"E assert 0", "E assert 0",
]) ])

View File

@@ -156,7 +156,11 @@ class DSession:
exitstatus=exitstatus,) exitstatus=exitstatus,)
return 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) self.sched.addnode(node)
if self.shuttingdown: if self.shuttingdown:
node.shutdown() node.shutdown()
@@ -173,7 +177,7 @@ class DSession:
self.session_finished = True self.session_finished = True
def slave_errordown(self, node, error): 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) crashitem = self.sched.remove_node(node)
if crashitem: if crashitem:
self.handle_crashitem(crashitem, node) self.handle_crashitem(crashitem, node)
@@ -197,11 +201,13 @@ class DSession:
def slave_testreport(self, node, rep): def slave_testreport(self, node, rep):
self.sched.remove_item(node, rep.nodeid) self.sched.remove_item(node, rep.nodeid)
#self.report_line("testreport %s: %s" %(rep.id, rep.status)) #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.config.hook.pytest_runtest_logreport(report=rep)
self._handlefailures(rep) self._handlefailures(rep)
def slave_collectreport(self, node, rep): def slave_collectreport(self, node, rep):
#self.report_line("collectreport %s: %s" %(rep.id, rep.status)) #self.report_line("collectreport %s: %s" %(rep.id, rep.status))
#rep.node = node
self._handlefailures(rep) self._handlefailures(rep)
def _handlefailures(self, rep): def _handlefailures(self, rep):
@@ -263,6 +269,7 @@ class DSession:
msg = "Slave %r crashed while running %r" %(slave.gateway.id, nodeid) msg = "Slave %r crashed while running %r" %(slave.gateway.id, nodeid)
rep = runner.TestReport(nodeid, (), fspath, (fspath, None, fspath), (), rep = runner.TestReport(nodeid, (), fspath, (fspath, None, fspath), (),
"failed", msg, "???") "failed", msg, "???")
enrich_report_with_platform_data(rep, slave)
self.config.hook.pytest_runtest_logreport(report=rep) self.config.hook.pytest_runtest_logreport(report=rep)
def setup(self): def setup(self):
@@ -279,52 +286,39 @@ class DSession:
class TerminalDistReporter: class TerminalDistReporter:
def __init__(self, config): def __init__(self, config):
self.gateway2info = {}
self.config = config self.config = config
self.tplugin = config.pluginmanager.getplugin("terminal")
self.tr = config.pluginmanager.getplugin("terminalreporter") self.tr = config.pluginmanager.getplugin("terminalreporter")
def write_line(self, msg): def write_line(self, msg):
self.tr.write_line(msg) self.tr.write_line(msg)
def pytest_itemstart(self, __multicall__): def pytest_gwmanage_newgateway(self, gateway):
try: rinfo = gateway._rinfo()
__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)
if self.config.getvalue("verbose"): if self.config.getvalue("verbose"):
self.write_line(infoline) version = "%s.%s.%s" %rinfo.version_info[:3]
self.gateway2info[gateway] = infoline self.write_line("[%s] %s Python %s cwd: %s" % (
gateway.id, rinfo.platform, version, rinfo.cwd))
def pytest_testnodeready(self, node): def pytest_testnodeready(self, node):
if self.config.getvalue("verbose"): if self.config.getvalue("debug"):
self.write_line( d = node.slaveinfo
"[%s] txnode ready to receive tests" %(node.gateway.id,)) infoline = "[%s] -- Python %s" %(
d['id'],
d['version'].replace('\n', ' -- '),)
self.write_line(infoline)
def pytest_testnodedown(self, node, error): def pytest_testnodedown(self, node, error):
if not error: if not error:
return 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)

View File

@@ -25,8 +25,7 @@ class GatewayManager:
assert not list(self.group) assert not list(self.group)
for spec in self.specs: for spec in self.specs:
gw = self.group.makegateway(spec) gw = self.group.makegateway(spec)
self.hook.pytest_gwmanage_newgateway( self.hook.pytest_gwmanage_newgateway(gateway=gw)
gateway=gw, platinfo=gw._rinfo())
def rsync(self, source, notify=None, verbose=False, ignores=None): def rsync(self, source, notify=None, verbose=False, ignores=None):
""" perform rsync to all remote hosts. """ perform rsync to all remote hosts.

View File

@@ -103,7 +103,7 @@ class SlaveController(object):
if eventname in ("collectionstart"): if eventname in ("collectionstart"):
self.log("ignoring %s(%s)" %(eventname, kwargs)) self.log("ignoring %s(%s)" %(eventname, kwargs))
elif eventname == "slaveready": elif eventname == "slaveready":
self.notify_inproc(eventname, node=self) self.notify_inproc(eventname, node=self, **kwargs)
elif eventname == "slavefinished": elif eventname == "slavefinished":
self._down = True self._down = True
self.slaveoutput = kwargs['slaveoutput'] self.slaveoutput = kwargs['slaveoutput']
@@ -166,7 +166,8 @@ class SlaveInteractor:
def pytest_sessionstart(self, session): def pytest_sessionstart(self, session):
self.session = session self.session = session
self.collection = session.collection self.collection = session.collection
self.sendevent("slaveready") slaveinfo = getinfodict()
self.sendevent("slaveready", slaveinfo=slaveinfo)
def pytest_sessionfinish(self, __multicall__, exitstatus): def pytest_sessionfinish(self, __multicall__, exitstatus):
self.config.slaveoutput['exitstatus'] = exitstatus self.config.slaveoutput['exitstatus'] = exitstatus
@@ -225,3 +226,13 @@ def unserialize_report(reportdict):
else: else:
return runner.TestReport(**d) 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(),
)