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