# HG changeset patch # User Gregory Szorc # Date 1397935594 25200 # Node ID cd87760308336c0054ea64efc30114be7b4ab2ad # Parent 883e268cb860c0ea2eb0faa94114e11c3a4a3893 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. diff -r 883e268cb860 -r cd8776030833 tests/run-tests.py --- 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()