[py-svn] r51222 - in py/branch/event/py/test2: . rsession rsession/testing testing
hpk at codespeak.net
hpk at codespeak.net
Sat Feb 2 21:38:03 CET 2008
Author: hpk
Date: Sat Feb 2 21:38:02 2008
New Revision: 51222
Removed:
py/branch/event/py/test2/rsession/testing/test_master.py
Modified:
py/branch/event/py/test2/repevent.py
py/branch/event/py/test2/rsession/hostmanage.py
py/branch/event/py/test2/rsession/master.py
py/branch/event/py/test2/rsession/rsession.py
py/branch/event/py/test2/rsession/slave.py
py/branch/event/py/test2/rsession/testing/basetest.py
py/branch/event/py/test2/rsession/testing/test_hostmanage.py
py/branch/event/py/test2/rsession/testing/test_rsession.py
py/branch/event/py/test2/rsession/testing/test_slave.py
py/branch/event/py/test2/session.py
py/branch/event/py/test2/testing/test_itemgen.py
py/branch/event/py/test2/testing/test_outcome.py
py/branch/event/py/test2/testing/test_session2.py
Log:
* intermediate checkin (2 tests failing)
* sharing more code between dist and local sessions
* strike one layer of indirection
* remove some obscure and complicated (mostly skipped) tests
Modified: py/branch/event/py/test2/repevent.py
==============================================================================
--- py/branch/event/py/test2/repevent.py (original)
+++ py/branch/event/py/test2/repevent.py Sat Feb 2 21:38:02 2008
@@ -67,7 +67,6 @@
self.trail = trail
assert outcome in ("passed", "failed", "skipped")
setattr(self, outcome, True)
- self.outcome = outcome
self.info = info
# ----------------------------------------------------------------------
@@ -75,11 +74,9 @@
# ----------------------------------------------------------------------
class SendItem(BaseEvent):
- def __init__(self, channel, item):
+ def __init__(self, host, item):
self.item = item
- self.channel = channel
- if channel:
- self.host = channel.gateway.host
+ self.host = host
class HostRSyncing(BaseEvent):
def __init__(self, host, root, remotepath, synced):
@@ -97,12 +94,15 @@
self.host = host
self.roots = roots
+class HostDown(BaseEvent):
+ def __init__(self, host):
+ self.host = host
+
class HostRSyncRootReady(BaseEvent):
def __init__(self, host, root):
self.host = host
self.root = root
-
# ----------------------------------------------------------------------
# XXX Extra Events XXX
# ----------------------------------------------------------------------
Modified: py/branch/event/py/test2/rsession/hostmanage.py
==============================================================================
--- py/branch/event/py/test2/rsession/hostmanage.py (original)
+++ py/branch/event/py/test2/rsession/hostmanage.py Sat Feb 2 21:38:02 2008
@@ -1,7 +1,6 @@
import py
import sys, os
from py.__.test2.rsession.master import MasterNode
-from py.__.test2.rsession.slave import setup_slave
from py.__.test2 import repevent
class HostInfo(object):
@@ -157,43 +156,41 @@
def setup_hosts(self):
self.init_rsync()
- nodes = []
for host in self.hosts:
- if hasattr(host.gw, 'remote_exec'): # otherwise dummy for tests :/
- ch = setup_slave(host, self.config)
- nodes.append(MasterNode(ch, self.config.hub.notify))
- return nodes
-
- def teardown_hosts(self, nodes, timeout=1.0):
- return
- for node in nodes:
- node.channel.send(None)
- clean = False
- while not clean:
- clean = True
- for node in nodes:
- if node.pending:
- clean = False
- # XXX magic waiting
- py.std.time.sleep(0.1)
- self.teardown_gateways(nodes)
-
- def kill_channels(self, channels):
- for channel in channels:
- channel.send(42)
-
- def teardown_gateways(self, nodes):
- return
- self.config.hub.notify("teardown gateways %r" %(nodes,))
- for node in nodes:
- #try:
- try:
- node.channel.waitclose(1.0)
- except IOError: # timeout
- # force closing
- node.channel.close()
- node.channel.gateway.exit()
+ host.node = MasterNode(host, self.config)
+ def teardown_hosts(self, timeout=1.0):
+ # XXX teardown nodes and hosts
+ queue = py.std.Queue.Queue()
+ def hostdown(event):
+ if isinstance(event, repevent.HostDown):
+ queue.put(event)
+ self.config.hub.append(hostdown)
+
+ pending_hosts = []
+ for host in self.hosts:
+ if not host.node.channel.isclosed():
+ host.node.channel.send(None)
+ pending_hosts.append(host)
+
+ while pending_hosts:
+ event = queue.get(timeout=timeout)
+ if event.host not in pending_hosts:
+ print "got random HostDown of", event.host
+ else:
+ pending_hosts.remove(event.host)
+
+ def trysendtest(self, item):
+ for host in self.hosts:
+ node = getattr(host, 'node', None)
+ if node and len(node.pending) < 15: # XXX
+ node.send(item)
+ return True
+
+
+#
+# helpers
+#
def gethomedir():
import os
homedir = os.environ.get('HOME', '')
Modified: py/branch/event/py/test2/rsession/master.py
==============================================================================
--- py/branch/event/py/test2/rsession/master.py (original)
+++ py/branch/event/py/test2/rsession/master.py Sat Feb 2 21:38:02 2008
@@ -6,17 +6,19 @@
from py.__.test2 import repevent
class MasterNode(object):
- def __init__(self, channel, notify):
- self.notify = notify
- self.channel = channel
+ def __init__(self, host, config):
+ self.host = host
+ self.config = config
+ self.notify = config.hub.notify
+ self.channel = setup_slave(host, config)
+ self.channel.setcallback(self._callback)
self.pending = []
- channel.setcallback(self._callback)
- def _callback(self, outcome):
+ def _callback(self, outcomestring):
+ if outcomestring is None:
+ self.notify(repevent.HostDown(self.host))
+ return
item = self.pending.pop()
- self.receive_result(outcome, item)
-
- def receive_result(self, outcomestring, item):
repr_outcome = ReprOutcome(outcomestring)
# send finish report
# XXX the following should be done by outcome serializing
@@ -30,14 +32,12 @@
def send(self, item):
try:
- if item is StopIteration:
- self.channel.send(42)
+ if item is None:
+ self.channel.send(None)
else:
- self.pending.insert(0, item)
- #itemspec = item.listnames()[1:]
self.channel.send(item._get_collector_trail())
- # send start report
- self.notify(repevent.SendItem(self.channel, item))
+ self.pending.insert(0, item)
+ self.notify(repevent.SendItem(self.host, item))
except IOError:
print "Sending error, channel IOError"
print self.channel._getremoteerror()
@@ -45,23 +45,19 @@
# of hanging nodes and such
raise
-def dispatch_loop(masternodes, itemgenerator, #shouldstop,
- waiter = lambda: py.std.time.sleep(0.1),
- max_tasks_per_node=15):
- all_tests = {}
- while 1:
- try:
- for node in masternodes:
- if len(node.pending) < max_tasks_per_node:
- item = itemgenerator.next()
- all_tests[item] = True
- #if shouldstop():
- # for _node in masternodes:
- # _node.send(StopIteration) # magic connector
- # return None
- node.send(item)
- except StopIteration:
- break
- waiter()
- return all_tests
+# setting up slave code
+from slave import setup
+defaultconftestnames = ['dist_nicelevel']
+def setup_slave(host, config):
+ channel = host.gw.remote_exec(str(py.code.Source(setup, "setup()")))
+ configrepr = config._makerepr(defaultconftestnames)
+ #print "sending configrepr", configrepr
+ topdir = host.gw_remotepath
+ if topdir is None:
+ assert host.inplacelocal
+ topdir = config.topdir
+ channel.send(str(topdir))
+ channel.send(configrepr)
+ return channel
+
Modified: py/branch/event/py/test2/rsession/rsession.py
==============================================================================
--- py/branch/event/py/test2/rsession/rsession.py (original)
+++ py/branch/event/py/test2/rsession/rsession.py Sat Feb 2 21:38:02 2008
@@ -1,27 +1,22 @@
-
-""" Remote session base class
+"""
+ Remote Session Base Class
"""
import os
import py
-import sys
-import re
-import time
-from py.__.test2 import repevent
-from py.__.test2.rsession.master import dispatch_loop
+from py.__.test2.session import Session
from py.__.test2.rsession.hostmanage import HostManager
-from py.__.test2.session import AbstractSession, itemgen
-class RSession(AbstractSession):
- """ Remote version of session
+class RSession(Session):
+ """ Distributing tests to remote places.
"""
def fixoptions(self):
super(RSession, self).fixoptions()
option = self.config.option
if option.nocapture:
print "Cannot use nocapture with distributed testing"
- sys.exit(1)
+ py.std.sys.exit(1)
config = self.config
try:
config.getvalue('dist_hosts')
@@ -37,37 +32,20 @@
print "see also: http://codespeak.net/py/current/doc/test.html#automated-distributed-testing"
raise SystemExit
- def main(self):
- """ main loop for running tests. """
- hm = HostManager(self.config)
- hub = self.config.hub
- hub.notify(repevent.SessionStart(self))
- try:
- nodes = hm.setup_hosts()
- try:
- self.dispatch_tests(nodes)
- except (KeyboardInterrupt, SystemExit):
- print >>sys.stderr, "C-c pressed waiting for gateways to teardown..."
- channels = [node.channel for node in nodes]
- hm.kill_channels(channels)
- hm.teardown_gateways(channels)
- print >>sys.stderr, "... Done"
- raise
-
- print "tearing down nodes"
- hm.teardown_hosts(nodes)
- hub.notify(repevent.SessionFinish(self))
- except (KeyboardInterrupt, SystemExit):
- hub.notify(repevent.InterruptedExecution())
- raise
- except:
- hub.notify(repevent.CrashedExecution())
- raise
-
- def dispatch_tests(self, nodes):
- colitems = self.config.getcolitems()
- keyword = self.config.option.keyword
- itemgenerator = itemgen(self, colitems, keyword)
- max_tasks_per_node = self.config.getvalue("dist_taskspernode")
- all_tests = dispatch_loop(nodes, itemgenerator,
- max_tasks_per_node=max_tasks_per_node)
+ def setup(self):
+ super(RSession, self).setup()
+ self.hm = hm = HostManager(self.config)
+ self.hm.setup_hosts()
+
+ def teardown(self):
+ super(RSession, self).teardown()
+ self.hm.teardown_hosts()
+
+ def runtest(self, item):
+ # dispatch tests to host manager
+ sent = self.hm.trysendtest(item)
+ if not sent and not self.shouldstop:
+ self.sleepabit()
+
+ def sleepabit(self):
+ py.std.time.sleep(0.1)
Modified: py/branch/event/py/test2/rsession/slave.py
==============================================================================
--- py/branch/event/py/test2/rsession/slave.py (original)
+++ py/branch/event/py/test2/rsession/slave.py Sat Feb 2 21:38:02 2008
@@ -44,6 +44,7 @@
while 1:
nextitem = receive()
if nextitem is None:
+ send(None)
break
try:
node = getnode(nextitem)
@@ -54,28 +55,13 @@
excinfo = py.code.ExceptionInfo()
send(SerializableOutcome(excinfo=excinfo, is_critical=True).make_repr())
else:
+ send(res)
if not res[0] and not res[3] and config.option.exitfirst:
- # we're finished, but need to eat what we can
- send(res)
break
- send(res)
-
+ # we're finished, but we should eat what we can
while nextitem is not None:
nextitem = receive()
-defaultconftestnames = ['dist_nicelevel']
-def setup_slave(host, config):
- channel = host.gw.remote_exec(str(py.code.Source(setup, "setup()")))
- configrepr = config._makerepr(defaultconftestnames)
- #print "sending configrepr", configrepr
- topdir = host.gw_remotepath
- if topdir is None:
- assert host.inplacelocal
- topdir = config.topdir
- channel.send(str(topdir))
- channel.send(configrepr)
- return channel
-
def setup():
# our current dir is the topdir
import os, sys
Modified: py/branch/event/py/test2/rsession/testing/basetest.py
==============================================================================
--- py/branch/event/py/test2/rsession/testing/basetest.py (original)
+++ py/branch/event/py/test2/rsession/testing/basetest.py Sat Feb 2 21:38:02 2008
@@ -7,13 +7,13 @@
def func_source():
import py
import time
- def funcpass():
+ def funcpassed():
pass
- def funcfail():
+ def funcfailed():
raise AssertionError("hello world")
- def funcskip():
+ def funcskipped():
py.test2.skip("skipped")
def funcprint():
Modified: py/branch/event/py/test2/rsession/testing/test_hostmanage.py
==============================================================================
--- py/branch/event/py/test2/rsession/testing/test_hostmanage.py (original)
+++ py/branch/event/py/test2/rsession/testing/test_hostmanage.py Sat Feb 2 21:38:02 2008
@@ -268,6 +268,7 @@
print events
assert 0
+
def test_getpath_relto_home():
x = getpath_relto_home("hello")
assert x == py.path.local._gethomedir().join("hello")
Deleted: /py/branch/event/py/test2/rsession/testing/test_master.py
==============================================================================
--- /py/branch/event/py/test2/rsession/testing/test_master.py Sat Feb 2 21:38:02 2008
+++ (empty file)
@@ -1,198 +0,0 @@
-""" master code and test dispatching for
- making 1-n master -> slave connection
- and test it locally.
-"""
-
-import time, threading
-import py, sys
-
-if sys.platform == 'win32':
- py.test.skip("rsession is unsupported on Windows.")
-
-from py.__.test2.rsession.master import dispatch_loop, MasterNode
-from py.__.test2.rsession.slave import setup_slave
-from py.__.test2.outcome import ReprOutcome, SerializableOutcome
-from py.__.test2 import repevent
-from py.__.test2.rsession.hostmanage import HostInfo
-
-def setup_module(mod):
- # bind an empty config
- mod.tmpdir = tmpdir = py.test2.ensuretemp(mod.__name__)
- # to avoid rsyncing
- config = py.test2.config._reparse([tmpdir])
- config.option.dist_taskspernode = 10
- mod.rootcol = config._getcollector(tmpdir)
-
-class DummyGateway(object):
- def __init__(self):
- self.host = HostInfo("localhost")
-
-class DummyChannel(object):
- def __init__(self):
- self.sent = []
- self.gateway = DummyGateway()
-
- def setcallback(self, func):
- self.callback = func
-
- def send(self, item):
- assert py.std.marshal.dumps(item)
- self.sent.append(item)
-
-class NonWorkingChannel(object):
- def setcallback(self, func):
- pass
-
- def send(self, item):
- raise IOError
-
- def _getremoteerror(self):
- return "blah"
-
-class Item(py.test2.collect.Item):
- def _get_collector_trail(self):
- return (self.name,)
-
-def test_masternode():
- try:
- raise ValueError()
- except ValueError:
- excinfo = py.code.ExceptionInfo()
-
- ch = DummyChannel()
- reportlist = []
- mnode = MasterNode(ch, reportlist.append)
- mnode.send(Item("ok"))
- mnode.send(Item("notok"))
- ch.callback(SerializableOutcome().make_repr())
- ch.callback(SerializableOutcome(excinfo=excinfo).make_repr())
- assert len(reportlist) == 4
- received = [i for i in reportlist
- if isinstance(i, repevent.ItemTestReport)]
- py.test.skip("XXX fix master tests")
- assert received[0].outcome.passed
- assert not received[1].outcome.passed
-
-def test_masternode_nonworking_channel():
- ch = NonWorkingChannel()
- reportlist = []
- mnode = MasterNode(ch, reportlist.append)
- cap = py.io.StdCaptureFD()
- py.test2.raises(IOError, 'mnode.send(Item("ok"))')
- out, err = cap.reset()
- assert out.find("blah") != -1
-
-def test_sending_two_noes():
- # XXX fijal: this test previously tested that the second
- # item result would not get send. why? did i miss
- # something?
- #
- ch = DummyChannel()
- reportlist = []
- mnode = MasterNode(ch, reportlist.append)
- mnode.send(Item("ok"))
- mnode.send(Item("ok"))
- ch.callback(SerializableOutcome().make_repr())
- ch.callback(SerializableOutcome().make_repr())
- assert len(reportlist) == 4
-
-def test_outcome_repr():
- out = ReprOutcome(SerializableOutcome(skipped="xxx").make_repr())
- s = repr(out)
- assert s.lower().find("skip") != -1
-
-class DummyMasterNode(object):
- def __init__(self):
- self.pending = []
-
- def send(self, data):
- self.pending.append(data)
-
-def test_dispatch_loop():
- masternodes = [DummyMasterNode(), DummyMasterNode()]
- itemgenerator = iter(range(100))
- shouldstop = lambda : False
- def waiter():
- for node in masternodes:
- node.pending.pop()
- dispatch_loop(masternodes, itemgenerator, waiter=waiter)
-
-class TestSlave:
- def setup_class(cls):
- cls.tmpdir = tmpdir = py.test2.ensuretemp(cls.__name__)
- cls.pkgpath = pkgpath = tmpdir.join("slavetestpkg")
- pkgpath.ensure("__init__.py")
- pkgpath.join("test_something.py").write(py.code.Source("""
- def funcpass():
- pass
-
- def funcfail():
- raise AssertionError("hello world")
- """))
- cls.config = py.test2.config._reparse([tmpdir])
- assert cls.config.topdir == tmpdir
- cls.rootcol = cls.config._getcollector(tmpdir)
-
- def _gettrail(self, *names):
- item = self.rootcol._getitembynames(names)
- return self.config.get_collector_trail(item)
-
- def test_slave_running(self):
- py.test.skip("XXX test broken, needs refactoring")
- def simple_report(event):
- if not isinstance(event, repevent.ItemFinish):
- return
- item = event.item
- if item.code.name == 'funcpass':
- assert event.outcome.passed
- else:
- assert not event.outcome.passed
-
- def open_gw():
- gw = py.execnet.PopenGateway()
- host = HostInfo("localhost")
- host.gw_remotepath = ''
- host.gw = gw
- #gw.host.gw = gw
- config = py.test2.config._reparse([tmpdir])
- channel = setup_slave(host, config)
- mn = MasterNode(channel, simple_report)
- return mn
-
- master_nodes = [open_gw(), open_gw(), open_gw()]
- funcpass_item = self.xxx
- funcfail_item = rootcol._getitembynames(funcfail_spec)
- itemgenerator = iter([funcfail_item] +
- [funcpass_item] * 5 + [funcfail_item] * 5)
- shouldstop = lambda : False
- dispatch_loop(master_nodes, itemgenerator, shouldstop)
-
-def test_slave_running_interrupted():
- py.test.skip("XXX test broken, needs refactoring")
- #def simple_report(event):
- # if not isinstance(event, repevent.ItemFinish):
- # return
- # item = event.item
- # if item.code.name == 'funcpass':
- # assert event.outcome.passed
- # else:
- # assert not event.outcome.passed
- reports = []
-
- def open_gw():
- gw = py.execnet.PopenGateway()
- gw.host = HostInfo("localhost")
- gw.host.gw = gw
- config = py.test2.config._reparse([tmpdir])
- channel = setup_slave(gw.host, config)
- mn = MasterNode(channel, reports.append, {})
- return mn, gw, channel
-
- mn, gw, channel = open_gw()
- rootcol = py.test2.collect.Directory(pkgdir)
- funchang_item = rootcol._getitembynames(funchang_spec)
- mn.send(funchang_item)
- mn.send(StopIteration)
- # XXX: We have to wait here a bit to make sure that it really did happen
- channel.waitclose(2)
-
Modified: py/branch/event/py/test2/rsession/testing/test_rsession.py
==============================================================================
--- py/branch/event/py/test2/rsession/testing/test_rsession.py (original)
+++ py/branch/event/py/test2/rsession/testing/test_rsession.py Sat Feb 2 21:38:02 2008
@@ -37,9 +37,6 @@
"""))
config = py.test2.config._reparse([self.source.join("sub"), '-x'])
rsession = RSession(config)
- def f(ev):
- print ev
- config.hub.append(f)
allevents = getevents_runmain(rsession)
testevents = [x for x in allevents
if isinstance(x, repevent.ItemTestReport)]
@@ -92,29 +89,31 @@
queue = py.std.Queue.Queue()
self.config.hub.append(queue.put)
hm = HostManager(self.config, hosts=hosts)
- nodes = hm.setup_hosts()
+ hm.setup_hosts()
# actually run some tests
- for node in nodes:
- node.send(self.getexample("pass"))
- node.send(self.getexample("fail"))
- node.send(self.getexample("skip"))
+ for host in hm.hosts:
+ node = host.node
+ node.send(self.getexample("passed"))
+ node.send(self.getexample("failed"))
+ node.send(self.getexample("skipped"))
node.send(self.getexample("print"))
+ num_hosts = len(hm.hosts)
events = []
- while len(events) < 4 * len(nodes):
+ while len(events) < 4 * num_hosts:
item = queue.get(timeout=0.5)
if isinstance(item, repevent.ItemTestReport):
events.append(item)
print "got all events", events
- hm.teardown_hosts(nodes)
+ hm.teardown_hosts()
passed = [ev for ev in events
if ev.passed]
skipped = [ev for ev in events
if ev.skipped]
- assert len(passed) == 2 * len(nodes)
- assert len(skipped) == len(nodes)
- assert len(events) == 4 * len(nodes)
+ assert len(passed) == 2 * num_hosts
+ assert len(skipped) == num_hosts
+ assert len(events) == 4 * num_hosts
# one of passed for each node has non-empty stdout
#passed_stdout = [i for i in passed if i.outcome.stdout.find('samfing') != -1]
#assert len(passed_stdout) == len(nodes), passed
Modified: py/branch/event/py/test2/rsession/testing/test_slave.py
==============================================================================
--- py/branch/event/py/test2/rsession/testing/test_slave.py (original)
+++ py/branch/event/py/test2/rsession/testing/test_slave.py Sat Feb 2 21:38:02 2008
@@ -22,7 +22,7 @@
def test_slave_run_passing(self):
node = self.gettestnode()
- item = self.getexample("pass")
+ item = self.getexample("passed")
outcome = node.execute(item._get_collector_trail())
assert outcome.passed
assert not outcome.setupfailure
@@ -34,12 +34,12 @@
def test_slave_run_failing(self):
node = self.gettestnode()
- item = self.getexample("fail")
+ item = self.getexample("failed")
outcome = node.execute(item._get_collector_trail())
assert not outcome.passed
assert not outcome.setupfailure
assert len(outcome.excinfo.traceback) == 1
- assert outcome.excinfo.traceback[-1].frame.code.name == 'funcfail'
+ assert outcome.excinfo.traceback[-1].frame.code.name == 'funcfailed'
ser = outcome.make_repr()
reproutcome = ReprOutcome(ser)
@@ -49,7 +49,7 @@
def test_slave_run_skipping(self):
node = self.gettestnode()
- item = self.getexample("skip")
+ item = self.getexample("skipped")
outcome = node.execute(item._get_collector_trail())
assert not outcome.passed
assert outcome.skipped
@@ -61,7 +61,7 @@
def test_slave_run_failing_wrapped(self):
node = self.gettestnode()
- item = self.getexample("fail")
+ item = self.getexample("failed")
repr_outcome = node.run(item._get_collector_trail())
outcome = ReprOutcome(repr_outcome)
assert not outcome.passed
Modified: py/branch/event/py/test2/session.py
==============================================================================
--- py/branch/event/py/test2/session.py (original)
+++ py/branch/event/py/test2/session.py Sat Feb 2 21:38:02 2008
@@ -12,38 +12,13 @@
GeneratorExit = py.builtin.GeneratorExit
-def itemgen(session, colitems, keywordexpr=None):
- hub = session.config.hub
- stopitems = py.test2.collect.Item # XXX should be generator here as well
- while colitems:
- next = colitems.pop(0)
- if isinstance(next, stopitems):
- if next._skipbykeyword(keywordexpr):
- hub.notify(repevent.DeselectedTest(next, keywordexpr))
- if session.config.option.keyword_oneshot:
- keywordexpr = None
- else:
- yield next
- else:
- hub.notify(repevent.CollectionStart(next))
- try:
- cols = [next.join(x) for x in next.run()]
- for x in itemgen(session, cols, keywordexpr):
- yield x
- except (KeyboardInterrupt, SystemExit, GeneratorExit):
- raise
- except:
- excinfo = py.code.ExceptionInfo()
- hub.notify(repevent.CollectionFinish(next, excinfo))
- else:
- hub.notify(repevent.CollectionFinish(next))
-
-class AbstractSession(object):
- """ An abstract session executes collectors/items through a runner.
- """
+class Session(object):
+ """
+ Session drives the collection and running of tests
+ and generates test events for reporters.
+ """
def __init__(self, config):
self.config = config
- self._keyword = config.option.keyword
def fixoptions(self):
""" check, fix and determine conflicting options. """
@@ -60,64 +35,87 @@
raise ValueError, "--looponfailing together with --dist not supported."
if option.executable and option.usepdb:
raise ValueError, "--exec together with --pdb not supported."
-
if option.keyword_oneshot and not option.keyword:
raise ValueError, "--keyword-oneshot makes sense only when --keyword is supplied"
-class Session(AbstractSession):
- """
- A Session gets test Items from Collectors, executes the
- Items and sends the Outcome to the Reporter.
- """
- def shouldclose(self):
- return False
+ def collect(self):
+ colitems = self.config.getcolitems()
+ keyword = self.config.option.keyword
+ for x in self.genitems(colitems, keyword):
+ yield x
- def header(self, colitems):
+ def genitems(self, colitems, keywordexpr=None):
+ hub = self.config.hub
+ stopitems = py.test2.collect.Item
+ while colitems:
+ next = colitems.pop(0)
+ if isinstance(next, stopitems):
+ if next._skipbykeyword(keywordexpr):
+ hub.notify(repevent.DeselectedTest(next, keywordexpr))
+ if self.config.option.keyword_oneshot:
+ keywordexpr = None
+ else:
+ yield next
+ else:
+ hub.notify(repevent.CollectionStart(next))
+ excinfo = None
+ try:
+ cols = [next.join(x) for x in next.run()]
+ for x in self.genitems(cols, keywordexpr):
+ yield x
+ except (KeyboardInterrupt, SystemExit, GeneratorExit):
+ raise
+ except:
+ excinfo = py.code.ExceptionInfo()
+ hub.notify(repevent.CollectionFinish(next, excinfo))
+
+ def setup(self):
""" setup any neccessary resources ahead of the test run. """
- self.config.hub.notify(repevent.SessionStart(self))
if not self.config.option.nomagic:
py.magic.invoke(assertion=1)
+ self._failurelist = self._initfailurelist()
- def footer(self, colitems):
+ def teardown(self):
""" teardown any resources after a test run. """
py.test2.collect.Function._state.teardown_all()
if not self.config.option.nomagic:
py.magic.revoke(assertion=1)
- self.config.hub.notify(repevent.SessionFinish(self))
-
+ return self._failurelist
+
+ def _initfailurelist(self):
+ failurelist = []
+ def processfailures(event):
+ if isinstance(event, repevent.ItemFinish) and event.failed:
+ failurelist.append(event)
+ if self.config.option.exitfirst:
+ self.shouldstop = True
+ self.config.hub.append(processfailures)
+ return failurelist
+
def main(self):
""" main loop for running tests. """
- config = self.config
- colitems = self.config.getcolitems()
- self.header(colitems)
- keyword = self.config.option.keyword
- itemgenerator = itemgen(self, colitems, keyword)
- failures = []
+ self.shouldstop = False
+ self.setup()
+ self.config.hub.notify(repevent.SessionStart(self))
try:
- while 1:
- try:
- item = itemgenerator.next()
- if not self.config.option.collectonly:
- outcome = self.run(item)
- self.config.hub.notify(repevent.ItemFinish(item, outcome.excinfo))
- if outcome is not None:
- if not outcome.passed and not outcome.skipped:
- failures.append((item, outcome))
- if self.config.option.exitfirst:
- raise StopIteration()
- except StopIteration:
- break
+ for item in self.collect():
+ if self.shouldstop:
+ break
+ if not self.config.option.collectonly:
+ self.runtest(item)
finally:
- self.footer(colitems)
+ failures = self.teardown()
+ self.config.hub.notify(repevent.SessionFinish(self))
return failures
- def run(self, item):
+ def runtest(self, item):
if not self.config.option.boxed:
executor = RunExecutor(item, config=self.config)
- return ReprOutcome(executor.execute().make_repr())
+ outcome = ReprOutcome(executor.execute().make_repr())
else:
executor = BoxExecutor(item, config=self.config)
- return ReprOutcome(executor.execute())
+ outcome = ReprOutcome(executor.execute())
+ self.config.hub.notify(repevent.ItemFinish(item, outcome.excinfo))
class Exit(Exception):
""" for immediate program exits without tracebacks and reporter/summary. """
Modified: py/branch/event/py/test2/testing/test_itemgen.py
==============================================================================
--- py/branch/event/py/test2/testing/test_itemgen.py (original)
+++ py/branch/event/py/test2/testing/test_itemgen.py Sat Feb 2 21:38:02 2008
@@ -1,6 +1,5 @@
import py
-from py.__.test2.session import itemgen
from py.__.test2 import repevent
class TestItemgen:
Modified: py/branch/event/py/test2/testing/test_outcome.py
==============================================================================
--- py/branch/event/py/test2/testing/test_outcome.py (original)
+++ py/branch/event/py/test2/testing/test_outcome.py Sat Feb 2 21:38:02 2008
@@ -62,3 +62,9 @@
#def test_f3():
# f3()
+
+def test_outcome_repr():
+ out = ReprOutcome(SerializableOutcome(skipped="xxx").make_repr())
+ s = repr(out)
+ assert s.lower().find("skip") != -1
+
Modified: py/branch/event/py/test2/testing/test_session2.py
==============================================================================
--- py/branch/event/py/test2/testing/test_session2.py (original)
+++ py/branch/event/py/test2/testing/test_session2.py Sat Feb 2 21:38:02 2008
@@ -11,12 +11,15 @@
def getevents_runmain(session):
hub = session.config.hub
allevents = []
- hub.append(allevents.append)
+ def appendevent(event):
+ allevents.append(event)
+ print event
+ hub.append(appendevent)
try:
session.main()
return allevents
finally:
- hub.remove(allevents.append)
+ hub.remove(appendevent)
def setup_module(mod):
More information about the pytest-commit
mailing list