rework session instantiation and exitstatus handling
--HG-- branch : trunk
This commit is contained in:
parent
2718fccfa0
commit
f779d3f863
|
@ -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. """
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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*"
|
||||||
])
|
])
|
||||||
|
|
Loading…
Reference in New Issue