[svn r63560] beginning to review/polish test events
* pyevent() now receives args and kwargs as simple arguments * refactoring event handling in tests --HG-- branch : trunk
This commit is contained in:
parent
3ab894cadc
commit
54cc936437
|
@ -9,7 +9,7 @@ class EventQueue:
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
bus.register(self)
|
bus.register(self)
|
||||||
|
|
||||||
def pyevent(self, eventname, *args, **kwargs):
|
def pyevent(self, eventname, args, kwargs):
|
||||||
self.queue.put((eventname, args, kwargs))
|
self.queue.put((eventname, args, kwargs))
|
||||||
|
|
||||||
def geteventargs(self, eventname, timeout=2.0):
|
def geteventargs(self, eventname, timeout=2.0):
|
||||||
|
@ -48,7 +48,7 @@ class MySetup:
|
||||||
assert not self.node.channel.isclosed()
|
assert not self.node.channel.isclosed()
|
||||||
return self.node
|
return self.node
|
||||||
|
|
||||||
def finalize(self):
|
def xfinalize(self):
|
||||||
if hasattr(self, 'node'):
|
if hasattr(self, 'node'):
|
||||||
gw = self.node.gateway
|
gw = self.node.gateway
|
||||||
print "exiting:", gw
|
print "exiting:", gw
|
||||||
|
@ -56,7 +56,7 @@ class MySetup:
|
||||||
|
|
||||||
def pytest_funcarg__mysetup(pyfuncitem):
|
def pytest_funcarg__mysetup(pyfuncitem):
|
||||||
mysetup = MySetup(pyfuncitem)
|
mysetup = MySetup(pyfuncitem)
|
||||||
pyfuncitem.addfinalizer(mysetup.finalize)
|
#pyfuncitem.addfinalizer(mysetup.finalize)
|
||||||
return mysetup
|
return mysetup
|
||||||
|
|
||||||
def pytest_funcarg__testdir(__call__, pyfuncitem):
|
def pytest_funcarg__testdir(__call__, pyfuncitem):
|
||||||
|
|
|
@ -22,10 +22,6 @@ class NOP(BaseEvent):
|
||||||
# Basic Live Reporting Events
|
# Basic Live Reporting Events
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
class TestrunStart(BaseEvent):
|
|
||||||
def __init__(self):
|
|
||||||
self.timestart = time.time()
|
|
||||||
|
|
||||||
class TestrunFinish(BaseEvent):
|
class TestrunFinish(BaseEvent):
|
||||||
def __init__(self, exitstatus=0, excinfo=None):
|
def __init__(self, exitstatus=0, excinfo=None):
|
||||||
self.exitstatus = exitstatus
|
self.exitstatus = exitstatus
|
||||||
|
|
|
@ -55,7 +55,7 @@ class PluginHooks:
|
||||||
|
|
||||||
class Events:
|
class Events:
|
||||||
# Events
|
# Events
|
||||||
def pyevent(self, eventname, *args, **kwargs):
|
def pyevent(self, eventname, args, kwargs):
|
||||||
""" generically called for each notification event. """
|
""" generically called for each notification event. """
|
||||||
|
|
||||||
def pyevent__gateway_init(self, gateway):
|
def pyevent__gateway_init(self, gateway):
|
||||||
|
@ -76,7 +76,7 @@ class Events:
|
||||||
def pyevent__internalerror(self, event):
|
def pyevent__internalerror(self, event):
|
||||||
""" called for internal errors. """
|
""" called for internal errors. """
|
||||||
|
|
||||||
def pyevent__itemstart(self, item, node):
|
def pyevent__itemstart(self, item, node=None):
|
||||||
""" test item gets collected. """
|
""" test item gets collected. """
|
||||||
|
|
||||||
def pyevent__itemtestreport(self, event):
|
def pyevent__itemtestreport(self, event):
|
||||||
|
@ -91,7 +91,7 @@ class Events:
|
||||||
def pyevent__collectionreport(self, event):
|
def pyevent__collectionreport(self, event):
|
||||||
""" collector finished collecting. """
|
""" collector finished collecting. """
|
||||||
|
|
||||||
def pyevent__testrunstart(self, event):
|
def pyevent__testrunstart(self):
|
||||||
""" whole test run starts. """
|
""" whole test run starts. """
|
||||||
|
|
||||||
def pyevent__testrunfinish(self, event):
|
def pyevent__testrunfinish(self, event):
|
||||||
|
|
|
@ -16,7 +16,7 @@ class EventlogPlugin:
|
||||||
self.eventlogfile.close()
|
self.eventlogfile.close()
|
||||||
del self.eventlogfile
|
del self.eventlogfile
|
||||||
|
|
||||||
def pyevent(self, eventname, *args, **kwargs):
|
def pyevent(self, eventname, args, kwargs):
|
||||||
if hasattr(self, 'eventlogfile'):
|
if hasattr(self, 'eventlogfile'):
|
||||||
f = self.eventlogfile
|
f = self.eventlogfile
|
||||||
print >>f, eventname, args, kwargs
|
print >>f, eventname, args, kwargs
|
||||||
|
@ -36,6 +36,6 @@ def test_generic(plugintester):
|
||||||
""")
|
""")
|
||||||
testdir.runpytest("--eventlog=event.log")
|
testdir.runpytest("--eventlog=event.log")
|
||||||
s = testdir.tmpdir.join("event.log").read()
|
s = testdir.tmpdir.join("event.log").read()
|
||||||
assert s.find("TestrunStart") != -1
|
assert s.find("testrunstart") != -1
|
||||||
assert s.find("ItemTestReport") != -1
|
assert s.find("ItemTestReport") != -1
|
||||||
assert s.find("TestrunFinish") != -1
|
assert s.find("TestrunFinish") != -1
|
||||||
|
|
|
@ -21,8 +21,8 @@ class ExecnetcleanupPlugin:
|
||||||
if self._gateways is not None:
|
if self._gateways is not None:
|
||||||
self._gateways.remove(gateway)
|
self._gateways.remove(gateway)
|
||||||
|
|
||||||
def pyevent__testrunstart(self, event):
|
def pyevent__testrunstart(self):
|
||||||
self.trace("testrunstart", event)
|
self.trace("testrunstart")
|
||||||
self._gateways = []
|
self._gateways = []
|
||||||
|
|
||||||
def pyevent__testrunfinish(self, event):
|
def pyevent__testrunfinish(self, event):
|
||||||
|
|
|
@ -3,8 +3,10 @@ pytes plugin for easing testing of pytest runs themselves.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
import inspect
|
||||||
from py.__.test import event
|
from py.__.test import event
|
||||||
from py.__.test.config import Config as pytestConfig
|
from py.__.test.config import Config as pytestConfig
|
||||||
|
import api
|
||||||
|
|
||||||
class PytesterPlugin:
|
class PytesterPlugin:
|
||||||
def pytest_funcarg__linecomp(self, pyfuncitem):
|
def pytest_funcarg__linecomp(self, pyfuncitem):
|
||||||
|
@ -257,6 +259,13 @@ class Event:
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Event %r %r>" %(self.name, self.args)
|
return "<Event %r %r>" %(self.name, self.args)
|
||||||
|
|
||||||
|
class ParsedEvent:
|
||||||
|
def __init__(self, locals):
|
||||||
|
self.__dict__ = locals.copy()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Event %r>" %(self.__dict__,)
|
||||||
|
|
||||||
class EventRecorder(object):
|
class EventRecorder(object):
|
||||||
def __init__(self, pyplugins, debug=False): # True):
|
def __init__(self, pyplugins, debug=False): # True):
|
||||||
self.events = []
|
self.events = []
|
||||||
|
@ -264,7 +273,7 @@ class EventRecorder(object):
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
pyplugins.register(self)
|
pyplugins.register(self)
|
||||||
|
|
||||||
def pyevent(self, name, *args, **kwargs):
|
def pyevent(self, name, args, kwargs):
|
||||||
if name == "plugin_registered" and args == (self,):
|
if name == "plugin_registered" and args == (self,):
|
||||||
return
|
return
|
||||||
if self.debug:
|
if self.debug:
|
||||||
|
@ -278,12 +287,42 @@ class EventRecorder(object):
|
||||||
return event
|
return event
|
||||||
raise KeyError("popevent: %r not found in %r" %(name, self.events))
|
raise KeyError("popevent: %r not found in %r" %(name, self.events))
|
||||||
|
|
||||||
|
def getevents(self, eventname):
|
||||||
|
method = self.geteventmethod(eventname)
|
||||||
|
l = []
|
||||||
|
for event in self.events:
|
||||||
|
if event.name == eventname:
|
||||||
|
pevent = method(*event.args, **event.kwargs)
|
||||||
|
l.append(pevent)
|
||||||
|
return l
|
||||||
|
|
||||||
|
def geteventmethod(self, eventname):
|
||||||
|
mname = "pyevent__" + eventname
|
||||||
|
method = getattr(api.Events, mname)
|
||||||
|
args, varargs, varkw, default = inspect.getargspec(method)
|
||||||
|
assert args[0] == "self"
|
||||||
|
args = args[1:]
|
||||||
|
fspec = inspect.formatargspec(args, varargs, varkw, default)
|
||||||
|
source = """def %(mname)s%(fspec)s:
|
||||||
|
return ParsedEvent(locals())""" % locals()
|
||||||
|
print source
|
||||||
|
exec source
|
||||||
|
return locals()[mname]
|
||||||
|
|
||||||
|
|
||||||
|
def firstparsedevent(self, eventname):
|
||||||
|
return self.parsedevents(eventname)[0]
|
||||||
|
|
||||||
def get(self, cls):
|
def get(self, cls):
|
||||||
l = []
|
l = []
|
||||||
for event in self.events:
|
for event in self.events:
|
||||||
value = event.args[0]
|
try:
|
||||||
if isinstance(value, cls):
|
value = event.args[0]
|
||||||
l.append(value)
|
except IndexError:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if isinstance(value, cls):
|
||||||
|
l.append(value)
|
||||||
return l
|
return l
|
||||||
|
|
||||||
def getnamed(self, *names):
|
def getnamed(self, *names):
|
||||||
|
|
|
@ -370,7 +370,7 @@ class TestWithFunctionIntegration:
|
||||||
except ValueError:
|
except ValueError:
|
||||||
excinfo = event.InternalException()
|
excinfo = event.InternalException()
|
||||||
reslog = ResultDB(StringIO.StringIO())
|
reslog = ResultDB(StringIO.StringIO())
|
||||||
reslog.pyevent("internalerror", excinfo)
|
reslog.pyevent("internalerror", (excinfo,), {})
|
||||||
entry = reslog.logfile.getvalue()
|
entry = reslog.logfile.getvalue()
|
||||||
entry_lines = entry.splitlines()
|
entry_lines = entry.splitlines()
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,9 @@ class ResultLog(object):
|
||||||
shortrepr, longrepr = getoutcomecodes(event)
|
shortrepr, longrepr = getoutcomecodes(event)
|
||||||
self.write_log_entry(shortrepr, gpath, longrepr)
|
self.write_log_entry(shortrepr, gpath, longrepr)
|
||||||
|
|
||||||
def pyevent(self, eventname, event, *args, **kwargs):
|
def pyevent(self, eventname, args, kwargs):
|
||||||
|
if args:
|
||||||
|
event = args[0]
|
||||||
if eventname == "itemtestreport":
|
if eventname == "itemtestreport":
|
||||||
self.log_outcome(event)
|
self.log_outcome(event)
|
||||||
elif eventname == "collectionreport":
|
elif eventname == "collectionreport":
|
||||||
|
@ -91,6 +93,7 @@ class ResultLog(object):
|
||||||
path = event.repr.reprcrash.path # fishing :(
|
path = event.repr.reprcrash.path # fishing :(
|
||||||
self.write_log_entry('!', path, str(event.repr))
|
self.write_log_entry('!', path, str(event.repr))
|
||||||
|
|
||||||
|
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
#
|
#
|
||||||
# plugin tests
|
# plugin tests
|
||||||
|
@ -223,7 +226,7 @@ class TestWithFunctionIntegration:
|
||||||
except ValueError:
|
except ValueError:
|
||||||
excinfo = event.InternalException()
|
excinfo = event.InternalException()
|
||||||
reslog = ResultLog(StringIO.StringIO())
|
reslog = ResultLog(StringIO.StringIO())
|
||||||
reslog.pyevent("internalerror", excinfo)
|
reslog.pyevent("internalerror", (excinfo,), {})
|
||||||
entry = reslog.logfile.getvalue()
|
entry = reslog.logfile.getvalue()
|
||||||
entry_lines = entry.splitlines()
|
entry_lines = entry.splitlines()
|
||||||
|
|
||||||
|
|
|
@ -194,7 +194,7 @@ class TerminalReporter:
|
||||||
self.stats.setdefault("skipped", []).append(event)
|
self.stats.setdefault("skipped", []).append(event)
|
||||||
self.write_fspath_result(event.colitem.fspath, "S")
|
self.write_fspath_result(event.colitem.fspath, "S")
|
||||||
|
|
||||||
def pyevent__testrunstart(self, event):
|
def pyevent__testrunstart(self):
|
||||||
self.write_sep("=", "test session starts", bold=True)
|
self.write_sep("=", "test session starts", bold=True)
|
||||||
self._sessionstarttime = py.std.time.time()
|
self._sessionstarttime = py.std.time.time()
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ class TestTerminal:
|
||||||
""")
|
""")
|
||||||
rep = TerminalReporter(modcol.config, file=linecomp.stringio)
|
rep = TerminalReporter(modcol.config, file=linecomp.stringio)
|
||||||
rep.config.bus.register(rep)
|
rep.config.bus.register(rep)
|
||||||
rep.config.bus.notify("testrunstart", event.TestrunStart())
|
rep.config.bus.notify("testrunstart")
|
||||||
|
|
||||||
for item in testdir.genitems([modcol]):
|
for item in testdir.genitems([modcol]):
|
||||||
ev = basic_run_report(item)
|
ev = basic_run_report(item)
|
||||||
|
@ -397,7 +397,7 @@ class TestTerminal:
|
||||||
""", configargs=("-v",))
|
""", configargs=("-v",))
|
||||||
rep = TerminalReporter(modcol.config, file=linecomp.stringio)
|
rep = TerminalReporter(modcol.config, file=linecomp.stringio)
|
||||||
rep.config.bus.register(rep)
|
rep.config.bus.register(rep)
|
||||||
rep.config.bus.notify("testrunstart", event.TestrunStart())
|
rep.config.bus.notify("testrunstart")
|
||||||
items = modcol.collect()
|
items = modcol.collect()
|
||||||
rep.config.option.debug = True #
|
rep.config.option.debug = True #
|
||||||
for item in items:
|
for item in items:
|
||||||
|
@ -422,7 +422,7 @@ class TestTerminal:
|
||||||
modcol = testdir.getmodulecol("import xyz")
|
modcol = testdir.getmodulecol("import xyz")
|
||||||
rep = TerminalReporter(modcol.config, file=linecomp.stringio)
|
rep = TerminalReporter(modcol.config, file=linecomp.stringio)
|
||||||
rep.config.bus.register(rep)
|
rep.config.bus.register(rep)
|
||||||
rep.config.bus.notify("testrunstart", event.TestrunStart())
|
rep.config.bus.notify("testrunstart")
|
||||||
l = list(testdir.genitems([modcol]))
|
l = list(testdir.genitems([modcol]))
|
||||||
assert len(l) == 0
|
assert len(l) == 0
|
||||||
linecomp.assert_contains_lines([
|
linecomp.assert_contains_lines([
|
||||||
|
@ -518,8 +518,8 @@ class TestTerminal:
|
||||||
""", configargs=("--tb=%s" % tbopt,))
|
""", configargs=("--tb=%s" % tbopt,))
|
||||||
rep = TerminalReporter(modcol.config, file=linecomp.stringio)
|
rep = TerminalReporter(modcol.config, file=linecomp.stringio)
|
||||||
rep.config.bus.register(rep)
|
rep.config.bus.register(rep)
|
||||||
rep.config.bus.notify("testrunstart", event.TestrunStart())
|
rep.config.bus.notify("testrunstart")
|
||||||
rep.config.bus.notify("testrunstart", event.TestrunStart())
|
rep.config.bus.notify("testrunstart")
|
||||||
for item in testdir.genitems([modcol]):
|
for item in testdir.genitems([modcol]):
|
||||||
rep.config.bus.notify("itemtestreport", basic_run_report(item))
|
rep.config.bus.notify("itemtestreport", basic_run_report(item))
|
||||||
rep.config.bus.notify("testrunfinish", event.TestrunFinish())
|
rep.config.bus.notify("testrunfinish", event.TestrunFinish())
|
||||||
|
@ -566,7 +566,7 @@ class TestTerminal:
|
||||||
rep = TerminalReporter(modcol.config, file=linecomp.stringio)
|
rep = TerminalReporter(modcol.config, file=linecomp.stringio)
|
||||||
modcol.config.bus.register(rep)
|
modcol.config.bus.register(rep)
|
||||||
bus = modcol.config.bus
|
bus = modcol.config.bus
|
||||||
bus.notify("testrunstart", event.TestrunStart())
|
bus.notify("testrunstart")
|
||||||
try:
|
try:
|
||||||
for item in testdir.genitems([modcol]):
|
for item in testdir.genitems([modcol]):
|
||||||
bus.notify("itemtestreport", basic_run_report(item))
|
bus.notify("itemtestreport", basic_run_report(item))
|
||||||
|
|
|
@ -79,7 +79,7 @@ class Session(object):
|
||||||
|
|
||||||
def sessionstarts(self):
|
def sessionstarts(self):
|
||||||
""" setup any neccessary resources ahead of the test run. """
|
""" setup any neccessary resources ahead of the test run. """
|
||||||
self.bus.notify("testrunstart", event.TestrunStart())
|
self.bus.notify("testrunstart")
|
||||||
|
|
||||||
def pyevent__itemtestreport(self, rep):
|
def pyevent__itemtestreport(self, rep):
|
||||||
if rep.failed:
|
if rep.failed:
|
||||||
|
|
|
@ -25,11 +25,11 @@ class SessionTests:
|
||||||
assert failed[0].colitem.name == "test_one_one"
|
assert failed[0].colitem.name == "test_one_one"
|
||||||
assert failed[1].colitem.name == "test_other"
|
assert failed[1].colitem.name == "test_other"
|
||||||
assert failed[2].colitem.name == "test_two"
|
assert failed[2].colitem.name == "test_two"
|
||||||
itemstarted = sorter.getnamed("itemstart")
|
itemstarted = sorter.getevents("itemstart")
|
||||||
assert len(itemstarted) == 4
|
assert len(itemstarted) == 4
|
||||||
colstarted = sorter.getnamed("collectionstart")
|
colstarted = sorter.getevents("collectionstart")
|
||||||
assert len(colstarted) == 1
|
assert len(colstarted) == 1
|
||||||
col = colstarted[0].collector
|
col = colstarted[0].event.collector
|
||||||
assert isinstance(col, py.test.collect.Module)
|
assert isinstance(col, py.test.collect.Module)
|
||||||
|
|
||||||
def test_nested_import_error(self, testdir):
|
def test_nested_import_error(self, testdir):
|
||||||
|
|
Loading…
Reference in New Issue