adapt to pytest changes, add looponfailingdirs ini-option

This commit is contained in:
holger krekel
2010-11-06 09:58:00 +01:00
parent 985c9163b7
commit 9d55d3c831
9 changed files with 48 additions and 37 deletions

View File

@@ -1,2 +1,2 @@
#
__version__ = '1.5a4'
__version__ = '1.5a5'

View File

@@ -301,7 +301,7 @@ class DSession:
runner = self.config.pluginmanager.getplugin("runner")
fspath = nodeid.split("::")[0]
msg = "Slave %r crashed while running %r" %(slave.gateway.id, nodeid)
rep = runner.TestReport(nodeid, (), fspath, (fspath, None, fspath), (),
rep = runner.TestReport(nodeid, (fspath, None, fspath), (),
"failed", msg, "???")
enrich_report_with_platform_data(rep, slave)
self.config.hook.pytest_runtest_logreport(report=rep)
@@ -350,6 +350,6 @@ def enrich_report_with_platform_data(rep, node):
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?
# XXX more structured longrepr?
rep.longrepr = infoline + "\n\n" + str(rep.longrepr)

View File

@@ -7,21 +7,22 @@
the controlling process which should best never happen.
"""
import py
import py, pytest
import sys
import execnet
def looponfail_main(config):
remotecontrol = RemoteControl(config)
# XXX better configure rootdir
gettopdir = config.pluginmanager.getplugin("session").gettopdir
rootdirs = [gettopdir(config.args)]
rootdirs = config.getini("looponfailroots")
statrecorder = StatRecorder(rootdirs)
try:
while 1:
remotecontrol.loop_once()
if not remotecontrol.failures and remotecontrol.wasfailing:
continue # the last failures passed, let's immediately rerun all
repr_pytest_looponfailinfo(
failreports=remotecontrol.failures,
rootdirs=rootdirs)
statrecorder.waitonchange(checkinterval=2.0)
except KeyboardInterrupt:
print()
@@ -29,7 +30,6 @@ def looponfail_main(config):
class RemoteControl(object):
def __init__(self, config):
self.config = config
self.remote_topdir = None
self.failures = []
def trace(self, *args):
@@ -70,8 +70,8 @@ class RemoteControl(object):
def runsession(self):
try:
self.trace("sending", (self.remote_topdir, self.failures))
self.channel.send((self.remote_topdir, self.failures))
self.trace("sending", self.failures)
self.channel.send(self.failures)
try:
return self.channel.receive()
except self.channel.RemoteError:
@@ -85,15 +85,11 @@ class RemoteControl(object):
self.setup()
self.wasfailing = self.failures and len(self.failures)
result = self.runsession()
topdir, failures, reports, collection_failed = result
failures, reports, collection_failed = result
if collection_failed:
reports = ["Collection failed, keeping previous failure set"]
else:
self.remote_topdir, self.failures = topdir, failures
repr_pytest_looponfailinfo(
failreports=reports,
rootdirs=[self.remote_topdir],)
self.failures = failures
def repr_pytest_looponfailinfo(failreports, rootdirs):
tr = py.io.TerminalWriter()
@@ -147,23 +143,29 @@ class SlaveFailSession:
def pytest_collection(self, session):
self.session = session
self.collection = session.collection
self.topdir, self.trails = self.current_command
if self.topdir and self.trails:
self.topdir = py.path.local(self.topdir)
self.collection.topdir = self.topdir
self.collection = collection = session.collection
self.trails = self.current_command
hook = self.collection.ihook
try:
items = collection.perform_collect(self.trails or None)
except pytest.UsageError:
items = collection.perform_collect(None)
hook.pytest_collection_modifyitems(config=session.config, items=items)
hook.pytest_collection_finish(collection=collection)
return True
if self.trails:
col = self.collection
items = []
for trail in self.trails:
names = col._parsearg(trail, base=self.topdir)
names = col._parsearg(trail)
try:
for node in col.matchnodes([col._topcollector], names):
items.extend(col.genitems(node))
except self.config.Error:
except pytest.UsageError:
pass # ignore collect errors / vanished tests
self.collection.items = items
return True
self.topdir = session.collection.topdir
def pytest_runtest_logreport(self, report):
if report.failed:
@@ -189,8 +191,7 @@ class SlaveFailSession:
loc = rep.longrepr
loc = str(getattr(loc, 'reprcrash', loc))
failreports.append(loc)
topdir = str(self.topdir)
self.channel.send((topdir, trails, failreports, self.collection_failed))
self.channel.send((trails, failreports, self.collection_failed))
class StatRecorder:
def __init__(self, rootdirlist):

View File

@@ -142,7 +142,7 @@ where the configuration file was found.
"""
import sys
import py
import py, pytest
def pytest_addoption(parser):
group = parser.getgroup("xdist", "distributed and subprocess testing")
@@ -178,6 +178,8 @@ def pytest_addoption(parser):
' remote distributed testing.', type="pathlist")
parser.addini('rsyncignore', 'list of (relative) paths to be ignored '
'for rsyncing.', type="pathlist")
parser.addini("looponfailroots", type="pathlist",
help="directories to check for changes", default=[py.path.local()])
# -------------------------------------------------------------------------
# distributed testing hooks
@@ -218,10 +220,10 @@ def check_options(config):
usepdb = config.option.usepdb # a core option
if val("looponfail"):
if usepdb:
raise config.Error("--pdb incompatible with --looponfail.")
raise pytest.UsageError("--pdb incompatible with --looponfail.")
elif val("dist") != "no":
if usepdb:
raise config.Error("--pdb incompatible with distributing tests.")
raise pytest.UsageError("--pdb incompatible with distributing tests.")
def pytest_runtest_protocol(item):

View File

@@ -53,8 +53,8 @@ class SlaveInteractor:
if name == "runtests":
ids = kwargs['ids']
for nodeid in ids:
for item in self.collection.getbyid(nodeid):
self.config.hook.pytest_runtest_protocol(item=item)
item = self._id2item[nodeid]
self.config.hook.pytest_runtest_protocol(item=item)
elif name == "runtests_all":
for item in self.collection.items:
self.config.hook.pytest_runtest_protocol(item=item)
@@ -63,9 +63,13 @@ class SlaveInteractor:
return True
def pytest_collection_finish(self, collection):
ids = [collection.getid(item) for item in collection.items]
self._id2item = {}
ids = []
for item in collection.items:
self._id2item[item.nodeid] = item
ids.append(item.nodeid)
self.sendevent("collectionfinish",
topdir=str(collection.topdir),
topdir=str(collection.fspath),
ids=ids)
#def pytest_runtest_logstart(self, nodeid, location, fspath):