132 lines
4.5 KiB
Python
132 lines
4.5 KiB
Python
import py
|
|
|
|
class Session(object):
|
|
"""
|
|
A Session gets test Items from Collectors, # executes the
|
|
Items and sends the Outcome to the Reporter.
|
|
"""
|
|
def __init__(self, config):
|
|
self._memo = []
|
|
self.config = config
|
|
|
|
def shouldclose(self):
|
|
return False
|
|
|
|
def header(self, colitems):
|
|
""" setup any neccessary resources ahead of the test run. """
|
|
if not self.config.option.nomagic:
|
|
py.magic.invoke(assertion=1)
|
|
|
|
def footer(self, colitems):
|
|
""" teardown any resources after a test run. """
|
|
py.test.Function.state.teardown_all()
|
|
if not self.config.option.nomagic:
|
|
py.magic.revoke(assertion=1)
|
|
|
|
def fixoptions(self):
|
|
""" check, fix and determine conflicting options. """
|
|
option = self.config.option
|
|
# implied options
|
|
if option.usepdb:
|
|
if not option.nocapture:
|
|
option.nocapture = True
|
|
# conflicting options
|
|
if option.looponfailing and option.usepdb:
|
|
raise ValueError, "--looponfailing together with --pdb not supported."
|
|
if option.looponfailing and option.dist:
|
|
raise ValueError, "--looponfailing together with --dist not supported."
|
|
if option.executable and option.usepdb:
|
|
raise ValueError, "--exec together with --pdb not supported."
|
|
|
|
def start(self, colitem):
|
|
""" hook invoked before each colitem.run() invocation. """
|
|
|
|
def finish(self, colitem, outcome):
|
|
""" hook invoked after each colitem.run() invocation. """
|
|
self._memo.append((colitem, outcome))
|
|
|
|
def startiteration(self, colitem, subitems):
|
|
pass
|
|
|
|
def getitemoutcomepairs(self, cls):
|
|
return [x for x in self._memo if isinstance(x[1], cls)]
|
|
|
|
def main(self):
|
|
""" main loop for running tests. """
|
|
colitems = self.config.getcolitems()
|
|
try:
|
|
self.header(colitems)
|
|
try:
|
|
try:
|
|
for colitem in colitems:
|
|
self.runtraced(colitem)
|
|
except KeyboardInterrupt:
|
|
raise
|
|
finally:
|
|
self.footer(colitems)
|
|
except Exit, ex:
|
|
pass
|
|
|
|
def runtraced(self, colitem):
|
|
if self.shouldclose():
|
|
raise Exit, "received external close signal"
|
|
|
|
outcome = None
|
|
colitem.startcapture()
|
|
try:
|
|
self.start(colitem)
|
|
try:
|
|
try:
|
|
if colitem._stickyfailure:
|
|
raise colitem._stickyfailure
|
|
outcome = self.run(colitem)
|
|
except (KeyboardInterrupt, Exit):
|
|
raise
|
|
except colitem.Outcome, outcome:
|
|
if outcome.excinfo is None:
|
|
outcome.excinfo = py.code.ExceptionInfo()
|
|
except:
|
|
excinfo = py.code.ExceptionInfo()
|
|
outcome = colitem.Failed(excinfo=excinfo)
|
|
assert (outcome is None or
|
|
isinstance(outcome, (list, colitem.Outcome)))
|
|
finally:
|
|
self.finish(colitem, outcome)
|
|
if isinstance(outcome, colitem.Failed) and self.config.option.exitfirst:
|
|
py.test.exit("exit on first problem configured.", item=colitem)
|
|
finally:
|
|
colitem.finishcapture()
|
|
|
|
def run(self, colitem):
|
|
if self.config.option.collectonly and isinstance(colitem, py.test.Item):
|
|
return
|
|
if isinstance(colitem, py.test.Item):
|
|
colitem.skipbykeyword(self.config.option.keyword)
|
|
res = colitem.run()
|
|
if res is None:
|
|
return py.test.Item.Passed()
|
|
elif not isinstance(res, (list, tuple)):
|
|
raise TypeError("%r.run() returned neither "
|
|
"list, tuple nor None: %r" % (colitem, res))
|
|
else:
|
|
finish = self.startiteration(colitem, res)
|
|
try:
|
|
for name in res:
|
|
obj = colitem.join(name)
|
|
assert obj is not None
|
|
self.runtraced(obj)
|
|
finally:
|
|
if finish:
|
|
finish()
|
|
return res
|
|
|
|
class Exit(Exception):
|
|
""" for immediate program exits without tracebacks and reporter/summary. """
|
|
def __init__(self, msg="unknown reason", item=None):
|
|
self.msg = msg
|
|
Exception.__init__(self, msg)
|
|
|
|
def exit(msg, item=None):
|
|
raise Exit(msg=msg, item=item)
|
|
|