properly handle test items that get locally collected but cannot be collected on the remote side (often due to platform reasons)

--HG--
branch : 1.0.x
This commit is contained in:
holger krekel 2009-07-30 09:52:12 +02:00
parent dcf194ebb8
commit ad34e50b71
5 changed files with 61 additions and 15 deletions

View File

@ -1,7 +1,11 @@
Changes between 1.0.0b8 and 1.0.0b9
=====================================
* simplified py.test.mark API
* dist-testing: properly handle test items that get locally
collected but cannot be collected on the remote side - often
due to platform/dependency reasons
* simplified py.test.mark API - see keyword plugin documentation
* make assert-reinterpretation work better with comparisons not
returning bools (reported with numpy from thanks maciej fijalkowski)

View File

@ -4,7 +4,6 @@ Collectors and test Items form a tree
that is usually built iteratively.
"""
import py
from py.__.test.outcome import Skipped
def configproperty(name):
def fget(self):
@ -31,6 +30,10 @@ class Node(object):
self.config = getattr(parent, 'config', None)
self.fspath = getattr(parent, 'fspath', None)
def _checkcollectable(self):
if not hasattr(self, 'fspath'):
self.parent._memocollect() # to reraise exception
#
# note to myself: Pickling is uh.
#
@ -44,6 +47,7 @@ class Node(object):
except Exception:
# seems our parent can't collect us
# so let's be somewhat operable
# _checkcollectable() is to tell outsiders about the fact
self.name = name
self.parent = parent
self.config = parent.config

View File

@ -367,13 +367,21 @@ class TestDSession:
assert node.gateway.spec.popen
#XXX eq.geteventargs("pytest_sessionfinish")
@py.test.mark.xfail
def test_collected_function_causes_remote_skip_at_module_level(self, testdir):
p = testdir.makepyfile("""
import py
py.test.importorskip("xyz")
def test_func():
pass
""")
# we need to be able to collect test_func locally but not in the subprocess
XXX
def test_collected_function_causes_remote_skip(testdir):
sub = testdir.mkpydir("testing")
sub.join("test_module.py").write(py.code.Source("""
import py
path = py.path.local(%r)
if path.check():
path.remove()
else:
py.test.skip("remote skip")
def test_func():
pass
def test_func2():
pass
""" % str(sub.ensure("somefile"))))
result = testdir.runpytest('-v', '--dist=each', '--tx=popen')
result.stdout.fnmatch_lines([
"*2 skipped*"
])

View File

@ -124,12 +124,37 @@ class SlaveNode(object):
break
if isinstance(task, list):
for item in task:
item.config.hook.pytest_runtest_protocol(item=item)
self.run_single(item=item)
else:
task.config.hook.pytest_runtest_protocol(item=task)
self.run_single(item=task)
except KeyboardInterrupt:
raise
except:
er = py.code.ExceptionInfo().getrepr(funcargs=True, showlocals=True)
self.sendevent("pytest_internalerror", excrepr=er)
raise
def run_single(self, item):
call = CallInfo(item._checkcollectable, 'setup')
if call.excinfo:
# likely it is not collectable here because of
# platform/import-dependency induced skips
# XXX somewhat ugly shortcuts - also makes a collection
# failure into an ItemTestReport - this might confuse
# pytest_runtest_logreport hooks
runner = item.config.pluginmanager.getplugin("pytest_runner")
rep = runner.pytest_runtest_makereport(item=item, call=call)
self.pytest_runtest_logreport(rep)
return
item.config.hook.pytest_runtest_protocol(item=item)
class CallInfo:
excinfo = None
def __init__(self, func, when):
self.when = when
try:
self.result = func()
except KeyboardInterrupt:
raise
except:
self.excinfo = py.code.ExceptionInfo()

View File

@ -130,6 +130,11 @@ class TmpTestdir:
def mkdir(self, name):
return self.tmpdir.mkdir(name)
def mkpydir(self, name):
p = self.mkdir(name)
p.ensure("__init__.py")
return p
def genitems(self, colitems):
return list(self.session.genitems(colitems))