changeset 21296:cd8776030833

run-tests: create classes for representing tests Currently, the state for an individual test is scattered across a number of functions and variables. This patch begins a process of isolating a single test's state into instances of a class. It does this by establishing a new Test base class and child classes for Python tests and T tests. The class currently has a run() API that proxies into the existing "runner" functions. Upcoming patches will move the logic for each test type into the class.
author Gregory Szorc <gregory.szorc@gmail.com>
date Sat, 19 Apr 2014 12:26:34 -0700
parents 883e268cb860
children dd8e94601417
files tests/run-tests.py
diffstat 1 files changed, 31 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/tests/run-tests.py	Wed Apr 30 18:40:20 2014 -0700
+++ b/tests/run-tests.py	Sat Apr 19 12:26:34 2014 -0700
@@ -579,6 +579,19 @@
             os.mkdir(adir)
         covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit)
 
+class Test(object):
+    """Encapsulates a single, runnable test."""
+
+    def __init__(self, path, options):
+        self._path = path
+        self._options = options
+
+    def run(self, testtmp, replacements, env):
+        return self._run(testtmp, replacements, env)
+
+    def _run(self, testtmp, replacements, env):
+        raise NotImplemented('Subclasses must implement Test.run()')
+
 def pytest(test, wd, options, replacements, env):
     py3kswitch = options.py3k_warnings and ' -3' or ''
     cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test)
@@ -587,6 +600,11 @@
         replacements.append((r'\r\n', '\n'))
     return run(cmd, wd, options, replacements, env)
 
+class PythonTest(Test):
+    """A Python-based test."""
+    def _run(self, testtmp, replacements, env):
+        return pytest(self._path, testtmp, self._options, replacements, env)
+
 needescape = re.compile(r'[\x00-\x08\x0b-\x1f\x7f-\xff]').search
 escapesub = re.compile(r'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub
 escapemap = dict((chr(i), r'\x%02x' % i) for i in range(256))
@@ -843,6 +861,12 @@
         exitcode = False # set exitcode to warned
     return exitcode, postout
 
+class TTest(Test):
+    """A "t test" is a test backed by a .t file."""
+
+    def _run(self, testtmp, replacements, env):
+        return tsttest(self._path, testtmp, self._options, replacements, env)
+
 wifexited = getattr(os, "WIFEXITED", lambda x: False)
 def run(cmd, wd, options, replacements, env):
     """Run command in a sub-process, capturing the output (stdout and stderr).
@@ -952,9 +976,9 @@
 
     if not os.path.basename(lctest).startswith("test-"):
         return skip("not a test file")
-    for ext, func, out in testtypes:
+    for ext, cls, out in testtypes:
         if lctest.endswith(ext):
-            runner = func
+            runner = cls
             ref = os.path.join(TESTDIR, test + out)
             break
     else:
@@ -965,6 +989,8 @@
     if os.path.exists(err):
         os.remove(err)       # Remove any previous output files
 
+    t = runner(testpath, options)
+
     # Make a tmp subdirectory to work in
     threadtmp = os.path.join(HGTMP, "child%d" % count)
     testtmp = os.path.join(threadtmp, os.path.basename(test))
@@ -992,7 +1018,7 @@
 
     starttime = time.time()
     try:
-        ret, out = runner(testpath, testtmp, options, replacements, env)
+        ret, out = t.run(testtmp, replacements, env)
     except KeyboardInterrupt:
         endtime = time.time()
         log('INTERRUPTED: %s (after %d seconds)' % (test, endtime - starttime))
@@ -1192,8 +1218,8 @@
     if warned:
         return 80
 
-testtypes = [('.py', pytest, '.out'),
-             ('.t', tsttest, '')]
+testtypes = [('.py', PythonTest, '.out'),
+             ('.t', TTest, '')]
 
 def main(args, parser=None):
     parser = parser or getparser()