move some code around, ending up with fewer files logically grouped
This commit is contained in:
@@ -272,3 +272,101 @@ class TestTerminalReporting:
|
|||||||
"> assert 0",
|
"> assert 0",
|
||||||
"E assert 0",
|
"E assert 0",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_teardownfails_one_function(testdir):
|
||||||
|
p = testdir.makepyfile("""
|
||||||
|
def test_func():
|
||||||
|
pass
|
||||||
|
def teardown_function(function):
|
||||||
|
assert 0
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest(p, '-n1', '--tx=popen')
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*def teardown_function(function):*",
|
||||||
|
"*1 passed*1 error*"
|
||||||
|
])
|
||||||
|
|
||||||
|
@py.test.mark.xfail
|
||||||
|
def test_terminate_on_hangingnode(testdir):
|
||||||
|
p = testdir.makeconftest("""
|
||||||
|
def pytest__teardown_final(session):
|
||||||
|
if session.nodeid == "my": # running on slave
|
||||||
|
import time
|
||||||
|
time.sleep(3)
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest(p, '--dist=each', '--tx=popen//id=my')
|
||||||
|
assert result.duration < 2.0
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*killed*my*",
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_session_hooks(testdir):
|
||||||
|
testdir.makeconftest("""
|
||||||
|
import sys
|
||||||
|
def pytest_sessionstart(session):
|
||||||
|
sys.pytestsessionhooks = session
|
||||||
|
def pytest_sessionfinish(session):
|
||||||
|
if hasattr(session.config, 'slaveinput'):
|
||||||
|
name = "slave"
|
||||||
|
else:
|
||||||
|
name = "master"
|
||||||
|
f = open(name, "w")
|
||||||
|
f.write("xy")
|
||||||
|
f.close()
|
||||||
|
# let's fail on the slave
|
||||||
|
if name == "slave":
|
||||||
|
raise ValueError(42)
|
||||||
|
""")
|
||||||
|
p = testdir.makepyfile("""
|
||||||
|
import sys
|
||||||
|
def test_hello():
|
||||||
|
assert hasattr(sys, 'pytestsessionhooks')
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest(p, "--dist=each", "--tx=popen")
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*ValueError*",
|
||||||
|
"*1 passed*",
|
||||||
|
])
|
||||||
|
assert not result.ret
|
||||||
|
d = result.parseoutcomes()
|
||||||
|
assert d['passed'] == 1
|
||||||
|
assert testdir.tmpdir.join("slave").check()
|
||||||
|
assert testdir.tmpdir.join("master").check()
|
||||||
|
|
||||||
|
def test_funcarg_teardown_failure(testdir):
|
||||||
|
p = testdir.makepyfile("""
|
||||||
|
def pytest_funcarg__myarg(request):
|
||||||
|
def teardown(val):
|
||||||
|
raise ValueError(val)
|
||||||
|
return request.cached_setup(setup=lambda: 42, teardown=teardown,
|
||||||
|
scope="module")
|
||||||
|
def test_hello(myarg):
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest("--debug", p, "-n1")
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*ValueError*42*",
|
||||||
|
"*1 passed*1 error*",
|
||||||
|
])
|
||||||
|
py.test.xfail("fix exitstatus handling")
|
||||||
|
assert result.ret
|
||||||
|
|
||||||
|
def test_crashing_item(testdir):
|
||||||
|
p = testdir.makepyfile("""
|
||||||
|
import py
|
||||||
|
import os
|
||||||
|
def test_crash():
|
||||||
|
py.process.kill(os.getpid())
|
||||||
|
def test_noncrash():
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest("-n2", p)
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*crashed*test_crash*",
|
||||||
|
"*1 failed*1 passed*"
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -429,115 +429,3 @@ class TestDSession:
|
|||||||
linecomp.assert_contains_lines([
|
linecomp.assert_contains_lines([
|
||||||
"[X1,X2] rsyncing: hello",
|
"[X1,X2] rsyncing: hello",
|
||||||
])
|
])
|
||||||
|
|
||||||
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*"
|
|
||||||
])
|
|
||||||
|
|
||||||
def test_teardownfails_one_function(testdir):
|
|
||||||
p = testdir.makepyfile("""
|
|
||||||
def test_func():
|
|
||||||
pass
|
|
||||||
def teardown_function(function):
|
|
||||||
assert 0
|
|
||||||
""")
|
|
||||||
result = testdir.runpytest(p, '--dist=each', '--tx=popen')
|
|
||||||
result.stdout.fnmatch_lines([
|
|
||||||
"*def teardown_function(function):*",
|
|
||||||
"*1 passed*1 error*"
|
|
||||||
])
|
|
||||||
|
|
||||||
@py.test.mark.xfail
|
|
||||||
def test_terminate_on_hangingnode(testdir):
|
|
||||||
p = testdir.makeconftest("""
|
|
||||||
def pytest__teardown_final(session):
|
|
||||||
if session.nodeid == "my": # running on slave
|
|
||||||
import time
|
|
||||||
time.sleep(3)
|
|
||||||
""")
|
|
||||||
result = testdir.runpytest(p, '--dist=each', '--tx=popen//id=my')
|
|
||||||
assert result.duration < 2.0
|
|
||||||
result.stdout.fnmatch_lines([
|
|
||||||
"*killed*my*",
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_session_hooks(testdir):
|
|
||||||
testdir.makeconftest("""
|
|
||||||
import sys
|
|
||||||
def pytest_sessionstart(session):
|
|
||||||
sys.pytestsessionhooks = session
|
|
||||||
def pytest_sessionfinish(session):
|
|
||||||
f = open(session.nodeid or "master", 'w')
|
|
||||||
f.write("xy")
|
|
||||||
f.close()
|
|
||||||
# let's fail on the slave
|
|
||||||
if session.nodeid:
|
|
||||||
raise ValueError(42)
|
|
||||||
""")
|
|
||||||
p = testdir.makepyfile("""
|
|
||||||
import sys
|
|
||||||
def test_hello():
|
|
||||||
assert hasattr(sys, 'pytestsessionhooks')
|
|
||||||
""")
|
|
||||||
result = testdir.runpytest(p, "--dist=each", "--tx=popen//id=my1")
|
|
||||||
result.stdout.fnmatch_lines([
|
|
||||||
"*ValueError*",
|
|
||||||
"*1 passed*",
|
|
||||||
])
|
|
||||||
assert result.ret
|
|
||||||
d = result.parseoutcomes()
|
|
||||||
assert d['passed'] == 1
|
|
||||||
assert testdir.tmpdir.join("my1").check()
|
|
||||||
assert testdir.tmpdir.join("master").check()
|
|
||||||
|
|
||||||
def test_funcarg_teardown_failure(testdir):
|
|
||||||
p = testdir.makepyfile("""
|
|
||||||
def pytest_funcarg__myarg(request):
|
|
||||||
def teardown(val):
|
|
||||||
raise ValueError(val)
|
|
||||||
return request.cached_setup(setup=lambda: 42, teardown=teardown,
|
|
||||||
scope="module")
|
|
||||||
def test_hello(myarg):
|
|
||||||
pass
|
|
||||||
""")
|
|
||||||
result = testdir.runpytest(p, "-n1")
|
|
||||||
assert result.ret
|
|
||||||
result.stdout.fnmatch_lines([
|
|
||||||
"*ValueError*42*",
|
|
||||||
"*1 passed*1 error*",
|
|
||||||
])
|
|
||||||
|
|
||||||
def test_crashing_item(testdir):
|
|
||||||
p = testdir.makepyfile("""
|
|
||||||
import py
|
|
||||||
import os
|
|
||||||
def test_crash():
|
|
||||||
py.process.kill(os.getpid())
|
|
||||||
def test_noncrash():
|
|
||||||
pass
|
|
||||||
""")
|
|
||||||
result = testdir.runpytest("-n2", p)
|
|
||||||
result.stdout.fnmatch_lines([
|
|
||||||
"*crashed*test_crash*",
|
|
||||||
"*1 failed*1 passed*"
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,65 @@
|
|||||||
import py
|
import py
|
||||||
from xdist.looponfail import RemoteControl
|
from xdist.looponfail import RemoteControl
|
||||||
|
from xdist.looponfail import StatRecorder
|
||||||
|
|
||||||
|
class TestStatRecorder:
|
||||||
|
def test_filechange(self, tmpdir):
|
||||||
|
tmp = tmpdir
|
||||||
|
hello = tmp.ensure("hello.py")
|
||||||
|
sd = StatRecorder([tmp])
|
||||||
|
changed = sd.check()
|
||||||
|
assert not changed
|
||||||
|
|
||||||
|
hello.write("world")
|
||||||
|
changed = sd.check()
|
||||||
|
assert changed
|
||||||
|
|
||||||
|
tmp.ensure("new.py")
|
||||||
|
changed = sd.check()
|
||||||
|
assert changed
|
||||||
|
|
||||||
|
tmp.join("new.py").remove()
|
||||||
|
changed = sd.check()
|
||||||
|
assert changed
|
||||||
|
|
||||||
|
tmp.join("a", "b", "c.py").ensure()
|
||||||
|
changed = sd.check()
|
||||||
|
assert changed
|
||||||
|
|
||||||
|
tmp.join("a", "c.txt").ensure()
|
||||||
|
changed = sd.check()
|
||||||
|
assert changed
|
||||||
|
changed = sd.check()
|
||||||
|
assert not changed
|
||||||
|
|
||||||
|
tmp.join("a").remove()
|
||||||
|
changed = sd.check()
|
||||||
|
assert changed
|
||||||
|
|
||||||
|
def test_pycremoval(self, tmpdir):
|
||||||
|
tmp = tmpdir
|
||||||
|
hello = tmp.ensure("hello.py")
|
||||||
|
sd = StatRecorder([tmp])
|
||||||
|
changed = sd.check()
|
||||||
|
assert not changed
|
||||||
|
|
||||||
|
pycfile = hello + "c"
|
||||||
|
pycfile.ensure()
|
||||||
|
changed = sd.check()
|
||||||
|
assert not changed
|
||||||
|
|
||||||
|
hello.write("world")
|
||||||
|
changed = sd.check()
|
||||||
|
assert not pycfile.check()
|
||||||
|
|
||||||
|
def test_waitonchange(self, tmpdir, monkeypatch):
|
||||||
|
tmp = tmpdir
|
||||||
|
sd = StatRecorder([tmp])
|
||||||
|
|
||||||
|
l = [True, False]
|
||||||
|
monkeypatch.setattr(StatRecorder, 'check', lambda self: l.pop())
|
||||||
|
sd.waitonchange(checkinterval=0.2)
|
||||||
|
assert not l
|
||||||
|
|
||||||
class TestRemoteControl:
|
class TestRemoteControl:
|
||||||
def test_nofailures(self, testdir):
|
def test_nofailures(self, testdir):
|
||||||
@@ -174,3 +234,4 @@ def removepyc(path):
|
|||||||
pyc = path + "c"
|
pyc = path + "c"
|
||||||
if pyc.check():
|
if pyc.check():
|
||||||
pyc.remove()
|
pyc.remove()
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ class TestReportSerialization:
|
|||||||
for rep in reports:
|
for rep in reports:
|
||||||
d = serialize_report(rep)
|
d = serialize_report(rep)
|
||||||
check_marshallable(d)
|
check_marshallable(d)
|
||||||
newrep = unserialize_report(d)
|
newrep = unserialize_report("testreport", d)
|
||||||
assert newrep.passed == rep.passed
|
assert newrep.passed == rep.passed
|
||||||
assert newrep.failed == rep.failed
|
assert newrep.failed == rep.failed
|
||||||
assert newrep.skipped == rep.skipped
|
assert newrep.skipped == rep.skipped
|
||||||
@@ -99,7 +99,7 @@ class TestReportSerialization:
|
|||||||
for rep in reports:
|
for rep in reports:
|
||||||
d = serialize_report(rep)
|
d = serialize_report(rep)
|
||||||
check_marshallable(d)
|
check_marshallable(d)
|
||||||
newrep = unserialize_report(d)
|
newrep = unserialize_report("collectreport", d)
|
||||||
assert newrep.passed == rep.passed
|
assert newrep.passed == rep.passed
|
||||||
assert newrep.failed == rep.failed
|
assert newrep.failed == rep.failed
|
||||||
assert newrep.skipped == rep.skipped
|
assert newrep.skipped == rep.skipped
|
||||||
@@ -111,7 +111,7 @@ class TestReportSerialization:
|
|||||||
for rep in reports:
|
for rep in reports:
|
||||||
d = serialize_report(rep)
|
d = serialize_report(rep)
|
||||||
check_marshallable(d)
|
check_marshallable(d)
|
||||||
newrep = unserialize_report(d)
|
newrep = unserialize_report("collectreport", d)
|
||||||
assert newrep.passed == rep.passed
|
assert newrep.passed == rep.passed
|
||||||
assert newrep.failed == rep.failed
|
assert newrep.failed == rep.failed
|
||||||
assert newrep.skipped == rep.skipped
|
assert newrep.skipped == rep.skipped
|
||||||
@@ -137,7 +137,7 @@ class TestSlaveInteractor:
|
|||||||
slave.sendcommand("runtests", ids=ids)
|
slave.sendcommand("runtests", ids=ids)
|
||||||
ev = slave.popevent("testreport")
|
ev = slave.popevent("testreport")
|
||||||
assert ev.name == "testreport"
|
assert ev.name == "testreport"
|
||||||
rep = unserialize_report(ev.kwargs['data'])
|
rep = unserialize_report(ev.name, ev.kwargs['data'])
|
||||||
assert rep.nodeid.endswith("::test_func")
|
assert rep.nodeid.endswith("::test_func")
|
||||||
assert rep.passed
|
assert rep.passed
|
||||||
assert rep.when == "call"
|
assert rep.when == "call"
|
||||||
@@ -155,7 +155,7 @@ class TestSlaveInteractor:
|
|||||||
assert not ev.kwargs
|
assert not ev.kwargs
|
||||||
ev = slave.popevent()
|
ev = slave.popevent()
|
||||||
assert ev.name == "collectreport"
|
assert ev.name == "collectreport"
|
||||||
rep = unserialize_report(ev.kwargs['data'])
|
rep = unserialize_report(ev.name, ev.kwargs['data'])
|
||||||
assert rep.skipped
|
assert rep.skipped
|
||||||
ev = slave.popevent("collectionfinish")
|
ev = slave.popevent("collectionfinish")
|
||||||
print ev.kwargs
|
print ev.kwargs
|
||||||
@@ -168,7 +168,7 @@ class TestSlaveInteractor:
|
|||||||
assert not ev.kwargs
|
assert not ev.kwargs
|
||||||
ev = slave.popevent()
|
ev = slave.popevent()
|
||||||
assert ev.name == "collectreport"
|
assert ev.name == "collectreport"
|
||||||
rep = unserialize_report(ev.kwargs['data'])
|
rep = unserialize_report(ev.name, ev.kwargs['data'])
|
||||||
assert rep.failed
|
assert rep.failed
|
||||||
ev = slave.popevent("collectionfinish")
|
ev = slave.popevent("collectionfinish")
|
||||||
print ev.kwargs
|
print ev.kwargs
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
import py
|
|
||||||
from xdist.util import StatRecorder
|
|
||||||
|
|
||||||
def test_filechange(tmpdir):
|
|
||||||
tmp = tmpdir
|
|
||||||
hello = tmp.ensure("hello.py")
|
|
||||||
sd = StatRecorder([tmp])
|
|
||||||
changed = sd.check()
|
|
||||||
assert not changed
|
|
||||||
|
|
||||||
hello.write("world")
|
|
||||||
changed = sd.check()
|
|
||||||
assert changed
|
|
||||||
|
|
||||||
tmp.ensure("new.py")
|
|
||||||
changed = sd.check()
|
|
||||||
assert changed
|
|
||||||
|
|
||||||
tmp.join("new.py").remove()
|
|
||||||
changed = sd.check()
|
|
||||||
assert changed
|
|
||||||
|
|
||||||
tmp.join("a", "b", "c.py").ensure()
|
|
||||||
changed = sd.check()
|
|
||||||
assert changed
|
|
||||||
|
|
||||||
tmp.join("a", "c.txt").ensure()
|
|
||||||
changed = sd.check()
|
|
||||||
assert changed
|
|
||||||
changed = sd.check()
|
|
||||||
assert not changed
|
|
||||||
|
|
||||||
tmp.join("a").remove()
|
|
||||||
changed = sd.check()
|
|
||||||
assert changed
|
|
||||||
|
|
||||||
def test_pycremoval(tmpdir):
|
|
||||||
tmp = tmpdir
|
|
||||||
hello = tmp.ensure("hello.py")
|
|
||||||
sd = StatRecorder([tmp])
|
|
||||||
changed = sd.check()
|
|
||||||
assert not changed
|
|
||||||
|
|
||||||
pycfile = hello + "c"
|
|
||||||
pycfile.ensure()
|
|
||||||
changed = sd.check()
|
|
||||||
assert not changed
|
|
||||||
|
|
||||||
hello.write("world")
|
|
||||||
changed = sd.check()
|
|
||||||
assert not pycfile.check()
|
|
||||||
|
|
||||||
|
|
||||||
def test_waitonchange(tmpdir, monkeypatch):
|
|
||||||
tmp = tmpdir
|
|
||||||
sd = StatRecorder([tmp])
|
|
||||||
|
|
||||||
l = [True, False]
|
|
||||||
monkeypatch.setattr(StatRecorder, 'check', lambda self: l.pop())
|
|
||||||
sd.waitonchange(checkinterval=0.2)
|
|
||||||
assert not l
|
|
||||||
2
tox.ini
2
tox.ini
@@ -8,7 +8,7 @@ changedir=testing
|
|||||||
deps=
|
deps=
|
||||||
{distshare}/py-*
|
{distshare}/py-*
|
||||||
commands=
|
commands=
|
||||||
py.test -rsfxX --tools-on-path \
|
py.test -rsfxX \
|
||||||
--junitxml={envlogdir}/junit-{envname}.xml []
|
--junitxml={envlogdir}/junit-{envname}.xml []
|
||||||
[testenv:py26]
|
[testenv:py26]
|
||||||
basepython=python2.6
|
basepython=python2.6
|
||||||
|
|||||||
@@ -199,12 +199,17 @@ class DSession:
|
|||||||
nodeid=nodeid, location=location)
|
nodeid=nodeid, location=location)
|
||||||
|
|
||||||
def slave_testreport(self, node, rep):
|
def slave_testreport(self, node, rep):
|
||||||
|
if rep.when in ("setup", "call"):
|
||||||
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)
|
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_teardownreport(self, node, rep):
|
||||||
|
enrich_report_with_platform_data(rep, node)
|
||||||
|
self.config.hook.pytest__teardown_final_logerror(report=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
|
#rep.node = node
|
||||||
|
|||||||
@@ -11,13 +11,12 @@ import py
|
|||||||
import sys
|
import sys
|
||||||
import execnet
|
import execnet
|
||||||
from py._test.session import gettopdir
|
from py._test.session import gettopdir
|
||||||
from xdist import util
|
|
||||||
|
|
||||||
def looponfail_main(config):
|
def looponfail_main(config):
|
||||||
remotecontrol = RemoteControl(config)
|
remotecontrol = RemoteControl(config)
|
||||||
# XXX better configure rootdir
|
# XXX better configure rootdir
|
||||||
rootdirs = [gettopdir(config.args)]
|
rootdirs = [gettopdir(config.args)]
|
||||||
statrecorder = util.StatRecorder(rootdirs)
|
statrecorder = StatRecorder(rootdirs)
|
||||||
try:
|
try:
|
||||||
while 1:
|
while 1:
|
||||||
remotecontrol.loop_once()
|
remotecontrol.loop_once()
|
||||||
@@ -191,3 +190,54 @@ class SlaveFailSession:
|
|||||||
topdir = str(self.topdir)
|
topdir = str(self.topdir)
|
||||||
self.channel.send((topdir, trails, failreports, self.collection_failed))
|
self.channel.send((topdir, trails, failreports, self.collection_failed))
|
||||||
|
|
||||||
|
class StatRecorder:
|
||||||
|
def __init__(self, rootdirlist):
|
||||||
|
self.rootdirlist = rootdirlist
|
||||||
|
self.statcache = {}
|
||||||
|
self.check() # snapshot state
|
||||||
|
|
||||||
|
def fil(self, p):
|
||||||
|
return p.ext in ('.py', '.txt', '.c', '.h')
|
||||||
|
def rec(self, p):
|
||||||
|
return p.check(dotfile=0)
|
||||||
|
|
||||||
|
def waitonchange(self, checkinterval=1.0):
|
||||||
|
while 1:
|
||||||
|
changed = self.check()
|
||||||
|
if changed:
|
||||||
|
return
|
||||||
|
py.std.time.sleep(checkinterval)
|
||||||
|
|
||||||
|
def check(self, removepycfiles=True):
|
||||||
|
changed = False
|
||||||
|
statcache = self.statcache
|
||||||
|
newstat = {}
|
||||||
|
for rootdir in self.rootdirlist:
|
||||||
|
for path in rootdir.visit(self.fil, self.rec):
|
||||||
|
oldstat = statcache.get(path, None)
|
||||||
|
if oldstat is not None:
|
||||||
|
del statcache[path]
|
||||||
|
try:
|
||||||
|
newstat[path] = curstat = path.stat()
|
||||||
|
except py.error.ENOENT:
|
||||||
|
if oldstat:
|
||||||
|
del statcache[path]
|
||||||
|
changed = True
|
||||||
|
else:
|
||||||
|
if oldstat:
|
||||||
|
if oldstat.mtime != curstat.mtime or \
|
||||||
|
oldstat.size != curstat.size:
|
||||||
|
changed = True
|
||||||
|
py.builtin.print_("# MODIFIED", path)
|
||||||
|
if removepycfiles and path.ext == ".py":
|
||||||
|
pycfile = path + "c"
|
||||||
|
if pycfile.check():
|
||||||
|
pycfile.remove()
|
||||||
|
|
||||||
|
else:
|
||||||
|
changed = True
|
||||||
|
if statcache:
|
||||||
|
changed = True
|
||||||
|
self.statcache = newstat
|
||||||
|
return changed
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ class SlaveInteractor:
|
|||||||
for line in str(excrepr).split("\n"):
|
for line in str(excrepr).split("\n"):
|
||||||
self.log("IERROR> " + line)
|
self.log("IERROR> " + line)
|
||||||
|
|
||||||
|
def pytest__teardown_final_logerror(self, report):
|
||||||
|
rep = serialize_report(report)
|
||||||
|
self.sendevent("teardownreport", data=rep)
|
||||||
|
|
||||||
def pytest_sessionstart(self, session):
|
def pytest_sessionstart(self, session):
|
||||||
self.session = session
|
self.session = session
|
||||||
self.collection = session.collection
|
self.collection = session.collection
|
||||||
|
|||||||
@@ -295,8 +295,8 @@ class SlaveController(object):
|
|||||||
self.notify_inproc("slavefinished", node=self)
|
self.notify_inproc("slavefinished", node=self)
|
||||||
#elif eventname == "logstart":
|
#elif eventname == "logstart":
|
||||||
# self.notify_inproc(eventname, node=self, **kwargs)
|
# self.notify_inproc(eventname, node=self, **kwargs)
|
||||||
elif eventname in ("testreport", "collectreport"):
|
elif eventname in ("testreport", "collectreport", "teardownreport"):
|
||||||
rep = unserialize_report(kwargs['data'])
|
rep = unserialize_report(eventname, kwargs['data'])
|
||||||
self.notify_inproc(eventname, node=self, rep=rep)
|
self.notify_inproc(eventname, node=self, rep=rep)
|
||||||
elif eventname == "collectionfinish":
|
elif eventname == "collectionfinish":
|
||||||
self.notify_inproc(eventname, node=self, ids=kwargs['ids'])
|
self.notify_inproc(eventname, node=self, ids=kwargs['ids'])
|
||||||
@@ -310,9 +310,11 @@ class SlaveController(object):
|
|||||||
py.builtin.print_("!" * 20, excinfo)
|
py.builtin.print_("!" * 20, excinfo)
|
||||||
self.config.pluginmanager.notify_exception(excinfo)
|
self.config.pluginmanager.notify_exception(excinfo)
|
||||||
|
|
||||||
def unserialize_report(reportdict):
|
def unserialize_report(name, reportdict):
|
||||||
d = reportdict
|
d = reportdict
|
||||||
if 'result' in d:
|
if name == "testreport":
|
||||||
return runner.CollectReport(**d)
|
|
||||||
else:
|
|
||||||
return runner.TestReport(**d)
|
return runner.TestReport(**d)
|
||||||
|
elif name == "collectreport":
|
||||||
|
return runner.CollectReport(**d)
|
||||||
|
elif name == "teardownreport":
|
||||||
|
return runner.TeardownErrorReport(**d)
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
import py
|
|
||||||
|
|
||||||
class StatRecorder:
|
|
||||||
def __init__(self, rootdirlist):
|
|
||||||
self.rootdirlist = rootdirlist
|
|
||||||
self.statcache = {}
|
|
||||||
self.check() # snapshot state
|
|
||||||
|
|
||||||
def fil(self, p):
|
|
||||||
return p.ext in ('.py', '.txt', '.c', '.h')
|
|
||||||
def rec(self, p):
|
|
||||||
return p.check(dotfile=0)
|
|
||||||
|
|
||||||
def waitonchange(self, checkinterval=1.0):
|
|
||||||
while 1:
|
|
||||||
changed = self.check()
|
|
||||||
if changed:
|
|
||||||
return
|
|
||||||
py.std.time.sleep(checkinterval)
|
|
||||||
|
|
||||||
def check(self, removepycfiles=True):
|
|
||||||
changed = False
|
|
||||||
statcache = self.statcache
|
|
||||||
newstat = {}
|
|
||||||
for rootdir in self.rootdirlist:
|
|
||||||
for path in rootdir.visit(self.fil, self.rec):
|
|
||||||
oldstat = statcache.get(path, None)
|
|
||||||
if oldstat is not None:
|
|
||||||
del statcache[path]
|
|
||||||
try:
|
|
||||||
newstat[path] = curstat = path.stat()
|
|
||||||
except py.error.ENOENT:
|
|
||||||
if oldstat:
|
|
||||||
del statcache[path]
|
|
||||||
changed = True
|
|
||||||
else:
|
|
||||||
if oldstat:
|
|
||||||
if oldstat.mtime != curstat.mtime or \
|
|
||||||
oldstat.size != curstat.size:
|
|
||||||
changed = True
|
|
||||||
py.builtin.print_("# MODIFIED", path)
|
|
||||||
if removepycfiles and path.ext == ".py":
|
|
||||||
pycfile = path + "c"
|
|
||||||
if pycfile.check():
|
|
||||||
pycfile.remove()
|
|
||||||
|
|
||||||
else:
|
|
||||||
changed = True
|
|
||||||
if statcache:
|
|
||||||
changed = True
|
|
||||||
self.statcache = newstat
|
|
||||||
return changed
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user