diff --git a/python/cmdtest.py b/python/cmdtest.py
index 3c4ba77..43b7cbe 100755
--- a/python/cmdtest.py
+++ b/python/cmdtest.py
@@ -23,6 +23,7 @@
 # This is a minimal Python version of "cmdtest".
 
 import argparse
+import contextlib
 import copy
 import glob
 import hashlib
@@ -47,7 +48,7 @@ if sys.platform == 'win32':
 class AssertFailed(Exception):
     pass
 
-ORIG_CWD = os.getcwd()
+ROOT_WD = os.getcwd()
 
 class Statistics:
     def __init__(self):
@@ -92,6 +93,16 @@ def mkdir_for(filepath):
     if dirpath:
         os.makedirs(dirpath, exist_ok=True)
 
+@contextlib.contextmanager
+def temp_chdir(path):
+    global ROOT_WD
+    starting_directory = os.getcwd()
+    try:
+        os.chdir(path)
+        ROOT_WD = os.getcwd()
+        yield
+    finally:
+        os.chdir(starting_directory)
 
 def progress(*args):
     print("###", "-" * 50, *args)
@@ -201,7 +212,7 @@ class ExpectPattern:
 #----------------------------------------------------------------------
 
 class Result:
-    def __init__(self, err, before, after, stdout, stderr, tmpdir):
+    def __init__(self, err, before, after, stdout, stderr, tmpdir, test_class_name):
         self._err = err
         self._before = before
         self._after = after
@@ -214,6 +225,9 @@ class Result:
         self._checked_files = set()
         self._nerrors = 0
 
+        self.tmpdir = tmpdir
+        self.test_class_name = test_class_name
+
     def __enter__(self, *args):
         return self
 
@@ -230,6 +244,7 @@ class Result:
         if not self._checked_stderr: self.stderr_equal([])
 
         if self._nerrors > 0:
+            self.tmpdir.preserve(self.test_class_name)
             raise AssertFailed("...")
 
     def _error(self, name, actual, expect):
@@ -361,7 +376,7 @@ class TestCase:
         pass
 
     def prepend_path(self, dirpath):
-        os.environ['PATH'] = os.pathsep.join((os.path.join(ORIG_CWD, dirpath),
+        os.environ['PATH'] = os.pathsep.join((os.path.join(ROOT_WD, dirpath),
                                               os.environ['PATH']))
 
     def prepend_local_path(self, dirpath):
@@ -370,7 +385,7 @@ class TestCase:
 
     def import_file(self, src, tgt):
         mkdir_for(tgt)
-        shutil.copy(os.path.join(ORIG_CWD, src), tgt)
+        shutil.copy(os.path.join(ROOT_WD, src), tgt)
 
     def create_file(self, fname, content, encoding='utf-8'):
         mkdir_for(fname)
@@ -409,7 +424,7 @@ class TestCase:
 
         return Result(err, before, after,
                       File(stdout_log), File(stderr_log),
-                      tmpdir)
+                      tmpdir, type(self).__name__)
 
     def _wait_for_new_second(self):
         newest = self._newest_file_time()
@@ -507,9 +522,12 @@ class FsSnapshot:
 class Tmpdir:
     def __init__(self):
         self.top = os.path.abspath("tmp-cmdtest-python/work")
+        self.top_save = self.top + "-save"
         self.logdir = os.path.dirname(self.top)
         self.environ_path = os.environ['PATH']
         self.old_cwds = []
+        self.remove_all_preserve()
+        self.test_method_name = None
 
     def stdout_log(self):
         return os.path.join(self.logdir, "tmp.stdout")
@@ -523,11 +541,24 @@ class Tmpdir:
     def snapshot(self):
         return FsSnapshot(self.top)
 
+    def prepare_for_test(self, test_method_name):
+        self.clear()
+        self.test_method_name = test_method_name
+
     def clear(self):
         if os.path.exists(self.top):
             shutil.rmtree(self.top)
         os.makedirs(self.top)
 
+    def remove_all_preserve(self):
+        if os.path.exists(self.top_save):
+            shutil.rmtree(self.top_save)
+
+    def preserve(self, test_class_name):
+        shutil.move(self.top, os.path.join(self.top_save,
+                                           test_class_name,
+                                           self.test_method_name))
+
     def __enter__(self):
         self.old_cwds.append(os.getcwd())
         os.chdir(self.top)
@@ -551,7 +582,7 @@ class Tmethod:
 
     def run(self, tmpdir, statistics):
         obj = self.tclass.klass(tmpdir, statistics)
-        tmpdir.clear()
+        tmpdir.prepare_for_test(self.name())
         with tmpdir:
             try:
                 obj.setup()
@@ -608,8 +639,29 @@ class Tfile:
 
 #----------------------------------------------------------------------
 
-def parse_otions():
-    parser = argparse.ArgumentParser('jcons')
+# Run cmdtest in given directory
+def cmdtest_in_dir(path):
+    with temp_chdir(path):
+        py_files = glob.glob("CMDTEST_*.py")
+        return test_files(py_files)
+
+def test_files(py_files, selected_methods = set()):
+    statistics = Statistics()
+    tmpdir = Tmpdir()
+    for py_file in py_files:
+        tfile = Tfile(py_file)
+        for tclass in tfile.tclasses():
+            statistics.classes += 1
+            progress(tclass.name())
+            for tmethod in tclass.tmethods():
+                if not selected_methods or tmethod.name() in selected_methods:
+                    statistics.methods += 1
+                    progress(tmethod.name())
+                    tmethod.run(tmpdir, statistics)
+    return statistics
+
+def parse_options():
+    parser = argparse.ArgumentParser('cmdtest')
     parser.add_argument("-v", "--verbose", action="store_true",
                         help="be more verbose")
     parser.add_argument("arg", nargs="*",
@@ -631,19 +683,8 @@ def parse_otions():
     return options, py_files, selected_methods
 
 def main():
-    options, py_files, selected_methods = parse_otions()
-    statistics = Statistics()
-    for py_file in py_files:
-        tfile = Tfile(py_file)
-        tmpdir = Tmpdir()
-        for tclass in tfile.tclasses():
-            statistics.classes += 1
-            progress(tclass.name())
-            for tmethod in tclass.tmethods():
-                if not selected_methods or tmethod.name() in selected_methods:
-                    statistics.methods += 1
-                    progress(tmethod.name())
-                    tmethod.run(tmpdir, statistics)
+    options, py_files, selected_methods = parse_options()
+    statistics = test_files(py_files, selected_methods)
     print()
     print(statistics)
     print()