rework session instantiation and exitstatus handling

--HG--
branch : trunk
This commit is contained in:
holger krekel 2010-09-28 12:59:48 +02:00
parent 2718fccfa0
commit f779d3f863
6 changed files with 41 additions and 39 deletions

View File

@ -109,7 +109,7 @@ def pytest_runtest_protocol(item):
""" implement fixture, run and report about the given test item. """ """ implement fixture, run and report about the given test item. """
pytest_runtest_protocol.firstresult = True pytest_runtest_protocol.firstresult = True
def pytest_runtest_logstart(nodeid, location): def pytest_runtest_logstart(nodeid, location, fspath):
""" signal the start of a test run. """ """ signal the start of a test run. """
def pytest_runtest_setup(item): def pytest_runtest_setup(item):
@ -133,7 +133,7 @@ def pytest__teardown_final(session):
""" called before test session finishes. """ """ called before test session finishes. """
pytest__teardown_final.firstresult = True pytest__teardown_final.firstresult = True
def pytest__teardown_final_logerror(report): def pytest__teardown_final_logerror(report, session):
""" called if runtest_teardown_final failed. """ """ called if runtest_teardown_final failed. """
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------

View File

@ -27,7 +27,8 @@ def pytest_sessionfinish(session, exitstatus):
hook = session.config.hook hook = session.config.hook
rep = hook.pytest__teardown_final(session=session) rep = hook.pytest__teardown_final(session=session)
if rep: if rep:
hook.pytest__teardown_final_logerror(report=rep) hook.pytest__teardown_final_logerror(session=session, report=rep)
session.exitstatus = 1
class NodeInfo: class NodeInfo:
def __init__(self, nodeid, nodenames, fspath, location): def __init__(self, nodeid, nodenames, fspath, location):
@ -52,7 +53,8 @@ def pytest_runtest_protocol(item):
nodeinfo = getitemnodeinfo(item) nodeinfo = getitemnodeinfo(item)
item.ihook.pytest_runtest_logstart( item.ihook.pytest_runtest_logstart(
nodeid=nodeinfo.nodeid, nodeid=nodeinfo.nodeid,
location=nodeinfo.location location=nodeinfo.location,
fspath=str(item.fspath),
) )
runtestprotocol(item) runtestprotocol(item)
return True return True
@ -80,7 +82,8 @@ def pytest__teardown_final(session):
if call.excinfo: if call.excinfo:
ntraceback = call.excinfo.traceback .cut(excludepath=py._pydir) ntraceback = call.excinfo.traceback .cut(excludepath=py._pydir)
call.excinfo.traceback = ntraceback.filter() call.excinfo.traceback = ntraceback.filter()
return TeardownErrorReport(call.excinfo) longrepr = call.excinfo.getrepr(funcargs=True)
return TeardownErrorReport(longrepr)
def pytest_report_teststatus(report): def pytest_report_teststatus(report):
if report.when in ("setup", "teardown"): if report.when in ("setup", "teardown"):
@ -184,8 +187,8 @@ class TestReport(BaseReport):
class TeardownErrorReport(BaseReport): class TeardownErrorReport(BaseReport):
outcome = "failed" outcome = "failed"
when = "teardown" when = "teardown"
def __init__(self, excinfo): def __init__(self, longrepr):
self.longrepr = excinfo.getrepr(funcargs=True) self.longrepr = longrepr
def pytest_make_collect_report(collector): def pytest_make_collect_report(collector):
result = excinfo = None result = excinfo = None

View File

@ -138,14 +138,14 @@ class TerminalReporter:
def pytest__teardown_final_logerror(self, report): def pytest__teardown_final_logerror(self, report):
self.stats.setdefault("error", []).append(report) self.stats.setdefault("error", []).append(report)
def pytest_runtest_logstart(self, nodeid, location): def pytest_runtest_logstart(self, nodeid, location, fspath):
# ensure that the path is printed before the # ensure that the path is printed before the
# 1st test of a module starts running # 1st test of a module starts running
if self.config.option.verbose: if self.config.option.verbose:
line = self._locationline(*location) line = self._locationline(fspath, *location)
self.write_ensure_prefix(line, "") self.write_ensure_prefix(line, "")
else: else:
self.write_fspath_result(py.path.local(location[0]), "") self.write_fspath_result(py.path.local(fspath), "")
def pytest_runtest_logreport(self, report): def pytest_runtest_logreport(self, report):
rep = report rep = report
@ -158,11 +158,16 @@ class TerminalReporter:
if isinstance(word, tuple): if isinstance(word, tuple):
word, markup = word word, markup = word
else: else:
markup = {} if rep.passed:
markup = {'green':True}
elif rep.failed:
markup = {'red':True}
elif rep.skipped:
markup = {'yellow':True}
if not self.config.option.verbose: if not self.config.option.verbose:
self.write_fspath_result(rep.fspath, letter) self.write_fspath_result(rep.fspath, letter)
else: else:
line = self._locationline(*rep.location) line = self._locationline(str(rep.fspath), *rep.location)
if not hasattr(rep, 'node'): if not hasattr(rep, 'node'):
self.write_ensure_prefix(line, word, **markup) self.write_ensure_prefix(line, word, **markup)
#self._tw.write(word, **markup) #self._tw.write(word, **markup)
@ -227,13 +232,12 @@ class TerminalReporter:
else: else:
excrepr.reprcrash.toterminal(self._tw) excrepr.reprcrash.toterminal(self._tw)
def _locationline(self, fspath, lineno, domain): def _locationline(self, collect_fspath, fspath, lineno, domain):
#collect_fspath = self._getfspath(item) if fspath and fspath != collect_fspath:
#if fspath and fspath != collect_fspath: fspath = "%s <- %s" % (
# fspath = "%s <- %s" % ( self.curdir.bestrelpath(py.path.local(collect_fspath)),
# self.curdir.bestrelpath(collect_fspath), self.curdir.bestrelpath(py.path.local(fspath)))
# self.curdir.bestrelpath(fspath)) elif fspath:
if fspath:
fspath = self.curdir.bestrelpath(py.path.local(fspath)) fspath = self.curdir.bestrelpath(py.path.local(fspath))
if lineno is not None: if lineno is not None:
lineno += 1 lineno += 1

View File

@ -44,14 +44,7 @@ class Session(object):
self.config.pluginmanager.register(self, name="session", prepend=True) self.config.pluginmanager.register(self, name="session", prepend=True)
self._testsfailed = 0 self._testsfailed = 0
self.shouldstop = False self.shouldstop = False
self.collection = Collection(config) self.collection = Collection(config) # XXX move elswehre
def sessionfinishes(self, exitstatus):
# XXX move to main loop / refactor mainloop
self.config.hook.pytest_sessionfinish(
session=self,
exitstatus=exitstatus,
)
def pytest_runtest_logreport(self, report): def pytest_runtest_logreport(self, report):
if report.failed: if report.failed:
@ -66,32 +59,33 @@ class Session(object):
def main(self): def main(self):
""" main loop for running tests. """ """ main loop for running tests. """
self.shouldstop = False self.shouldstop = False
exitstatus = EXIT_OK self.exitstatus = EXIT_OK
config = self.config config = self.config
try: try:
config.pluginmanager.do_configure(config) config.pluginmanager.do_configure(config)
config.hook.pytest_sessionstart(session=self) config.hook.pytest_sessionstart(session=self)
config.hook.pytest_perform_collection(session=self) config.hook.pytest_perform_collection(session=self)
config.hook.pytest_runtest_mainloop(session=self) config.hook.pytest_runtest_mainloop(session=self)
if self._testsfailed:
exitstatus = EXIT_TESTSFAILED
self.sessionfinishes(exitstatus=exitstatus)
config.pluginmanager.do_unconfigure(config)
except self.config.Error: except self.config.Error:
raise raise
except KeyboardInterrupt: except KeyboardInterrupt:
excinfo = py.code.ExceptionInfo() excinfo = py.code.ExceptionInfo()
self.config.hook.pytest_keyboard_interrupt(excinfo=excinfo) self.config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
exitstatus = EXIT_INTERRUPTED self.exitstatus = EXIT_INTERRUPTED
except: except:
excinfo = py.code.ExceptionInfo() excinfo = py.code.ExceptionInfo()
self.config.pluginmanager.notify_exception(excinfo) self.config.pluginmanager.notify_exception(excinfo)
exitstatus = EXIT_INTERNALERROR self.exitstatus = EXIT_INTERNALERROR
if excinfo.errisinstance(SystemExit): if excinfo.errisinstance(SystemExit):
sys.stderr.write("mainloop: caught Spurious SystemExit!\n") sys.stderr.write("mainloop: caught Spurious SystemExit!\n")
if exitstatus in (EXIT_INTERNALERROR, EXIT_INTERRUPTED):
self.sessionfinishes(exitstatus=exitstatus) if not self.exitstatus and self._testsfailed:
return exitstatus self.exitstatus = EXIT_TESTSFAILED
self.config.hook.pytest_sessionfinish(
session=self, exitstatus=self.exitstatus,
)
config.pluginmanager.do_unconfigure(config)
return self.exitstatus
class Collection: class Collection:
def __init__(self, config): def __init__(self, config):

View File

@ -7,7 +7,7 @@ def test_cmdmain(name, pytestconfig):
main = getattr(py.cmdline, name) main = getattr(py.cmdline, name)
assert py.builtin.callable(main) assert py.builtin.callable(main)
assert name[:2] == "py" assert name[:2] == "py"
if pytestconfig.getvalue("toolsonpath"): if not pytestconfig.getvalue("notoolsonpath"):
scriptname = "py." + name[2:] scriptname = "py." + name[2:]
assert py.path.local.sysfind(scriptname), scriptname assert py.path.local.sysfind(scriptname), scriptname

View File

@ -95,7 +95,8 @@ class TestTerminal:
item.config.pluginmanager.register(tr) item.config.pluginmanager.register(tr)
nodeid = item.collection.getid(item) nodeid = item.collection.getid(item)
location = item.ihook.pytest_report_iteminfo(item=item) location = item.ihook.pytest_report_iteminfo(item=item)
tr.config.hook.pytest_runtest_logstart(nodeid=nodeid, location=location) tr.config.hook.pytest_runtest_logstart(nodeid=nodeid,
location=location, fspath=str(item.fspath))
linecomp.assert_contains_lines([ linecomp.assert_contains_lines([
"*test_show_runtest_logstart.py*" "*test_show_runtest_logstart.py*"
]) ])