comparison tests/run-tests.py @ 21305:d7a7825ff2cf

run-tests: capture execution results in a TestResult class Some implementation details of test execution still live outside of Test. These include determining what a result means and cleaning up after the test. To move to the world where more of this logic can live inside Test or a derived object, the logic for test execution needs to be refactored. Specifically, exception trapping and opportunities for result processing need to be moved into Test. This patch starts the process by establishing a TestResult class for holding the results of a test execution. In order to actually use this class, exception trapping and execution time recording needed to be moved into Test.run().
author Gregory Szorc <gregory.szorc@gmail.com>
date Sat, 19 Apr 2014 13:50:25 -0700
parents e626a67da4ba
children cbf5475827da
comparison
equal deleted inserted replaced
21304:e626a67da4ba 21305:d7a7825ff2cf
561 561
562 def run(self): 562 def run(self):
563 env = self._getenv() 563 env = self._getenv()
564 createhgrc(env['HGRCPATH'], self._options) 564 createhgrc(env['HGRCPATH'], self._options)
565 565
566 result = TestResult()
567 starttime = time.time()
568
569 def updateduration():
570 result.duration = time.time() - starttime
571
566 try: 572 try:
567 return self._run(self._replacements, env) 573 ret, out = self._run(self._replacements, env)
568 finally: 574 updateduration()
569 killdaemons(env['DAEMON_PIDS']) 575 result.ret = ret
576 result.out = out
577 except KeyboardInterrupt:
578 updateduration()
579 result.interrupted = True
580 except Exception, e:
581 updateduration()
582 result.exception = e
583
584 killdaemons(env['DAEMON_PIDS'])
585
586 return result
570 587
571 def _run(self, replacements, env): 588 def _run(self, replacements, env):
572 raise NotImplemented('Subclasses must implement Test.run()') 589 raise NotImplemented('Subclasses must implement Test.run()')
573 590
574 def _setreplacements(self, count): 591 def _setreplacements(self, count):
622 for k in env.keys(): 639 for k in env.keys():
623 if k.startswith('HG_'): 640 if k.startswith('HG_'):
624 del env[k] 641 del env[k]
625 642
626 return env 643 return env
644
645 class TestResult(object):
646 """Holds the result of a test execution."""
647
648 def __init__(self):
649 self.ret = None
650 self.out = None
651 self.duration = None
652 self.interrupted = False
653 self.exception = None
627 654
628 def pytest(test, wd, options, replacements, env): 655 def pytest(test, wd, options, replacements, env):
629 py3kswitch = options.py3k_warnings and ' -3' or '' 656 py3kswitch = options.py3k_warnings and ' -3' or ''
630 cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test) 657 cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test)
631 vlog("# Running", cmd) 658 vlog("# Running", cmd)
1023 1050
1024 if os.path.exists(err): 1051 if os.path.exists(err):
1025 os.remove(err) # Remove any previous output files 1052 os.remove(err) # Remove any previous output files
1026 1053
1027 t = runner(testpath, options, count) 1054 t = runner(testpath, options, count)
1028 1055 res = t.run()
1029 starttime = time.time() 1056
1030 try: 1057 if res.interrupted:
1031 ret, out = t.run() 1058 log('INTERRUPTED: %s (after %d seconds)' % (test, res.duration))
1032 except KeyboardInterrupt: 1059 raise KeyboardInterrupt()
1033 endtime = time.time() 1060
1034 log('INTERRUPTED: %s (after %d seconds)' % (test, endtime - starttime)) 1061 if res.exception:
1035 raise 1062 return fail('Exception during execution: %s' % res.exception, 255)
1036 endtime = time.time() 1063
1037 times.append((test, endtime - starttime)) 1064 ret = res.ret
1065 out = res.out
1066
1067 times.append((test, res.duration))
1038 vlog("# Ret was:", ret) 1068 vlog("# Ret was:", ret)
1039 1069
1040 skipped = (ret == SKIPPED_STATUS) 1070 skipped = (ret == SKIPPED_STATUS)
1041 1071
1042 # If we're not in --debug mode and reference output file exists, 1072 # If we're not in --debug mode and reference output file exists,