2008-08-16 23:26:59 +08:00
|
|
|
""" basic test session implementation.
|
|
|
|
|
|
|
|
* drives collection of tests
|
|
|
|
* triggers executions of tests
|
|
|
|
* produces events used by reporting
|
|
|
|
"""
|
|
|
|
|
|
|
|
import py
|
|
|
|
from py.__.test import event, outcome
|
|
|
|
|
2009-02-27 18:18:27 +08:00
|
|
|
# imports used for genitems()
|
|
|
|
Item = py.test.collect.Item
|
|
|
|
Collector = py.test.collect.Collector
|
2008-08-16 23:26:59 +08:00
|
|
|
from runner import basic_collect_report
|
|
|
|
|
|
|
|
class Session(object):
|
|
|
|
"""
|
|
|
|
Session drives the collection and running of tests
|
|
|
|
and generates test events for reporters.
|
|
|
|
"""
|
|
|
|
def __init__(self, config):
|
|
|
|
self.config = config
|
2009-02-27 18:18:27 +08:00
|
|
|
self.bus = config.bus # shortcut
|
|
|
|
self.bus.register(self)
|
|
|
|
self._testsfailed = False
|
2008-08-16 23:26:59 +08:00
|
|
|
self._nomatch = False
|
2009-03-17 15:40:39 +08:00
|
|
|
self.shouldstop = False
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
def genitems(self, colitems, keywordexpr=None):
|
|
|
|
""" yield Items from iterating over the given colitems. """
|
|
|
|
while colitems:
|
|
|
|
next = colitems.pop(0)
|
2009-02-27 18:18:27 +08:00
|
|
|
if isinstance(next, (tuple, list)):
|
|
|
|
colitems[:] = list(next) + colitems
|
|
|
|
continue
|
2009-03-18 07:48:07 +08:00
|
|
|
assert self.bus is next.config.bus
|
2009-02-27 18:18:27 +08:00
|
|
|
notify = self.bus.notify
|
2008-08-16 23:26:59 +08:00
|
|
|
if isinstance(next, Item):
|
|
|
|
remaining = self.filteritems([next])
|
|
|
|
if remaining:
|
2009-03-21 10:04:44 +08:00
|
|
|
notify("itemstart", next)
|
2008-08-16 23:26:59 +08:00
|
|
|
yield next
|
|
|
|
else:
|
|
|
|
assert isinstance(next, Collector)
|
2009-04-03 23:47:16 +08:00
|
|
|
notify("collectionstart", next)
|
2008-08-16 23:26:59 +08:00
|
|
|
ev = basic_collect_report(next)
|
|
|
|
if ev.passed:
|
|
|
|
for x in self.genitems(ev.result, keywordexpr):
|
|
|
|
yield x
|
2009-02-27 18:18:27 +08:00
|
|
|
notify("collectionreport", ev)
|
2009-03-17 15:35:58 +08:00
|
|
|
if self.shouldstop:
|
|
|
|
break
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
def filteritems(self, colitems):
|
|
|
|
""" return items to process (some may be deselected)"""
|
|
|
|
keywordexpr = self.config.option.keyword
|
|
|
|
if not keywordexpr or self._nomatch:
|
|
|
|
return colitems
|
|
|
|
if keywordexpr[-1] == ":":
|
|
|
|
keywordexpr = keywordexpr[:-1]
|
|
|
|
remaining = []
|
|
|
|
deselected = []
|
|
|
|
for colitem in colitems:
|
|
|
|
if isinstance(colitem, Item):
|
|
|
|
if colitem._skipbykeyword(keywordexpr):
|
|
|
|
deselected.append(colitem)
|
|
|
|
continue
|
|
|
|
remaining.append(colitem)
|
|
|
|
if deselected:
|
2009-04-03 23:47:16 +08:00
|
|
|
self.bus.notify("deselected", deselected)
|
2008-08-16 23:26:59 +08:00
|
|
|
if self.config.option.keyword.endswith(":"):
|
|
|
|
self._nomatch = True
|
|
|
|
return remaining
|
|
|
|
|
|
|
|
def collect(self, colitems):
|
|
|
|
keyword = self.config.option.keyword
|
|
|
|
for x in self.genitems(colitems, keyword):
|
|
|
|
yield x
|
|
|
|
|
|
|
|
def sessionstarts(self):
|
|
|
|
""" setup any neccessary resources ahead of the test run. """
|
2009-04-03 18:57:34 +08:00
|
|
|
self.bus.notify("testrunstart")
|
2009-02-27 18:18:27 +08:00
|
|
|
|
2009-04-03 01:58:51 +08:00
|
|
|
def pyevent__itemtestreport(self, rep):
|
2009-02-27 18:18:27 +08:00
|
|
|
if rep.failed:
|
|
|
|
self._testsfailed = True
|
|
|
|
if self.config.option.exitfirst:
|
|
|
|
self.shouldstop = True
|
2009-04-03 01:58:51 +08:00
|
|
|
pyevent__collectionreport = pyevent__itemtestreport
|
2008-08-16 23:26:59 +08:00
|
|
|
|
2008-09-13 04:35:18 +08:00
|
|
|
def sessionfinishes(self, exitstatus=0, excinfo=None):
|
2008-08-16 23:26:59 +08:00
|
|
|
""" teardown any resources after a test run. """
|
2009-02-27 18:18:27 +08:00
|
|
|
self.bus.notify("testrunfinish",
|
2009-04-03 20:18:25 +08:00
|
|
|
exitstatus=exitstatus,
|
|
|
|
excrepr=excinfo and excinfo.getrepr() or None)
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
def getinitialitems(self, colitems):
|
|
|
|
if colitems is None:
|
|
|
|
colitems = [self.config.getfsnode(arg)
|
|
|
|
for arg in self.config.args]
|
|
|
|
return colitems
|
|
|
|
|
|
|
|
def main(self, colitems=None):
|
|
|
|
""" main loop for running tests. """
|
|
|
|
colitems = self.getinitialitems(colitems)
|
|
|
|
self.shouldstop = False
|
|
|
|
self.sessionstarts()
|
2009-03-21 03:04:36 +08:00
|
|
|
#self.bus.notify("testnodeready", maketestnodeready())
|
2008-08-16 23:26:59 +08:00
|
|
|
exitstatus = outcome.EXIT_OK
|
2008-09-13 04:35:18 +08:00
|
|
|
captured_excinfo = None
|
2008-08-16 23:26:59 +08:00
|
|
|
try:
|
|
|
|
for item in self.collect(colitems):
|
|
|
|
if self.shouldstop:
|
|
|
|
break
|
|
|
|
if not self.config.option.collectonly:
|
|
|
|
self.runtest(item)
|
2009-02-27 18:18:27 +08:00
|
|
|
|
2009-03-06 05:10:18 +08:00
|
|
|
self.config._setupstate.teardown_all()
|
2008-08-16 23:26:59 +08:00
|
|
|
except KeyboardInterrupt:
|
2008-09-13 04:35:18 +08:00
|
|
|
captured_excinfo = py.code.ExceptionInfo()
|
2008-08-16 23:26:59 +08:00
|
|
|
exitstatus = outcome.EXIT_INTERRUPTED
|
|
|
|
except:
|
2009-02-27 18:18:27 +08:00
|
|
|
captured_excinfo = py.code.ExceptionInfo()
|
2009-04-03 22:18:47 +08:00
|
|
|
self.config.pytestplugins.notify_exception(captured_excinfo)
|
2008-08-16 23:26:59 +08:00
|
|
|
exitstatus = outcome.EXIT_INTERNALERROR
|
2009-02-27 18:18:27 +08:00
|
|
|
if exitstatus == 0 and self._testsfailed:
|
2008-08-16 23:26:59 +08:00
|
|
|
exitstatus = outcome.EXIT_TESTSFAILED
|
2008-09-13 04:35:18 +08:00
|
|
|
self.sessionfinishes(exitstatus=exitstatus, excinfo=captured_excinfo)
|
2008-08-16 23:26:59 +08:00
|
|
|
return exitstatus
|
|
|
|
|
|
|
|
def runpdb(self, excinfo):
|
2009-02-27 18:18:27 +08:00
|
|
|
from py.__.test.custompdb import post_mortem
|
|
|
|
post_mortem(excinfo._excinfo[2])
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
def runtest(self, item):
|
|
|
|
pdb = self.config.option.usepdb and self.runpdb or None
|
2009-04-04 05:18:41 +08:00
|
|
|
report = item.config.pytestplugins.do_itemrun(item, pdb=pdb)
|
|
|
|
self.bus.notify("itemtestreport", report)
|