Make runner support single threaded mode
diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py
index f7c4f08..7e39200 100644
--- a/src/python/grpcio_tests/commands.py
+++ b/src/python/grpcio_tests/commands.py
@@ -127,7 +127,7 @@
         import tests
         loader = tests.Loader()
         loader.loadTestsFromNames(['tests_aio'])
-        runner = tests.Runner()
+        runner = tests.Runner(dedicated_threads=False)
         result = runner.run(loader.suite)
         if not result.wasSuccessful():
             sys.exit('Test failure')
diff --git a/src/python/grpcio_tests/tests/_runner.py b/src/python/grpcio_tests/tests/_runner.py
index 9ef0f17..0b2186f 100644
--- a/src/python/grpcio_tests/tests/_runner.py
+++ b/src/python/grpcio_tests/tests/_runner.py
@@ -117,8 +117,15 @@
 
 class Runner(object):
 
-    def __init__(self):
+    def __init__(self, dedicated_threads=True):
+        """Constructs the Runner object.
+        
+        Args:
+          dedicated_threads: A bool indicates whether to spawn each unit test
+            in separate thread or not.
+        """
         self._skipped_tests = []
+        self._dedicated_threads = dedicated_threads
 
     def skip_tests(self, tests):
         self._skipped_tests = tests
@@ -194,24 +201,27 @@
                 sys.stdout.write('Running       {}\n'.format(
                     augmented_case.case.id()))
                 sys.stdout.flush()
-                case_thread = threading.Thread(
-                    target=augmented_case.case.run, args=(result,))
-                try:
-                    with stdout_pipe, stderr_pipe:
-                        case_thread.start()
-                        while case_thread.is_alive():
-                            check_kill_self()
-                            time.sleep(0)
-                        case_thread.join()
-                except:  # pylint: disable=try-except-raise
-                    # re-raise the exception after forcing the with-block to end
-                    raise
-                result.set_output(augmented_case.case, stdout_pipe.output(),
-                                  stderr_pipe.output())
-                sys.stdout.write(result_out.getvalue())
-                sys.stdout.flush()
-                result_out.truncate(0)
-                check_kill_self()
+                if self._dedicated_threads:
+                    case_thread = threading.Thread(
+                        target=augmented_case.case.run, args=(result,))
+                    try:
+                        with stdout_pipe, stderr_pipe:
+                            case_thread.start()
+                            while case_thread.is_alive():
+                                check_kill_self()
+                                time.sleep(0)
+                            case_thread.join()
+                    except:  # pylint: disable=try-except-raise
+                        # re-raise the exception after forcing the with-block to end
+                        raise
+                    result.set_output(augmented_case.case, stdout_pipe.output(),
+                                    stderr_pipe.output())
+                    sys.stdout.write(result_out.getvalue())
+                    sys.stdout.flush()
+                    result_out.truncate(0)
+                    check_kill_self()
+                else:
+                    augmented_case.case.run(result)
         result.stopTestRun()
         stdout_pipe.close()
         stderr_pipe.close()
@@ -223,3 +233,4 @@
         with open('report.xml', 'wb') as report_xml_file:
             _result.jenkins_junit_xml(result).write(report_xml_file)
         return result
+