136 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Python
		
	
	
	
| """ basic test session implementation. 
 | |
| 
 | |
| * drives collection of tests 
 | |
| * triggers executions of tests   
 | |
| * produces events used by reporting 
 | |
| """
 | |
| 
 | |
| import py
 | |
| 
 | |
| # exitcodes for the command line
 | |
| EXIT_OK = 0
 | |
| EXIT_TESTSFAILED = 1
 | |
| EXIT_INTERRUPTED = 2
 | |
| EXIT_INTERNALERROR = 3
 | |
| EXIT_NOHOSTS = 4
 | |
| 
 | |
| # imports used for genitems()
 | |
| Item = py.test.collect.Item
 | |
| Collector = py.test.collect.Collector
 | |
| 
 | |
| class Session(object): 
 | |
|     nodeid = ""
 | |
|     class Interrupted(KeyboardInterrupt):
 | |
|         """ signals an interrupted test run. """
 | |
|         __module__ = 'builtins' # for py3
 | |
|         
 | |
|     def __init__(self, config):
 | |
|         self.config = config
 | |
|         self.pluginmanager = config.pluginmanager # shortcut 
 | |
|         self.pluginmanager.register(self)
 | |
|         self._testsfailed = 0
 | |
|         self._nomatch = False
 | |
|         self.shouldstop = False
 | |
| 
 | |
|     def genitems(self, colitems, keywordexpr=None):
 | |
|         """ yield Items from iterating over the given colitems. """
 | |
|         if colitems:
 | |
|             colitems = list(colitems)
 | |
|         while colitems: 
 | |
|             next = colitems.pop(0)
 | |
|             if isinstance(next, (tuple, list)):
 | |
|                 colitems[:] = list(next) + colitems 
 | |
|                 continue
 | |
|             assert self.pluginmanager is next.config.pluginmanager
 | |
|             if isinstance(next, Item):
 | |
|                 remaining = self.filteritems([next])
 | |
|                 if remaining:
 | |
|                     self.config.hook.pytest_itemstart(item=next)
 | |
|                     yield next 
 | |
|             else:
 | |
|                 assert isinstance(next, Collector)
 | |
|                 self.config.hook.pytest_collectstart(collector=next)
 | |
|                 rep = self.config.hook.pytest_make_collect_report(collector=next)
 | |
|                 if rep.passed:
 | |
|                     for x in self.genitems(rep.result, keywordexpr):
 | |
|                         yield x 
 | |
|                 self.config.hook.pytest_collectreport(report=rep)
 | |
|             if self.shouldstop:
 | |
|                 raise self.Interrupted(self.shouldstop)
 | |
| 
 | |
|     def filteritems(self, colitems):
 | |
|         """ return items to process (some may be deselected)"""
 | |
|         keywordexpr = self.config.option.keyword 
 | |
|         if not keywordexpr or self._nomatch:
 | |
|             return colitems
 | |
|         if keywordexpr[-1] == ":": 
 | |
|             keywordexpr = keywordexpr[:-1]
 | |
|         remaining = []
 | |
|         deselected = []
 | |
|         for colitem in colitems:
 | |
|             if isinstance(colitem, Item):
 | |
|                 if colitem._skipbykeyword(keywordexpr):
 | |
|                     deselected.append(colitem)
 | |
|                     continue
 | |
|             remaining.append(colitem)
 | |
|         if deselected: 
 | |
|             self.config.hook.pytest_deselected(items=deselected)
 | |
|             if self.config.option.keyword.endswith(":"):
 | |
|                 self._nomatch = True
 | |
|         return remaining 
 | |
| 
 | |
|     def collect(self, colitems): 
 | |
|         keyword = self.config.option.keyword
 | |
|         for x in self.genitems(colitems, keyword):
 | |
|             yield x
 | |
| 
 | |
|     def sessionstarts(self):
 | |
|         """ setup any neccessary resources ahead of the test run. """
 | |
|         self.config.hook.pytest_sessionstart(session=self)
 | |
|         
 | |
|     def pytest_runtest_logreport(self, report):
 | |
|         if report.failed:
 | |
|             self._testsfailed += 1
 | |
|             maxfail = self.config.getvalue("maxfail")
 | |
|             if maxfail and self._testsfailed >= maxfail:
 | |
|                 self.shouldstop = "stopping after %d failures" % (
 | |
|                     self._testsfailed)
 | |
|     pytest_collectreport = pytest_runtest_logreport
 | |
| 
 | |
|     def sessionfinishes(self, exitstatus):
 | |
|         """ teardown any resources after a test run. """ 
 | |
|         self.config.hook.pytest_sessionfinish(
 | |
|             session=self, 
 | |
|             exitstatus=exitstatus, 
 | |
|         )
 | |
| 
 | |
|     def main(self, colitems):
 | |
|         """ main loop for running tests. """
 | |
|         self.shouldstop = False 
 | |
|         self.sessionstarts()
 | |
|         exitstatus = EXIT_OK
 | |
|         try:
 | |
|             self._mainloop(colitems)
 | |
|             if self._testsfailed:
 | |
|                 exitstatus = EXIT_TESTSFAILED
 | |
|             self.sessionfinishes(exitstatus=exitstatus)
 | |
|         except KeyboardInterrupt:
 | |
|             excinfo = py.code.ExceptionInfo()
 | |
|             self.config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
 | |
|             exitstatus = EXIT_INTERRUPTED
 | |
|         except:
 | |
|             excinfo = py.code.ExceptionInfo()
 | |
|             self.config.pluginmanager.notify_exception(excinfo)
 | |
|             exitstatus = EXIT_INTERNALERROR
 | |
|         if exitstatus in (EXIT_INTERNALERROR, EXIT_INTERRUPTED):
 | |
|             self.sessionfinishes(exitstatus=exitstatus)
 | |
|         return exitstatus
 | |
| 
 | |
|     def _mainloop(self, colitems):
 | |
|         for item in self.collect(colitems): 
 | |
|             if not self.config.option.collectonly: 
 | |
|                 item.config.hook.pytest_runtest_protocol(item=item)
 | |
|             if self.shouldstop:
 | |
|                 raise self.Interrupted(self.shouldstop)
 | |
| 
 |