[svn r51033] merging of svn+ssh://codespeak.net/svn/py/branch/reporter-merge/py/test/session.py
revisions 47584 to 51032: ------------------------------------------------------------------------ r51030 | hpk | 2008-01-25 14:30:54 +0100 (Fri, 25 Jan 2008) | 5 lines fixing test and restoring the functionality that session.main returns a list of failures (py.test --exec=python should work again) ------------------------------------------------------------------------ r50984 | hpk | 2008-01-24 18:27:06 +0100 (Thu, 24 Jan 2008) | 1 line avoid reporting hooks on session object ------------------------------------------------------------------------ r49391 | fijal | 2007-12-05 17:33:05 +0100 (Wed, 05 Dec 2007) | 2 lines Don't cache results. ------------------------------------------------------------------------ r48698 | fijal | 2007-11-15 01:31:42 +0100 (Thu, 15 Nov 2007) | 2 lines Uh. 2.4 compatibility ------------------------------------------------------------------------ r48318 | fijal | 2007-11-05 16:47:34 +0100 (Mon, 05 Nov 2007) | 3 lines Seems that --pdb don't need to imply -s and worked out of the box. I've got no idea how to test it though :-/ ------------------------------------------------------------------------ r48140 | fijal | 2007-10-28 19:43:21 +0100 (Sun, 28 Oct 2007) | 2 lines Reintroduce boxing ------------------------------------------------------------------------ r48138 | fijal | 2007-10-28 19:22:42 +0100 (Sun, 28 Oct 2007) | 2 lines Share more code. ------------------------------------------------------------------------ r48130 | fijal | 2007-10-28 14:58:42 +0100 (Sun, 28 Oct 2007) | 2 lines Add --collectonly handling, new style, logic separated ------------------------------------------------------------------------ r48129 | fijal | 2007-10-28 14:41:06 +0100 (Sun, 28 Oct 2007) | 2 lines Refactor LocalReporter not to rely on hosts being there ------------------------------------------------------------------------ r48128 | fijal | 2007-10-28 14:24:41 +0100 (Sun, 28 Oct 2007) | 2 lines Small regactoring for simple usage of default reporter class ------------------------------------------------------------------------ r48127 | fijal | 2007-10-28 12:56:41 +0100 (Sun, 28 Oct 2007) | 2 lines Remove terminal session as it's no longer needed ------------------------------------------------------------------------ r48126 | fijal | 2007-10-28 12:48:35 +0100 (Sun, 28 Oct 2007) | 2 lines Some real test for itemgen ------------------------------------------------------------------------ r47678 | fijal | 2007-10-21 18:43:54 +0200 (Sun, 21 Oct 2007) | 2 lines Make even less things working. ------------------------------------------------------------------------ r47667 | fijal | 2007-10-21 13:00:20 +0200 (Sun, 21 Oct 2007) | 4 lines Huge refactoring, the target is unification of session reporters and eventually sessions. Right now there is about 200 lines of code cut, but there is still some code to die and also some features missing :) ------------------------------------------------------------------------ r47660 | fijal | 2007-10-21 00:02:04 +0200 (Sun, 21 Oct 2007) | 2 lines Create a new branch for reporter merge ------------------------------------------------------------------------ --HG-- branch : trunk
This commit is contained in:
parent
b7c0d84ee3
commit
192a890435
|
@ -0,0 +1,165 @@
|
|||
import py
|
||||
import sys
|
||||
from py.__.test.outcome import Outcome, Failed, Passed, Skipped
|
||||
from py.__.test.reporter import choose_reporter, TestReporter
|
||||
from py.__.test import repevent
|
||||
from py.__.test.outcome import SerializableOutcome, ReprOutcome
|
||||
from py.__.test.reporter import LocalReporter
|
||||
from py.__.test.executor import RunExecutor, BoxExecutor
|
||||
|
||||
""" The session implementation - reporter version:
|
||||
|
||||
* itemgen is responsible for iterating and telling reporter
|
||||
about skipped and failed iterations (this is for collectors only),
|
||||
this should be probably moved to session (for uniformity)
|
||||
* session gets items which needs to be executed one after another
|
||||
and tells reporter about that
|
||||
"""
|
||||
|
||||
try:
|
||||
GeneratorExit
|
||||
except NameError:
|
||||
GeneratorExit = StopIteration # I think
|
||||
|
||||
def itemgen(session, colitems, reporter, keyword=None):
|
||||
stopitems = py.test.collect.Item # XXX should be generator here as well
|
||||
while 1:
|
||||
if not colitems:
|
||||
break
|
||||
next = colitems.pop(0)
|
||||
if reporter:
|
||||
reporter(repevent.ItemStart(next))
|
||||
|
||||
if isinstance(next, stopitems):
|
||||
try:
|
||||
next._skipbykeyword(keyword)
|
||||
yield next
|
||||
except Skipped:
|
||||
if session.config.option.keyword_oneshot:
|
||||
keyword = None
|
||||
excinfo = py.code.ExceptionInfo()
|
||||
reporter(repevent.SkippedTryiter(excinfo, next))
|
||||
else:
|
||||
try:
|
||||
cols = [next.join(x) for x in next.run()]
|
||||
for x in itemgen(session, cols, reporter, keyword):
|
||||
yield x
|
||||
except (KeyboardInterrupt, SystemExit, GeneratorExit):
|
||||
raise
|
||||
except:
|
||||
excinfo = py.code.ExceptionInfo()
|
||||
if excinfo.type is Skipped:
|
||||
reporter(repevent.SkippedTryiter(excinfo, next))
|
||||
else:
|
||||
reporter(repevent.FailedTryiter(excinfo, next))
|
||||
if reporter:
|
||||
reporter(repevent.ItemFinish(next))
|
||||
|
||||
class AbstractSession(object):
|
||||
""" An abstract session executes collectors/items through a runner.
|
||||
"""
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
self._keyword = config.option.keyword
|
||||
|
||||
def fixoptions(self):
|
||||
""" check, fix and determine conflicting options. """
|
||||
option = self.config.option
|
||||
if option.runbrowser and not option.startserver:
|
||||
#print "--runbrowser implies --startserver"
|
||||
option.startserver = True
|
||||
if self.config.getvalue("dist_boxed") and option.dist:
|
||||
option.boxed = 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."
|
||||
|
||||
if option.keyword_oneshot and not option.keyword:
|
||||
raise ValueError, "--keyword-oneshot makes sense only when --keyword is supplied"
|
||||
|
||||
def init_reporter(self, reporter, config, hosts):
|
||||
if reporter is None:
|
||||
reporter = choose_reporter(self.reporterclass, config)\
|
||||
(config, hosts)
|
||||
else:
|
||||
reporter = TestReporter(reporter)
|
||||
checkfun = lambda : self.config.option.exitfirst and \
|
||||
reporter.was_failure()
|
||||
return reporter, checkfun
|
||||
|
||||
class Session(AbstractSession):
|
||||
"""
|
||||
A Session gets test Items from Collectors, executes the
|
||||
Items and sends the Outcome to the Reporter.
|
||||
"""
|
||||
reporterclass = LocalReporter
|
||||
|
||||
def shouldclose(self):
|
||||
return False
|
||||
|
||||
def header(self, colitems):
|
||||
""" setup any neccessary resources ahead of the test run. """
|
||||
self.reporter(repevent.TestStarted(None, self.config,
|
||||
None))
|
||||
if not self.config.option.nomagic:
|
||||
py.magic.invoke(assertion=1)
|
||||
|
||||
def footer(self, colitems):
|
||||
""" teardown any resources after a test run. """
|
||||
py.test.collect.Function._state.teardown_all()
|
||||
if not self.config.option.nomagic:
|
||||
py.magic.revoke(assertion=1)
|
||||
self.reporter(repevent.TestFinished())
|
||||
|
||||
def main(self, reporter=None):
|
||||
""" main loop for running tests. """
|
||||
config = self.config
|
||||
self.reporter, shouldstop = self.init_reporter(reporter, config, None)
|
||||
|
||||
colitems = self.config.getcolitems()
|
||||
self.header(colitems)
|
||||
keyword = self.config.option.keyword
|
||||
reporter = self.reporter
|
||||
itemgenerator = itemgen(self, colitems, reporter, keyword)
|
||||
failures = []
|
||||
try:
|
||||
while 1:
|
||||
try:
|
||||
item = itemgenerator.next()
|
||||
if shouldstop():
|
||||
return
|
||||
outcome = self.run(item)
|
||||
if outcome is not None:
|
||||
if not outcome.passed and not outcome.skipped:
|
||||
failures.append((item, outcome))
|
||||
reporter(repevent.ReceivedItemOutcome(None, item, outcome))
|
||||
except StopIteration:
|
||||
break
|
||||
finally:
|
||||
self.footer(colitems)
|
||||
return failures
|
||||
return self.getitemoutcomepairs(Failed)
|
||||
|
||||
def run(self, item):
|
||||
if not self.config.option.boxed:
|
||||
executor = RunExecutor(item, self.config.option.usepdb,
|
||||
self.reporter, self.config)
|
||||
return ReprOutcome(executor.execute().make_repr())
|
||||
else:
|
||||
executor = BoxExecutor(item, self.config.option.usepdb,
|
||||
self.reporter, self.config)
|
||||
return ReprOutcome(executor.execute())
|
||||
|
||||
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)
|
||||
|
Loading…
Reference in New Issue