Move to 2-space indent: test files except AndroidDevice related (#710)

Pure shortening of the indentation length, no actual code change.
diff --git a/tests/mobly/asserts_test.py b/tests/mobly/asserts_test.py
index ac54393..547f4a9 100755
--- a/tests/mobly/asserts_test.py
+++ b/tests/mobly/asserts_test.py
@@ -21,14 +21,14 @@
 
 
 class AssertsTest(unittest.TestCase):
-    """Verifies that asserts.xxx functions raise the correct test signals.
-    """
-    def test_assert_false(self):
-        asserts.assert_false(False, MSG_EXPECTED_EXCEPTION)
-        with self.assertRaisesRegex(signals.TestFailure,
-                                     MSG_EXPECTED_EXCEPTION):
-            asserts.assert_false(True, MSG_EXPECTED_EXCEPTION)
+  """Verifies that asserts.xxx functions raise the correct test signals.
+  """
+  def test_assert_false(self):
+    asserts.assert_false(False, MSG_EXPECTED_EXCEPTION)
+    with self.assertRaisesRegex(signals.TestFailure,
+                   MSG_EXPECTED_EXCEPTION):
+      asserts.assert_false(True, MSG_EXPECTED_EXCEPTION)
 
 
 if __name__ == "__main__":
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/base_instrumentation_test_test.py b/tests/mobly/base_instrumentation_test_test.py
index 20d6424..ea6d2e4 100755
--- a/tests/mobly/base_instrumentation_test_test.py
+++ b/tests/mobly/base_instrumentation_test_test.py
@@ -48,208 +48,208 @@
 
 
 class InstrumentationResult(object):
-    def __init__(self):
-        self.error = None
-        self.completed_and_passed = False
-        self.executed = []
-        self.skipped = []
+  def __init__(self):
+    self.error = None
+    self.completed_and_passed = False
+    self.executed = []
+    self.skipped = []
 
 
 class BaseInstrumentationTestTest(unittest.TestCase):
-    def setUp(self):
-        self.tmp_dir = tempfile.mkdtemp()
+  def setUp(self):
+    self.tmp_dir = tempfile.mkdtemp()
 
-    def tearDown(self):
-        shutil.rmtree(self.tmp_dir)
+  def tearDown(self):
+    shutil.rmtree(self.tmp_dir)
 
-    def assert_parse_instrumentation_options(self, user_params,
-                                             expected_instrumentation_options):
-        mit = mock_instrumentation_test.MockInstrumentationTest(
-            self.tmp_dir, user_params)
-        instrumentation_options = mit.parse_instrumentation_options(
-            mit.user_params)
-        self.assertEqual(instrumentation_options,
-                         expected_instrumentation_options)
+  def assert_parse_instrumentation_options(self, user_params,
+                       expected_instrumentation_options):
+    mit = mock_instrumentation_test.MockInstrumentationTest(
+      self.tmp_dir, user_params)
+    instrumentation_options = mit.parse_instrumentation_options(
+      mit.user_params)
+    self.assertEqual(instrumentation_options,
+             expected_instrumentation_options)
 
-    def test_parse_instrumentation_options_with_no_user_params(self):
-        self.assert_parse_instrumentation_options({}, {})
+  def test_parse_instrumentation_options_with_no_user_params(self):
+    self.assert_parse_instrumentation_options({}, {})
 
-    def test_parse_instrumentation_options_with_no_instrumentation_params(
-            self):
-        self.assert_parse_instrumentation_options(
-            {
-                'param1': 'val1',
-                'param2': 'val2',
-            },
-            {},
-        )
+  def test_parse_instrumentation_options_with_no_instrumentation_params(
+      self):
+    self.assert_parse_instrumentation_options(
+      {
+        'param1': 'val1',
+        'param2': 'val2',
+      },
+      {},
+    )
 
-    def test_parse_instrumentation_options_with_only_instrumentation_params(
-            self):
-        self.assert_parse_instrumentation_options(
-            {
-                'instrumentation_option_key1': 'value1',
-                'instrumentation_option_key2': 'value2',
-            },
-            {'key1': 'value1',
-             'key2': 'value2'},
-        )
+  def test_parse_instrumentation_options_with_only_instrumentation_params(
+      self):
+    self.assert_parse_instrumentation_options(
+      {
+        'instrumentation_option_key1': 'value1',
+        'instrumentation_option_key2': 'value2',
+      },
+      {'key1': 'value1',
+       'key2': 'value2'},
+    )
 
-    def test_parse_instrumentation_options_with_mixed_user_params(self):
-        self.assert_parse_instrumentation_options(
-            {
-                'param1': 'val1',
-                'param2': 'val2',
-                'instrumentation_option_key1': 'value1',
-                'instrumentation_option_key2': 'value2',
-            },
-            {'key1': 'value1',
-             'key2': 'value2'},
-        )
+  def test_parse_instrumentation_options_with_mixed_user_params(self):
+    self.assert_parse_instrumentation_options(
+      {
+        'param1': 'val1',
+        'param2': 'val2',
+        'instrumentation_option_key1': 'value1',
+        'instrumentation_option_key2': 'value2',
+      },
+      {'key1': 'value1',
+       'key2': 'value2'},
+    )
 
-    def run_instrumentation_test(self, instrumentation_output, prefix=None):
-        mit = mock_instrumentation_test.MockInstrumentationTest(self.tmp_dir)
-        result = InstrumentationResult()
-        try:
-            result.completed_and_passed = mit.run_mock_instrumentation_test(
-                instrumentation_output, prefix=prefix)
-        except signals.TestError as e:
-            result.error = e
-        result.executed = mit.results.executed
-        result.skipped = mit.results.skipped
-        return result
+  def run_instrumentation_test(self, instrumentation_output, prefix=None):
+    mit = mock_instrumentation_test.MockInstrumentationTest(self.tmp_dir)
+    result = InstrumentationResult()
+    try:
+      result.completed_and_passed = mit.run_mock_instrumentation_test(
+        instrumentation_output, prefix=prefix)
+    except signals.TestError as e:
+      result.error = e
+    result.executed = mit.results.executed
+    result.skipped = mit.results.skipped
+    return result
 
-    def assert_equal_test(self, actual_test, expected_test):
-        (expected_test_name, expected_signal) = expected_test
-        self.assertEqual(actual_test.test_class,
-                         MOCK_INSTRUMENTATION_TEST_CLASS_NAME)
-        self.assertEqual(actual_test.test_name, expected_test_name)
-        self.assertIsInstance(actual_test.termination_signal.exception,
-                              expected_signal)
+  def assert_equal_test(self, actual_test, expected_test):
+    (expected_test_name, expected_signal) = expected_test
+    self.assertEqual(actual_test.test_class,
+             MOCK_INSTRUMENTATION_TEST_CLASS_NAME)
+    self.assertEqual(actual_test.test_name, expected_test_name)
+    self.assertIsInstance(actual_test.termination_signal.exception,
+                expected_signal)
 
-    def convert_to_raw_output(self, test_output):
-        """Converts code-based strings into adb output strings.
+  def convert_to_raw_output(self, test_output):
+    """Converts code-based strings into adb output strings.
 
-        In python3, adb returns 'utf-8' encoded byte arrays, which do not work
-        correctly with code-based unicode strings, so to simulate that, the raw
-        instrumentation output should be converted accordingly.
-        """
-        if sys.version_info >= (3, 0):
-            return bytes(test_output, 'utf-8')
-        else:
-            return bytes(test_output)
+    In python3, adb returns 'utf-8' encoded byte arrays, which do not work
+    correctly with code-based unicode strings, so to simulate that, the raw
+    instrumentation output should be converted accordingly.
+    """
+    if sys.version_info >= (3, 0):
+      return bytes(test_output, 'utf-8')
+    else:
+      return bytes(test_output)
 
-    def assert_run_instrumentation_test(self,
-                                        instrumentation_output,
-                                        expected_executed=[],
-                                        expected_skipped=[],
-                                        expected_completed_and_passed=False,
-                                        expected_has_error=False,
-                                        prefix=None,
-                                        expected_executed_times=[]):
-        result = self.run_instrumentation_test(
-            self.convert_to_raw_output(instrumentation_output), prefix=prefix)
-        if expected_has_error:
-            self.assertIsInstance(result.error, signals.TestError)
-        else:
-            self.assertIsNone(result.error)
-            self.assertEqual(result.completed_and_passed,
-                             expected_completed_and_passed)
-        self.assertEqual(len(result.executed), len(expected_executed))
-        for actual_test, expected_test in zip(result.executed,
-                                              expected_executed):
-            self.assert_equal_test(actual_test, expected_test)
-        self.assertEqual(len(result.skipped), len(expected_skipped))
-        for actual_test, expected_test in zip(result.skipped,
-                                              expected_skipped):
-            self.assert_equal_test(actual_test, expected_test)
-        if expected_executed_times:
-            for actual_test, expected_time in zip(result.executed,
-                                                  expected_executed_times):
-                (expected_begin_time, expected_end_time) = expected_time
-                self.assertEqual(actual_test.begin_time, expected_begin_time)
-                self.assertEqual(actual_test.end_time, expected_end_time)
+  def assert_run_instrumentation_test(self,
+                    instrumentation_output,
+                    expected_executed=[],
+                    expected_skipped=[],
+                    expected_completed_and_passed=False,
+                    expected_has_error=False,
+                    prefix=None,
+                    expected_executed_times=[]):
+    result = self.run_instrumentation_test(
+      self.convert_to_raw_output(instrumentation_output), prefix=prefix)
+    if expected_has_error:
+      self.assertIsInstance(result.error, signals.TestError)
+    else:
+      self.assertIsNone(result.error)
+      self.assertEqual(result.completed_and_passed,
+               expected_completed_and_passed)
+    self.assertEqual(len(result.executed), len(expected_executed))
+    for actual_test, expected_test in zip(result.executed,
+                        expected_executed):
+      self.assert_equal_test(actual_test, expected_test)
+    self.assertEqual(len(result.skipped), len(expected_skipped))
+    for actual_test, expected_test in zip(result.skipped,
+                        expected_skipped):
+      self.assert_equal_test(actual_test, expected_test)
+    if expected_executed_times:
+      for actual_test, expected_time in zip(result.executed,
+                          expected_executed_times):
+        (expected_begin_time, expected_end_time) = expected_time
+        self.assertEqual(actual_test.begin_time, expected_begin_time)
+        self.assertEqual(actual_test.end_time, expected_end_time)
 
-    def test_run_instrumentation_test_with_invalid_syntax(self):
-        instrumentation_output = """\
+  def test_run_instrumentation_test_with_invalid_syntax(self):
+    instrumentation_output = """\
 usage: am [subcommand] [options]
 usage: am start [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]
-               [--sampling INTERVAL] [-R COUNT] [-S]
+         [--sampling INTERVAL] [-R COUNT] [-S]
 
 am start: start an Activity.  Options are:
-    -D: enable debugging
+  -D: enable debugging
 
 am startservice: start a Service.  Options are:
-    --user <USER_ID> | current: Specify which user to run as; if not
-        specified then run as the current user.
+  --user <USER_ID> | current: Specify which user to run as; if not
+    specified then run as the current user.
 
 am task lock: bring <TASK_ID> to the front and don't allow other tasks to run.
 
 <INTENT> specifications include these flags and arguments:
-    [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
-    [-c <CATEGORY> [-c <CATEGORY>] ...]
+  [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
+  [-c <CATEGORY> [-c <CATEGORY>] ...]
 
 Error: Bad component name: /
 """
-        self.assert_run_instrumentation_test(
-            instrumentation_output, expected_has_error=True)
+    self.assert_run_instrumentation_test(
+      instrumentation_output, expected_has_error=True)
 
-    def test_run_instrumentation_test_with_no_output(self):
-        instrumentation_output = """\
+  def test_run_instrumentation_test_with_no_output(self):
+    instrumentation_output = """\
 """
-        self.assert_run_instrumentation_test(
-            instrumentation_output, expected_has_error=True)
+    self.assert_run_instrumentation_test(
+      instrumentation_output, expected_has_error=True)
 
-    def test_run_instrumentation_test_with_missing_test_package(self):
-        instrumentation_output = """\
+  def test_run_instrumentation_test_with_missing_test_package(self):
+    instrumentation_output = """\
 android.util.AndroidException: INSTRUMENTATION_FAILED: com.my.package.test/com.my.package.test.runner.MyRunner
-	at com.android.commands.am.Am.runInstrument(Am.java:897)
-	at com.android.commands.am.Am.onRun(Am.java:405)
-	at com.android.internal.os.BaseCommand.run(BaseCommand.java:51)
-	at com.android.commands.am.Am.main(Am.java:124)
-	at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
-	at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:262)
+  at com.android.commands.am.Am.runInstrument(Am.java:897)
+  at com.android.commands.am.Am.onRun(Am.java:405)
+  at com.android.internal.os.BaseCommand.run(BaseCommand.java:51)
+  at com.android.commands.am.Am.main(Am.java:124)
+  at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
+  at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:262)
 INSTRUMENTATION_STATUS: id=ActivityManagerService
 INSTRUMENTATION_STATUS: Error=Unable to find instrumentation info for: ComponentInfo{com.my.package.test/com.my.package.test.runner.MyRunner}
 INSTRUMENTATION_STATUS_CODE: -1"""
-        self.assert_run_instrumentation_test(
-            instrumentation_output, expected_has_error=True)
+    self.assert_run_instrumentation_test(
+      instrumentation_output, expected_has_error=True)
 
-    def test_run_instrumentation_test_with_missing_runner(self):
-        instrumentation_output = """\
+  def test_run_instrumentation_test_with_missing_runner(self):
+    instrumentation_output = """\
 android.util.AndroidException: INSTRUMENTATION_FAILED: com.my.package.test/com.my.package.test.runner
 INSTRUMENTATION_STATUS: id=ActivityManagerService
 INSTRUMENTATION_STATUS: Error=Unable to find instrumentation info for: ComponentInfo{com.my.package.test/com.my.package.test.runner}
 INSTRUMENTATION_STATUS_CODE: -1
-	at com.android.commands.am.Am.runInstrument(Am.java:897)
-	at com.android.commands.am.Am.onRun(Am.java:405)
-	at com.android.internal.os.BaseCommand.run(BaseCommand.java:51)
-	at com.android.commands.am.Am.main(Am.java:124)
-	at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
-	at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:262)"""
-        self.assert_run_instrumentation_test(
-            instrumentation_output, expected_has_error=True)
+  at com.android.commands.am.Am.runInstrument(Am.java:897)
+  at com.android.commands.am.Am.onRun(Am.java:405)
+  at com.android.internal.os.BaseCommand.run(BaseCommand.java:51)
+  at com.android.commands.am.Am.main(Am.java:124)
+  at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
+  at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:262)"""
+    self.assert_run_instrumentation_test(
+      instrumentation_output, expected_has_error=True)
 
-    def test_run_instrumentation_test_with_no_tests(self):
-        instrumentation_output = MOCK_EMPTY_INSTRUMENTATION_TEST
-        self.assert_run_instrumentation_test(
-            instrumentation_output, expected_completed_and_passed=True)
+  def test_run_instrumentation_test_with_no_tests(self):
+    instrumentation_output = MOCK_EMPTY_INSTRUMENTATION_TEST
+    self.assert_run_instrumentation_test(
+      instrumentation_output, expected_completed_and_passed=True)
 
-    @unittest.skipUnless(
-        sys.version_info >= (3, 0),
-        'Only python3 displays different string types differently.')
-    @mock.patch('logging.info')
-    def test_run_instrumentation_test_logs_correctly(self, mock_info_logger):
-        instrumentation_output = MOCK_EMPTY_INSTRUMENTATION_TEST
-        self.assert_run_instrumentation_test(
-            instrumentation_output, expected_completed_and_passed=True)
-        for mock_call in mock_info_logger.mock_calls:
-            logged_format = mock_call[1][0]
-            self.assertIsInstance(logged_format, str)
+  @unittest.skipUnless(
+    sys.version_info >= (3, 0),
+    'Only python3 displays different string types differently.')
+  @mock.patch('logging.info')
+  def test_run_instrumentation_test_logs_correctly(self, mock_info_logger):
+    instrumentation_output = MOCK_EMPTY_INSTRUMENTATION_TEST
+    self.assert_run_instrumentation_test(
+      instrumentation_output, expected_completed_and_passed=True)
+    for mock_call in mock_info_logger.mock_calls:
+      logged_format = mock_call[1][0]
+      self.assertIsInstance(logged_format, str)
 
-    @mock.patch('mobly.utils.get_current_epoch_time')
-    def test_run_instrumentation_test_with_passing_test(self, mock_get_time):
-        instrumentation_output = """\
+  @mock.patch('mobly.utils.get_current_epoch_time')
+  def test_run_instrumentation_test_with_passing_test(self, mock_get_time):
+    instrumentation_output = """\
 INSTRUMENTATION_STATUS: numtests=1
 INSTRUMENTATION_STATUS: stream=
 com.my.package.test.BasicTest:
@@ -274,18 +274,18 @@
 
 INSTRUMENTATION_CODE: -1
 """
-        expected_executed = [
-            ('com.my.package.test.BasicTest#basicTest', signals.TestPass),
-        ]
-        mock_get_time.side_effect = [13, 51]
-        self.assert_run_instrumentation_test(
-            instrumentation_output,
-            expected_executed=expected_executed,
-            expected_completed_and_passed=True,
-            expected_executed_times=[(13, 51)])
+    expected_executed = [
+      ('com.my.package.test.BasicTest#basicTest', signals.TestPass),
+    ]
+    mock_get_time.side_effect = [13, 51]
+    self.assert_run_instrumentation_test(
+      instrumentation_output,
+      expected_executed=expected_executed,
+      expected_completed_and_passed=True,
+      expected_executed_times=[(13, 51)])
 
-    def test_run_instrumentation_test_with_random_whitespace(self):
-        instrumentation_output = """\
+  def test_run_instrumentation_test_with_random_whitespace(self):
+    instrumentation_output = """\
 
 INSTRUMENTATION_STATUS: numtests=1
 
@@ -331,16 +331,16 @@
 INSTRUMENTATION_CODE: -1
 
 """
-        expected_executed = [
-            ('com.my.package.test.BasicTest#basicTest', signals.TestPass),
-        ]
-        self.assert_run_instrumentation_test(
-            instrumentation_output,
-            expected_executed=expected_executed,
-            expected_completed_and_passed=True)
+    expected_executed = [
+      ('com.my.package.test.BasicTest#basicTest', signals.TestPass),
+    ]
+    self.assert_run_instrumentation_test(
+      instrumentation_output,
+      expected_executed=expected_executed,
+      expected_completed_and_passed=True)
 
-    def test_run_instrumentation_test_with_prefix_test(self):
-        instrumentation_output = """\
+  def test_run_instrumentation_test_with_prefix_test(self):
+    instrumentation_output = """\
 INSTRUMENTATION_STATUS: numtests=1
 INSTRUMENTATION_STATUS: stream=
 com.my.package.test.BasicTest:
@@ -365,18 +365,18 @@
 
 INSTRUMENTATION_CODE: -1
 """
-        expected_executed = [
-            ('%s.com.my.package.test.BasicTest#basicTest' % MOCK_PREFIX,
-             signals.TestPass),
-        ]
-        self.assert_run_instrumentation_test(
-            instrumentation_output,
-            expected_executed=expected_executed,
-            expected_completed_and_passed=True,
-            prefix=MOCK_PREFIX)
+    expected_executed = [
+      ('%s.com.my.package.test.BasicTest#basicTest' % MOCK_PREFIX,
+       signals.TestPass),
+    ]
+    self.assert_run_instrumentation_test(
+      instrumentation_output,
+      expected_executed=expected_executed,
+      expected_completed_and_passed=True,
+      prefix=MOCK_PREFIX)
 
-    def test_run_instrumentation_test_with_failing_test(self):
-        instrumentation_output = """\
+  def test_run_instrumentation_test_with_failing_test(self):
+    instrumentation_output = """\
 INSTRUMENTATION_STATUS: class=com.my.package.test.BasicTest
 INSTRUMENTATION_STATUS: current=1
 INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
@@ -390,108 +390,108 @@
 INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
 INSTRUMENTATION_STATUS: numtests=1
 INSTRUMENTATION_STATUS: stack=java.lang.UnsupportedOperationException: dummy failing test
-	at com.my.package.test.BasicTest.failingTest(BasicTest.java:38)
-	at java.lang.reflect.Method.invoke(Native Method)
-	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
-	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
-	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
-	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
-	at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
-	at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
-	at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
-	at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
-	at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
-	at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
-	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
-	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
-	at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
-	at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
-	at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
-	at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
-	at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
+  at com.my.package.test.BasicTest.failingTest(BasicTest.java:38)
+  at java.lang.reflect.Method.invoke(Native Method)
+  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
+  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
+  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+  at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
+  at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
+  at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
+  at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
+  at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
+  at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.RunRules.evaluate(RunRules.java:20)
+  at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
+  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
+  at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
+  at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
+  at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
+  at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
+  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
 
 INSTRUMENTATION_STATUS: stream=
 Error in failingTest(com.my.package.test.BasicTest):
 java.lang.UnsupportedOperationException: dummy failing test
-	at com.my.package.test.BasicTest.failingTest(BasicTest.java:38)
-	at java.lang.reflect.Method.invoke(Native Method)
-	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
-	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
-	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
-	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
-	at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
-	at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
-	at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
-	at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
-	at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
-	at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
-	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
-	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
-	at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
-	at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
-	at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
-	at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
-	at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
+  at com.my.package.test.BasicTest.failingTest(BasicTest.java:38)
+  at java.lang.reflect.Method.invoke(Native Method)
+  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
+  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
+  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+  at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
+  at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
+  at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
+  at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
+  at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
+  at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.RunRules.evaluate(RunRules.java:20)
+  at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
+  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
+  at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
+  at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
+  at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
+  at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
+  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
 
 INSTRUMENTATION_STATUS: test=failingTest
 INSTRUMENTATION_STATUS_CODE: -2
@@ -501,69 +501,69 @@
 There was 1 failure:
 1) failingTest(com.my.package.test.BasicTest)
 java.lang.UnsupportedOperationException: dummy failing test
-	at com.my.package.test.BasicTest.failingTest(BasicTest.java:38)
-	at java.lang.reflect.Method.invoke(Native Method)
-	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
-	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
-	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
-	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
-	at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
-	at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
-	at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
-	at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
-	at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
-	at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
-	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
-	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
-	at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
-	at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
-	at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
-	at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
-	at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
+  at com.my.package.test.BasicTest.failingTest(BasicTest.java:38)
+  at java.lang.reflect.Method.invoke(Native Method)
+  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
+  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
+  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+  at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
+  at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
+  at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
+  at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
+  at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
+  at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.RunRules.evaluate(RunRules.java:20)
+  at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
+  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
+  at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
+  at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
+  at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
+  at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
+  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
 
 FAILURES!!!
 Tests run: 1,  Failures: 1
 
 
 INSTRUMENTATION_CODE: -1"""
-        expected_executed = [
-            ('com.my.package.test.BasicTest#failingTest', signals.TestFailure),
-        ]
-        self.assert_run_instrumentation_test(
-            instrumentation_output, expected_executed=expected_executed)
+    expected_executed = [
+      ('com.my.package.test.BasicTest#failingTest', signals.TestFailure),
+    ]
+    self.assert_run_instrumentation_test(
+      instrumentation_output, expected_executed=expected_executed)
 
-    def test_run_instrumentation_test_with_assumption_failure_test(self):
-        instrumentation_output = """\
+  def test_run_instrumentation_test_with_assumption_failure_test(self):
+    instrumentation_output = """\
 INSTRUMENTATION_STATUS: class=com.my.package.test.BasicTest
 INSTRUMENTATION_STATUS: current=1
 INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
@@ -577,57 +577,57 @@
 INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
 INSTRUMENTATION_STATUS: numtests=1
 INSTRUMENTATION_STATUS: stack=org.junit.AssumptionViolatedException: Assumption failure reason
-	at org.junit.Assume.assumeTrue(Assume.java:59)
-	at org.junit.Assume.assumeFalse(Assume.java:66)
-	at com.my.package.test.BasicTest.assumptionFailureTest(BasicTest.java:63)
-	at java.lang.reflect.Method.invoke(Native Method)
-	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
-	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
-	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
-	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
-	at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
-	at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
-	at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
-	at com.my.package.test.MyBaseTest$3.evaluate(MyBaseTest.java:96)
-	at com.my.package.test.MyBaseTest$4.evaluate(MyBaseTest.java:109)
-	at com.my.package.test.MyBaseTest$2.evaluate(MyBaseTest.java:77)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
-	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
-	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
-	at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
-	at com.my.package.test.runner.BaseRunner.runTests(BaseRunner.java:344)
-	at com.my.package.test.runner.BaseRunner.onStart(BaseRunner.java:330)
-	at com.my.package.test.runner.BaseRunner.onStart(BaseRunner.java:253)
-	at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
+  at org.junit.Assume.assumeTrue(Assume.java:59)
+  at org.junit.Assume.assumeFalse(Assume.java:66)
+  at com.my.package.test.BasicTest.assumptionFailureTest(BasicTest.java:63)
+  at java.lang.reflect.Method.invoke(Native Method)
+  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
+  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
+  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+  at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
+  at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
+  at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
+  at com.my.package.test.MyBaseTest$3.evaluate(MyBaseTest.java:96)
+  at com.my.package.test.MyBaseTest$4.evaluate(MyBaseTest.java:109)
+  at com.my.package.test.MyBaseTest$2.evaluate(MyBaseTest.java:77)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.RunRules.evaluate(RunRules.java:20)
+  at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
+  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
+  at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
+  at com.my.package.test.runner.BaseRunner.runTests(BaseRunner.java:344)
+  at com.my.package.test.runner.BaseRunner.onStart(BaseRunner.java:330)
+  at com.my.package.test.runner.BaseRunner.onStart(BaseRunner.java:253)
+  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
 
 INSTRUMENTATION_STATUS: stream=
 com.my.package.test.BasicTest:
@@ -641,17 +641,17 @@
 
 
 INSTRUMENTATION_CODE: -1"""
-        expected_skipped = [
-            ('com.my.package.test.BasicTest#assumptionFailureTest',
-             signals.TestSkip),
-        ]
-        self.assert_run_instrumentation_test(
-            instrumentation_output,
-            expected_skipped=expected_skipped,
-            expected_completed_and_passed=True)
+    expected_skipped = [
+      ('com.my.package.test.BasicTest#assumptionFailureTest',
+       signals.TestSkip),
+    ]
+    self.assert_run_instrumentation_test(
+      instrumentation_output,
+      expected_skipped=expected_skipped,
+      expected_completed_and_passed=True)
 
-    def test_run_instrumentation_test_with_ignored_test(self):
-        instrumentation_output = """\
+  def test_run_instrumentation_test_with_ignored_test(self):
+    instrumentation_output = """\
 INSTRUMENTATION_STATUS: class=com.my.package.test.BasicTest
 INSTRUMENTATION_STATUS: current=1
 INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
@@ -676,17 +676,17 @@
 
 
 INSTRUMENTATION_CODE: -1"""
-        expected_skipped = [
-            ('com.my.package.test.BasicTest#ignoredTest', signals.TestSkip),
-        ]
-        self.assert_run_instrumentation_test(
-            instrumentation_output,
-            expected_skipped=expected_skipped,
-            expected_completed_and_passed=True)
+    expected_skipped = [
+      ('com.my.package.test.BasicTest#ignoredTest', signals.TestSkip),
+    ]
+    self.assert_run_instrumentation_test(
+      instrumentation_output,
+      expected_skipped=expected_skipped,
+      expected_completed_and_passed=True)
 
-    @mock.patch('mobly.utils.get_current_epoch_time')
-    def test_run_instrumentation_test_with_crashed_test(self, mock_get_time):
-        instrumentation_output = """\
+  @mock.patch('mobly.utils.get_current_epoch_time')
+  def test_run_instrumentation_test_with_crashed_test(self, mock_get_time):
+    instrumentation_output = """\
 INSTRUMENTATION_STATUS: class=com.my.package.test.BasicTest
 INSTRUMENTATION_STATUS: current=1
 INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
@@ -697,19 +697,19 @@
 INSTRUMENTATION_STATUS_CODE: 1
 INSTRUMENTATION_RESULT: shortMsg=Process crashed.
 INSTRUMENTATION_CODE: 0"""
-        expected_executed = [
-            ('com.my.package.test.BasicTest#crashTest', signals.TestError),
-        ]
-        mock_get_time.side_effect = [67, 942]
-        self.assert_run_instrumentation_test(
-            instrumentation_output,
-            expected_executed=expected_executed,
-            expected_has_error=True,
-            expected_executed_times=[(67, 942)])
+    expected_executed = [
+      ('com.my.package.test.BasicTest#crashTest', signals.TestError),
+    ]
+    mock_get_time.side_effect = [67, 942]
+    self.assert_run_instrumentation_test(
+      instrumentation_output,
+      expected_executed=expected_executed,
+      expected_has_error=True,
+      expected_executed_times=[(67, 942)])
 
-    @mock.patch('mobly.utils.get_current_epoch_time')
-    def test_run_instrumentation_test_with_crashing_test(self, mock_get_time):
-        instrumentation_output = """\
+  @mock.patch('mobly.utils.get_current_epoch_time')
+  def test_run_instrumentation_test_with_crashing_test(self, mock_get_time):
+    instrumentation_output = """\
 INSTRUMENTATION_STATUS: class=com.my.package.test.BasicTest
 INSTRUMENTATION_STATUS: current=1
 INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
@@ -734,29 +734,29 @@
 
 
 INSTRUMENTATION_CODE: -1"""
-        expected_executed = [
-            ('com.my.package.test.BasicTest#crashAndRecover1Test',
-             signals.TestError),
-            ('com.my.package.test.BasicTest#crashAndRecover2Test',
-             signals.TestError),
-        ]
-        mock_get_time.side_effect = [16, 412, 4143, 6547]
-        # TODO(winterfrosts): Fix this issue with overlapping timing
-        self.assert_run_instrumentation_test(
-            instrumentation_output,
-            expected_executed=expected_executed,
-            expected_completed_and_passed=True,
-            expected_executed_times=[(16, 4143), (412, 6547)])
+    expected_executed = [
+      ('com.my.package.test.BasicTest#crashAndRecover1Test',
+       signals.TestError),
+      ('com.my.package.test.BasicTest#crashAndRecover2Test',
+       signals.TestError),
+    ]
+    mock_get_time.side_effect = [16, 412, 4143, 6547]
+    # TODO(winterfrosts): Fix this issue with overlapping timing
+    self.assert_run_instrumentation_test(
+      instrumentation_output,
+      expected_executed=expected_executed,
+      expected_completed_and_passed=True,
+      expected_executed_times=[(16, 4143), (412, 6547)])
 
-    def test_run_instrumentation_test_with_runner_setup_crash(self):
-        instrumentation_output = """\
+  def test_run_instrumentation_test_with_runner_setup_crash(self):
+    instrumentation_output = """\
 INSTRUMENTATION_RESULT: shortMsg=Process crashed.
 INSTRUMENTATION_CODE: 0"""
-        self.assert_run_instrumentation_test(
-            instrumentation_output, expected_has_error=True)
+    self.assert_run_instrumentation_test(
+      instrumentation_output, expected_has_error=True)
 
-    def test_run_instrumentation_test_with_runner_teardown_crash(self):
-        instrumentation_output = """\
+  def test_run_instrumentation_test_with_runner_teardown_crash(self):
+    instrumentation_output = """\
 INSTRUMENTATION_STATUS: numtests=1
 INSTRUMENTATION_STATUS: stream=
 com.my.package.test.BasicTest:
@@ -775,17 +775,17 @@
 INSTRUMENTATION_RESULT: shortMsg=Process crashed.
 INSTRUMENTATION_CODE: 0
 """
-        expected_executed = [
-            ('com.my.package.test.BasicTest#basicTest', signals.TestPass),
-        ]
-        self.assert_run_instrumentation_test(
-            instrumentation_output,
-            expected_executed=expected_executed,
-            expected_has_error=True)
+    expected_executed = [
+      ('com.my.package.test.BasicTest#basicTest', signals.TestPass),
+    ]
+    self.assert_run_instrumentation_test(
+      instrumentation_output,
+      expected_executed=expected_executed,
+      expected_has_error=True)
 
-    @mock.patch('mobly.utils.get_current_epoch_time')
-    def test_run_instrumentation_test_with_multiple_tests(self, mock_get_time):
-        instrumentation_output = """\
+  @mock.patch('mobly.utils.get_current_epoch_time')
+  def test_run_instrumentation_test_with_multiple_tests(self, mock_get_time):
+    instrumentation_output = """\
 INSTRUMENTATION_STATUS: class=com.my.package.test.BasicTest
 INSTRUMENTATION_STATUS: current=1
 INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
@@ -799,108 +799,108 @@
 INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
 INSTRUMENTATION_STATUS: numtests=4
 INSTRUMENTATION_STATUS: stack=java.lang.UnsupportedOperationException: dummy failing test
-	at com.my.package.test.BasicTest.failingTest(BasicTest.java:40)
-	at java.lang.reflect.Method.invoke(Native Method)
-	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
-	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
-	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
-	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
-	at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
-	at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
-	at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
-	at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
-	at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
-	at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
-	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
-	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
-	at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
-	at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
-	at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
-	at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
-	at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
+  at com.my.package.test.BasicTest.failingTest(BasicTest.java:40)
+  at java.lang.reflect.Method.invoke(Native Method)
+  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
+  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
+  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+  at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
+  at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
+  at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
+  at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
+  at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
+  at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.RunRules.evaluate(RunRules.java:20)
+  at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
+  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
+  at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
+  at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
+  at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
+  at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
+  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
 
 INSTRUMENTATION_STATUS: stream=
 Error in failingTest(com.my.package.test.BasicTest):
 java.lang.UnsupportedOperationException: dummy failing test
-	at com.my.package.test.BasicTest.failingTest(BasicTest.java:40)
-	at java.lang.reflect.Method.invoke(Native Method)
-	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
-	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
-	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
-	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
-	at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
-	at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
-	at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
-	at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
-	at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
-	at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
-	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
-	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
-	at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
-	at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
-	at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
-	at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
-	at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
+  at com.my.package.test.BasicTest.failingTest(BasicTest.java:40)
+  at java.lang.reflect.Method.invoke(Native Method)
+  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
+  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
+  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+  at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
+  at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
+  at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
+  at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
+  at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
+  at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.RunRules.evaluate(RunRules.java:20)
+  at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
+  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
+  at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
+  at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
+  at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
+  at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
+  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
 
 INSTRUMENTATION_STATUS: test=failingTest
 INSTRUMENTATION_STATUS_CODE: -2
@@ -916,56 +916,56 @@
 INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
 INSTRUMENTATION_STATUS: numtests=4
 INSTRUMENTATION_STATUS: stack=org.junit.AssumptionViolatedException: Assumption failure reason
-	at org.junit.Assume.assumeTrue(Assume.java:59)
-	at com.my.package.test.BasicTest.assumptionFailureTest(BasicTest.java:61)
-	at java.lang.reflect.Method.invoke(Native Method)
-	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
-	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
-	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
-	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
-	at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
-	at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
-	at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
-	at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
-	at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
-	at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
-	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
-	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
-	at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
-	at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
-	at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
-	at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
-	at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
+  at org.junit.Assume.assumeTrue(Assume.java:59)
+  at com.my.package.test.BasicTest.assumptionFailureTest(BasicTest.java:61)
+  at java.lang.reflect.Method.invoke(Native Method)
+  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
+  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
+  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+  at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
+  at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
+  at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
+  at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
+  at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
+  at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.RunRules.evaluate(RunRules.java:20)
+  at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
+  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
+  at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
+  at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
+  at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
+  at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
+  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
 
 INSTRUMENTATION_STATUS: stream=
 INSTRUMENTATION_STATUS: test=assumptionFailureTest
@@ -1004,85 +1004,85 @@
 There was 1 failure:
 1) failingTest(com.my.package.test.BasicTest)
 java.lang.UnsupportedOperationException: dummy failing test
-	at com.my.package.test.BasicTest.failingTest(BasicTest.java:40)
-	at java.lang.reflect.Method.invoke(Native Method)
-	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
-	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
-	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
-	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
-	at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
-	at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
-	at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
-	at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
-	at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
-	at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
-	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
-	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
-	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
-	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runners.Suite.runChild(Suite.java:128)
-	at org.junit.runners.Suite.runChild(Suite.java:27)
-	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
-	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
-	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
-	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
-	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
-	at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
-	at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
-	at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
-	at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
-	at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
-	at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
-	at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
+  at com.my.package.test.BasicTest.failingTest(BasicTest.java:40)
+  at java.lang.reflect.Method.invoke(Native Method)
+  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:57)
+  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:59)
+  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+  at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
+  at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
+  at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:433)
+  at com.my.package.test.BaseTest$3.evaluate(BaseTest.java:96)
+  at com.my.package.test.BaseTest$4.evaluate(BaseTest.java:109)
+  at com.my.package.test.BaseTest$2.evaluate(BaseTest.java:77)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
+  at org.junit.rules.RunRules.evaluate(RunRules.java:20)
+  at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:81)
+  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:327)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:84)
+  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:99)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runners.Suite.runChild(Suite.java:128)
+  at org.junit.runners.Suite.runChild(Suite.java:27)
+  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:292)
+  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:73)
+  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:290)
+  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:60)
+  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:270)
+  at org.junit.runners.ParentRunner.run(ParentRunner.java:370)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
+  at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
+  at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
+  at com.my.package.test.BaseRunner.runTests(BaseRunner.java:344)
+  at com.my.package.test.BaseRunner.onStart(BaseRunner.java:330)
+  at com.my.package.test.runner.MyRunner.onStart(MyRunner.java:253)
+  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)
 
 FAILURES!!!
 Tests run: 3,  Failures: 1
 
 
 INSTRUMENTATION_CODE: -1"""
-        expected_executed = [
-            ('com.my.package.test.BasicTest#failingTest', signals.TestFailure),
-            ('com.my.package.test.BasicTest#passingTest', signals.TestPass),
-        ]
-        expected_skipped = [
-            ('com.my.package.test.BasicTest#assumptionFailureTest',
-             signals.TestSkip),
-            ('com.my.package.test.BasicTest#ignoredTest', signals.TestSkip),
-        ]
-        mock_get_time.side_effect = [54, 64, -1, -1, -1, -1, 89, 94]
-        self.assert_run_instrumentation_test(
-            instrumentation_output,
-            expected_executed=expected_executed,
-            expected_skipped=expected_skipped,
-            expected_executed_times=[(54, 64), (89, 94)])
+    expected_executed = [
+      ('com.my.package.test.BasicTest#failingTest', signals.TestFailure),
+      ('com.my.package.test.BasicTest#passingTest', signals.TestPass),
+    ]
+    expected_skipped = [
+      ('com.my.package.test.BasicTest#assumptionFailureTest',
+       signals.TestSkip),
+      ('com.my.package.test.BasicTest#ignoredTest', signals.TestSkip),
+    ]
+    mock_get_time.side_effect = [54, 64, -1, -1, -1, -1, 89, 94]
+    self.assert_run_instrumentation_test(
+      instrumentation_output,
+      expected_executed=expected_executed,
+      expected_skipped=expected_skipped,
+      expected_executed_times=[(54, 64), (89, 94)])
 
-    def test__Instrumentation_block_set_key_on_multiple_equals_sign(self):
-        value = "blah=blah, blah2=blah2, blah=2=1=2"
-        parsed_line = "INSTRUMENTATION_STATUS: stack=%s" % value
-        block = _InstrumentationBlock()
-        block.set_key(_InstrumentationStructurePrefixes.STATUS, parsed_line)
-        self.assertIn(value,
-                      block.known_keys[_InstrumentationKnownStatusKeys.STACK])
+  def test__Instrumentation_block_set_key_on_multiple_equals_sign(self):
+    value = "blah=blah, blah2=blah2, blah=2=1=2"
+    parsed_line = "INSTRUMENTATION_STATUS: stack=%s" % value
+    block = _InstrumentationBlock()
+    block.set_key(_InstrumentationStructurePrefixes.STATUS, parsed_line)
+    self.assertIn(value,
+            block.known_keys[_InstrumentationKnownStatusKeys.STACK])
 
 
 if __name__ == '__main__':
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/base_test_test.py b/tests/mobly/base_test_test.py
index 6eb7149..4946d1a 100755
--- a/tests/mobly/base_test_test.py
+++ b/tests/mobly/base_test_test.py
@@ -42,2173 +42,2173 @@
 
 
 def never_call():
-    raise Exception(MSG_UNEXPECTED_EXCEPTION)
+  raise Exception(MSG_UNEXPECTED_EXCEPTION)
 
 
 class SomeError(Exception):
-    """A custom exception class used for tests in this module."""
+  """A custom exception class used for tests in this module."""
 
 
 class BaseTestTest(unittest.TestCase):
-    def setUp(self):
-        self.tmp_dir = tempfile.mkdtemp()
-        self.mock_test_cls_configs = config_parser.TestRunConfig()
-        self.summary_file = os.path.join(self.tmp_dir, 'summary.yaml')
-        self.mock_test_cls_configs.summary_writer = records.TestSummaryWriter(
-            self.summary_file)
-        self.mock_test_cls_configs.controller_configs = {}
-        self.mock_test_cls_configs.log_path = self.tmp_dir
-        self.mock_test_cls_configs.user_params = {"some_param": "hahaha"}
-        self.mock_test_cls_configs.reporter = mock.MagicMock()
-        self.mock_test_name = "test_something"
+  def setUp(self):
+    self.tmp_dir = tempfile.mkdtemp()
+    self.mock_test_cls_configs = config_parser.TestRunConfig()
+    self.summary_file = os.path.join(self.tmp_dir, 'summary.yaml')
+    self.mock_test_cls_configs.summary_writer = records.TestSummaryWriter(
+      self.summary_file)
+    self.mock_test_cls_configs.controller_configs = {}
+    self.mock_test_cls_configs.log_path = self.tmp_dir
+    self.mock_test_cls_configs.user_params = {"some_param": "hahaha"}
+    self.mock_test_cls_configs.reporter = mock.MagicMock()
+    self.mock_test_name = "test_something"
 
-    def tearDown(self):
-        shutil.rmtree(self.tmp_dir)
+  def tearDown(self):
+    shutil.rmtree(self.tmp_dir)
 
-    def test_paths(self):
-        '''Checks the output paths set in `BaseTestClass`.'''
-        path_checker = mock.MagicMock()
+  def test_paths(self):
+    '''Checks the output paths set in `BaseTestClass`.'''
+    path_checker = mock.MagicMock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                path_checker.log_path = self.log_path
-                path_checker.root_output_path = self.root_output_path
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        path_checker.log_path = self.log_path
+        path_checker.root_output_path = self.root_output_path
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_func"])
-        self.assertEqual(path_checker.root_output_path, self.tmp_dir)
-        self.assertTrue(os.path.exists(path_checker.root_output_path))
-        expected_log_path = os.path.join(self.tmp_dir, 'MockBaseTest')
-        self.assertEqual(path_checker.log_path, expected_log_path)
-        self.assertTrue(os.path.exists(path_checker.log_path))
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_func"])
+    self.assertEqual(path_checker.root_output_path, self.tmp_dir)
+    self.assertTrue(os.path.exists(path_checker.root_output_path))
+    expected_log_path = os.path.join(self.tmp_dir, 'MockBaseTest')
+    self.assertEqual(path_checker.log_path, expected_log_path)
+    self.assertTrue(os.path.exists(path_checker.log_path))
 
-    def test_current_test_name(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                asserts.assert_true(self.current_test_info.name == "test_func",
-                                    ("Got "
-                                     "unexpected test name %s.") %
-                                    self.current_test_info.name)
+  def test_current_test_name(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        asserts.assert_true(self.current_test_info.name == "test_func",
+                  ("Got "
+                   "unexpected test name %s.") %
+                  self.current_test_info.name)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_func"])
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertIsNone(actual_record.details)
-        self.assertIsNone(actual_record.extras)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_func"])
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertIsNone(actual_record.details)
+    self.assertIsNone(actual_record.extras)
 
-    def test_current_test_info(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                asserts.assert_true(
-                    self.current_test_info.name == 'test_func',
-                    'Got unexpected test name %s.' %
-                    self.current_test_info.name)
-                output_path = self.current_test_info.output_path
-                asserts.assert_true(os.path.exists(output_path),
-                                    'test output path missing')
+  def test_current_test_info(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        asserts.assert_true(
+          self.current_test_info.name == 'test_func',
+          'Got unexpected test name %s.' %
+          self.current_test_info.name)
+        output_path = self.current_test_info.output_path
+        asserts.assert_true(os.path.exists(output_path),
+                  'test output path missing')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=['test_func'])
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.test_name, 'test_func')
-        self.assertIsNone(actual_record.details)
-        self.assertIsNone(actual_record.extras)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=['test_func'])
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.test_name, 'test_func')
+    self.assertIsNone(actual_record.details)
+    self.assertIsNone(actual_record.extras)
 
-    def test_current_test_info_in_setup_class(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_class(self):
-                asserts.assert_true(
-                    self.current_test_info.name == 'setup_class',
-                    'Got unexpected test name %s.' %
-                    self.current_test_info.name)
-                output_path = self.current_test_info.output_path
-                asserts.assert_true(os.path.exists(output_path),
-                                    'test output path missing')
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+  def test_current_test_info_in_setup_class(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_class(self):
+        asserts.assert_true(
+          self.current_test_info.name == 'setup_class',
+          'Got unexpected test name %s.' %
+          self.current_test_info.name)
+        output_path = self.current_test_info.output_path
+        asserts.assert_true(os.path.exists(output_path),
+                  'test output path missing')
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, 'setup_class')
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, 'setup_class')
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
 
-    def test_self_tests_list(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def __init__(self, controllers):
-                super(MockBaseTest, self).__init__(controllers)
-                self.tests = ("test_something", )
+  def test_self_tests_list(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def __init__(self, controllers):
+        super(MockBaseTest, self).__init__(controllers)
+        self.tests = ("test_something", )
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-            def test_never(self):
-                # This should not execute it's not on default test list.
-                never_call()
+      def test_never(self):
+        # This should not execute it's not on default test list.
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.test_name, "test_something")
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.test_name, "test_something")
 
-    def test_self_tests_list_fail_by_convention(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def __init__(self, controllers):
-                super(MockBaseTest, self).__init__(controllers)
-                self.tests = ("not_a_test_something", )
+  def test_self_tests_list_fail_by_convention(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def __init__(self, controllers):
+        super(MockBaseTest, self).__init__(controllers)
+        self.tests = ("not_a_test_something", )
 
-            def not_a_test_something(self):
-                pass
+      def not_a_test_something(self):
+        pass
 
-            def test_never(self):
-                # This should not execute it's not on default test list.
-                never_call()
+      def test_never(self):
+        # This should not execute it's not on default test list.
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        expected_msg = (
-            r'Test method name not_a_test_something does not follow '
-            r'naming convention test_\*, abort.')
-        with self.assertRaisesRegex(base_test.Error, expected_msg):
-            bt_cls.run()
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    expected_msg = (
+      r'Test method name not_a_test_something does not follow '
+      r'naming convention test_\*, abort.')
+    with self.assertRaisesRegex(base_test.Error, expected_msg):
+      bt_cls.run()
 
-    def test_cli_test_selection_override_self_tests_list(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def __init__(self, controllers):
-                super(MockBaseTest, self).__init__(controllers)
-                self.tests = ("test_never", )
+  def test_cli_test_selection_override_self_tests_list(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def __init__(self, controllers):
+        super(MockBaseTest, self).__init__(controllers)
+        self.tests = ("test_never", )
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-            def test_never(self):
-                # This should not execute it's not selected by cmd line input.
-                never_call()
+      def test_never(self):
+        # This should not execute it's not selected by cmd line input.
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_something"])
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.test_name, "test_something")
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_something"])
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.test_name, "test_something")
 
-    def test_cli_test_selection_fail_by_convention(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def __init__(self, controllers):
-                super(MockBaseTest, self).__init__(controllers)
-                self.tests = ("not_a_test_something", )
+  def test_cli_test_selection_fail_by_convention(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def __init__(self, controllers):
+        super(MockBaseTest, self).__init__(controllers)
+        self.tests = ("not_a_test_something", )
 
-            def not_a_test_something(self):
-                pass
+      def not_a_test_something(self):
+        pass
 
-            def test_never(self):
-                # This should not execute it's not selected by cmd line input.
-                never_call()
+      def test_never(self):
+        # This should not execute it's not selected by cmd line input.
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        expected_msg = (
-            r'Test method name not_a_test_something does not follow '
-            r'naming convention test_\*, abort.')
-        with self.assertRaisesRegex(base_test.Error, expected_msg):
-            bt_cls.run(test_names=["not_a_test_something"])
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    expected_msg = (
+      r'Test method name not_a_test_something does not follow '
+      r'naming convention test_\*, abort.')
+    with self.assertRaisesRegex(base_test.Error, expected_msg):
+      bt_cls.run(test_names=["not_a_test_something"])
 
-    def test_default_execution_of_all_tests(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_something(self):
-                pass
+  def test_default_execution_of_all_tests(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_something(self):
+        pass
 
-            def not_a_test(self):
-                # This should not execute its name doesn't follow test method
-                # naming convention.
-                never_call()
+      def not_a_test(self):
+        # This should not execute its name doesn't follow test method
+        # naming convention.
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.test_name, "test_something")
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.test_name, "test_something")
 
-    def test_default_execution_skip_noncallable_tests(self):
-        mock_decorated = mock.MagicMock()
-        mock_undecorated = mock.MagicMock()
+  def test_default_execution_skip_noncallable_tests(self):
+    mock_decorated = mock.MagicMock()
+    mock_undecorated = mock.MagicMock()
 
-        class TestDecorator(object):
-            def __init__(self, func):
-                self.func = func
+    class TestDecorator(object):
+      def __init__(self, func):
+        self.func = func
 
-            def __call__(self, *args, **kwargs):
-                return self.func(*args, **kwargs)
+      def __call__(self, *args, **kwargs):
+        return self.func(*args, **kwargs)
 
-            def __get__(self, instance, owner):
-                return functools.partial(self.__call__, instance)
+      def __get__(self, instance, owner):
+        return functools.partial(self.__call__, instance)
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def __init__(self, controllers):
-                super(MockBaseTest, self).__init__(controllers)
-                self.test_noncallable = None
+    class MockBaseTest(base_test.BaseTestClass):
+      def __init__(self, controllers):
+        super(MockBaseTest, self).__init__(controllers)
+        self.test_noncallable = None
 
-            @TestDecorator
-            def test_decorated(self):
-                mock_decorated('test_decorated')
+      @TestDecorator
+      def test_decorated(self):
+        mock_decorated('test_decorated')
 
-            def test_undecorated(self):
-                mock_undecorated('test_undecorated')
+      def test_undecorated(self):
+        mock_undecorated('test_undecorated')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        self.assertNotIn('test_noncallable',
-                         [test.test_name for test in bt_cls.results.executed])
-        mock_decorated.assert_called_once_with('test_decorated')
-        mock_undecorated.assert_called_once_with('test_undecorated')
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    self.assertNotIn('test_noncallable',
+             [test.test_name for test in bt_cls.results.executed])
+    mock_decorated.assert_called_once_with('test_decorated')
+    mock_undecorated.assert_called_once_with('test_undecorated')
 
-    def test_missing_requested_test_func(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            pass
+  def test_missing_requested_test_func(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        expected_msg = ".* does not have test method test_something"
-        with self.assertRaisesRegex(base_test.Error, expected_msg):
-            bt_cls.run(test_names=["test_something"])
-        self.assertFalse(bt_cls.results.executed)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    expected_msg = ".* does not have test method test_something"
+    with self.assertRaisesRegex(base_test.Error, expected_msg):
+      bt_cls.run(test_names=["test_something"])
+    self.assertFalse(bt_cls.results.executed)
 
-    def test_setup_class_fail_by_exception(self):
-        teardown_class_call_check = mock.MagicMock()
-        on_fail_call_check = mock.MagicMock()
+  def test_setup_class_fail_by_exception(self):
+    teardown_class_call_check = mock.MagicMock()
+    on_fail_call_check = mock.MagicMock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_class(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_class(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-            def test_something(self):
-                # This should not execute because setup_class failed.
-                never_call()
+      def test_something(self):
+        # This should not execute because setup_class failed.
+        never_call()
 
-            def test_something2(self):
-                # This should not execute because setup_class failed.
-                never_call()
+      def test_something2(self):
+        # This should not execute because setup_class failed.
+        never_call()
 
-            def teardown_class(self):
-                # This should execute because the setup_class failure should
-                # have already been recorded.
-                if not self.results.is_all_pass:
-                    teardown_class_call_check("heehee")
+      def teardown_class(self):
+        # This should execute because the setup_class failure should
+        # have already been recorded.
+        if not self.results.is_all_pass:
+          teardown_class_call_check("heehee")
 
-            def on_fail(self, record):
-                on_fail_call_check("haha")
+      def on_fail(self, record):
+        on_fail_call_check("haha")
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        skipped_record = bt_cls.results.skipped[0]
-        self.assertIsNone(skipped_record.begin_time)
-        self.assertIsNone(skipped_record.end_time)
-        utils.validate_test_result(bt_cls.results)
-        self.assertEqual(actual_record.test_name, "setup_class")
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
-        expected_summary = ("Error 1, Executed 0, Failed 0, Passed 0, "
-                            "Requested 2, Skipped 2")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
-        teardown_class_call_check.assert_called_once_with("heehee")
-        on_fail_call_check.assert_called_once_with("haha")
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    skipped_record = bt_cls.results.skipped[0]
+    self.assertIsNone(skipped_record.begin_time)
+    self.assertIsNone(skipped_record.end_time)
+    utils.validate_test_result(bt_cls.results)
+    self.assertEqual(actual_record.test_name, "setup_class")
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
+    expected_summary = ("Error 1, Executed 0, Failed 0, Passed 0, "
+              "Requested 2, Skipped 2")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    teardown_class_call_check.assert_called_once_with("heehee")
+    on_fail_call_check.assert_called_once_with("haha")
 
-    def test_teardown_class_fail_by_exception(self):
-        mock_test_config = self.mock_test_cls_configs.copy()
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        mock_ctrlr_2_config_name = mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        my_config = [{'serial': 'xxxx', 'magic': 'Magic'}]
-        mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
-        mock_test_config.controller_configs[
-            mock_ctrlr_2_config_name] = copy.copy(my_config)
+  def test_teardown_class_fail_by_exception(self):
+    mock_test_config = self.mock_test_cls_configs.copy()
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    mock_ctrlr_2_config_name = mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    my_config = [{'serial': 'xxxx', 'magic': 'Magic'}]
+    mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
+    mock_test_config.controller_configs[
+      mock_ctrlr_2_config_name] = copy.copy(my_config)
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_class(self):
-                self.register_controller(mock_controller)
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_class(self):
+        self.register_controller(mock_controller)
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-            def teardown_class(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+      def teardown_class(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(mock_test_config)
-        bt_cls.run()
-        test_record = bt_cls.results.passed[0]
-        class_record = bt_cls.results.error[0]
-        self.assertFalse(bt_cls.results.is_all_pass)
-        self.assertEqual(class_record.test_name, 'teardown_class')
-        self.assertEqual(class_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNotNone(class_record.begin_time)
-        self.assertIsNotNone(class_record.end_time)
-        self.assertIsNone(class_record.extras)
-        expected_summary = ('Error 1, Executed 1, Failed 0, Passed 1, '
-                            'Requested 1, Skipped 0')
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
-        # Verify the controller info is recorded correctly.
-        info = bt_cls.results.controller_info[0]
-        self.assertEqual(info.test_class, 'MockBaseTest')
-        self.assertEqual(info.controller_name, 'MagicDevice')
-        self.assertEqual(info.controller_info, [{
-            'MyMagic': {
-                'magic': 'Magic'
-            }
-        }])
+    bt_cls = MockBaseTest(mock_test_config)
+    bt_cls.run()
+    test_record = bt_cls.results.passed[0]
+    class_record = bt_cls.results.error[0]
+    self.assertFalse(bt_cls.results.is_all_pass)
+    self.assertEqual(class_record.test_name, 'teardown_class')
+    self.assertEqual(class_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNotNone(class_record.begin_time)
+    self.assertIsNotNone(class_record.end_time)
+    self.assertIsNone(class_record.extras)
+    expected_summary = ('Error 1, Executed 1, Failed 0, Passed 1, '
+              'Requested 1, Skipped 0')
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    # Verify the controller info is recorded correctly.
+    info = bt_cls.results.controller_info[0]
+    self.assertEqual(info.test_class, 'MockBaseTest')
+    self.assertEqual(info.controller_name, 'MagicDevice')
+    self.assertEqual(info.controller_info, [{
+      'MyMagic': {
+        'magic': 'Magic'
+      }
+    }])
 
-    def test_teardown_class_raise_abort_all(self):
-        mock_test_config = self.mock_test_cls_configs.copy()
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        mock_ctrlr_2_config_name = mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        my_config = [{'serial': 'xxxx', 'magic': 'Magic'}]
-        mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
-        mock_test_config.controller_configs[
-            mock_ctrlr_2_config_name] = copy.copy(my_config)
+  def test_teardown_class_raise_abort_all(self):
+    mock_test_config = self.mock_test_cls_configs.copy()
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    mock_ctrlr_2_config_name = mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    my_config = [{'serial': 'xxxx', 'magic': 'Magic'}]
+    mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
+    mock_test_config.controller_configs[
+      mock_ctrlr_2_config_name] = copy.copy(my_config)
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_class(self):
-                self.register_controller(mock_controller)
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_class(self):
+        self.register_controller(mock_controller)
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-            def teardown_class(self):
-                raise asserts.abort_all(MSG_EXPECTED_EXCEPTION)
+      def teardown_class(self):
+        raise asserts.abort_all(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(mock_test_config)
-        with self.assertRaisesRegex(signals.TestAbortAll,
-                                    MSG_EXPECTED_EXCEPTION):
-            bt_cls.run()
-        test_record = bt_cls.results.passed[0]
-        self.assertTrue(bt_cls.results.is_all_pass)
-        expected_summary = ('Error 0, Executed 1, Failed 0, Passed 1, '
-                            'Requested 1, Skipped 0')
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
-        # Verify the controller info is recorded correctly.
-        info = bt_cls.results.controller_info[0]
-        self.assertEqual(info.test_class, 'MockBaseTest')
-        self.assertEqual(info.controller_name, 'MagicDevice')
-        self.assertEqual(info.controller_info, [{
-            'MyMagic': {
-                'magic': 'Magic'
-            }
-        }])
+    bt_cls = MockBaseTest(mock_test_config)
+    with self.assertRaisesRegex(signals.TestAbortAll,
+                  MSG_EXPECTED_EXCEPTION):
+      bt_cls.run()
+    test_record = bt_cls.results.passed[0]
+    self.assertTrue(bt_cls.results.is_all_pass)
+    expected_summary = ('Error 0, Executed 1, Failed 0, Passed 1, '
+              'Requested 1, Skipped 0')
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    # Verify the controller info is recorded correctly.
+    info = bt_cls.results.controller_info[0]
+    self.assertEqual(info.test_class, 'MockBaseTest')
+    self.assertEqual(info.controller_name, 'MagicDevice')
+    self.assertEqual(info.controller_info, [{
+      'MyMagic': {
+        'magic': 'Magic'
+      }
+    }])
 
-    def test_setup_test_fail_by_exception(self):
-        mock_on_fail = mock.Mock()
+  def test_setup_test_fail_by_exception(self):
+    mock_on_fail = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def on_fail(self, *args):
-                mock_on_fail('on_fail')
+    class MockBaseTest(base_test.BaseTestClass):
+      def on_fail(self, *args):
+        mock_on_fail('on_fail')
 
-            def setup_test(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+      def setup_test(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-            def test_something(self):
-                # This should not execute because setup_test failed.
-                never_call()
+      def test_something(self):
+        # This should not execute because setup_test failed.
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_something"])
-        mock_on_fail.assert_called_once_with('on_fail')
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertTrue('in setup_test\n    '
-                        'raise Exception(MSG_EXPECTED_EXCEPTION)\n'
-                        'Exception: This is an expected exception.\n' in
-                        actual_record.stacktrace)
-        self.assertIsNone(actual_record.extras)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_something"])
+    mock_on_fail.assert_called_once_with('on_fail')
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertTrue('in setup_test\n    '
+            'raise Exception(MSG_EXPECTED_EXCEPTION)\n'
+            'Exception: This is an expected exception.\n' in
+            actual_record.stacktrace)
+    self.assertIsNone(actual_record.extras)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_setup_test_fail_by_test_signal(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_test(self):
-                raise signals.TestFailure(MSG_EXPECTED_EXCEPTION)
+  def test_setup_test_fail_by_test_signal(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_test(self):
+        raise signals.TestFailure(MSG_EXPECTED_EXCEPTION)
 
-            def test_something(self):
-                # This should not execute because setup_test failed.
-                never_call()
+      def test_something(self):
+        # This should not execute because setup_test failed.
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_something"])
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        # Make sure the full stacktrace of `setup_test` is preserved.
-        self.assertTrue('self.setup_test()' in actual_record.stacktrace)
-        self.assertIsNone(actual_record.extras)
-        self.assertTrue(actual_record.end_time)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_something"])
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    # Make sure the full stacktrace of `setup_test` is preserved.
+    self.assertTrue('self.setup_test()' in actual_record.stacktrace)
+    self.assertIsNone(actual_record.extras)
+    self.assertTrue(actual_record.end_time)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_teardown_test_assert_fail(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def teardown_test(self):
-                asserts.fail(MSG_EXPECTED_EXCEPTION)
+  def test_teardown_test_assert_fail(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def teardown_test(self):
+        asserts.fail(MSG_EXPECTED_EXCEPTION)
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertTrue(actual_record.end_time)
-        self.assertIsNone(actual_record.extras)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertTrue(actual_record.end_time)
+    self.assertIsNone(actual_record.extras)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_teardown_test_raise_exception(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def teardown_test(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+  def test_teardown_test_raise_exception(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def teardown_test(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
-        self.assertFalse(actual_record.extra_errors)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
+    self.assertFalse(actual_record.extra_errors)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_teardown_test_executed_if_test_pass(self):
-        my_mock = mock.MagicMock()
+  def test_teardown_test_executed_if_test_pass(self):
+    my_mock = mock.MagicMock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def teardown_test(self):
-                my_mock("teardown_test")
+    class MockBaseTest(base_test.BaseTestClass):
+      def teardown_test(self):
+        my_mock("teardown_test")
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.passed[0]
-        my_mock.assert_called_once_with("teardown_test")
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertIsNone(actual_record.details)
-        self.assertIsNone(actual_record.extras)
-        self.assertTrue(actual_record.end_time)
-        expected_summary = ("Error 0, Executed 1, Failed 0, Passed 1, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.passed[0]
+    my_mock.assert_called_once_with("teardown_test")
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertIsNone(actual_record.details)
+    self.assertIsNone(actual_record.extras)
+    self.assertTrue(actual_record.end_time)
+    expected_summary = ("Error 0, Executed 1, Failed 0, Passed 1, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_teardown_test_executed_if_setup_test_fails(self):
-        my_mock = mock.MagicMock()
+  def test_teardown_test_executed_if_setup_test_fails(self):
+    my_mock = mock.MagicMock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_test(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_test(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-            def teardown_test(self):
-                my_mock("teardown_test")
+      def teardown_test(self):
+        my_mock("teardown_test")
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        my_mock.assert_called_once_with("teardown_test")
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
-        self.assertTrue(actual_record.end_time)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    my_mock.assert_called_once_with("teardown_test")
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
+    self.assertTrue(actual_record.end_time)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_teardown_test_executed_if_test_fails(self):
-        my_mock = mock.MagicMock()
+  def test_teardown_test_executed_if_test_fails(self):
+    my_mock = mock.MagicMock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def teardown_test(self):
-                my_mock("teardown_test")
+    class MockBaseTest(base_test.BaseTestClass):
+      def teardown_test(self):
+        my_mock("teardown_test")
 
-            def on_pass(self, record):
-                never_call()
+      def on_pass(self, record):
+        never_call()
 
-            def test_something(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+      def test_something(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        my_mock.assert_called_once_with("teardown_test")
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    my_mock.assert_called_once_with("teardown_test")
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_on_fail_executed_if_teardown_test_fails(self):
-        my_mock = mock.MagicMock()
+  def test_on_fail_executed_if_teardown_test_fails(self):
+    my_mock = mock.MagicMock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def on_fail(self, record):
-                my_mock("on_fail")
+    class MockBaseTest(base_test.BaseTestClass):
+      def on_fail(self, record):
+        my_mock("on_fail")
 
-            def on_pass(self, record):
-                never_call()
+      def on_pass(self, record):
+        never_call()
 
-            def teardown_test(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+      def teardown_test(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        my_mock.assert_called_once_with('on_fail')
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    my_mock.assert_called_once_with('on_fail')
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_on_fail_executed_if_test_fails(self):
-        my_mock = mock.MagicMock()
+  def test_on_fail_executed_if_test_fails(self):
+    my_mock = mock.MagicMock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def on_fail(self, record):
-                assert self.current_test_info.name == 'test_something'
-                my_mock("on_fail")
+    class MockBaseTest(base_test.BaseTestClass):
+      def on_fail(self, record):
+        assert self.current_test_info.name == 'test_something'
+        my_mock("on_fail")
 
-            def on_pass(self, record):
-                never_call()
+      def on_pass(self, record):
+        never_call()
 
-            def test_something(self):
-                asserts.assert_true(False, MSG_EXPECTED_EXCEPTION)
+      def test_something(self):
+        asserts.assert_true(False, MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        my_mock.assert_called_once_with("on_fail")
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
-        expected_summary = ("Error 0, Executed 1, Failed 1, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    my_mock.assert_called_once_with("on_fail")
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
+    expected_summary = ("Error 0, Executed 1, Failed 1, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_procedure_function_gets_correct_record(self):
-        on_fail_mock = mock.MagicMock()
+  def test_procedure_function_gets_correct_record(self):
+    on_fail_mock = mock.MagicMock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def on_fail(self, record):
-                on_fail_mock.record = record
+    class MockBaseTest(base_test.BaseTestClass):
+      def on_fail(self, record):
+        on_fail_mock.record = record
 
-            def test_something(self):
-                asserts.fail(MSG_EXPECTED_EXCEPTION)
+      def test_something(self):
+        asserts.fail(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, 'test_something')
-        self.assertEqual(on_fail_mock.record.test_name,
-                         actual_record.test_name)
-        self.assertEqual(on_fail_mock.record.begin_time,
-                         actual_record.begin_time)
-        self.assertEqual(on_fail_mock.record.end_time, actual_record.end_time)
-        self.assertEqual(on_fail_mock.record.stacktrace,
-                         actual_record.stacktrace)
-        self.assertEqual(on_fail_mock.record.extras, actual_record.extras)
-        self.assertEqual(on_fail_mock.record.extra_errors,
-                         actual_record.extra_errors)
-        # But they are not the same object.
-        self.assertIsNot(on_fail_mock.record, actual_record)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, 'test_something')
+    self.assertEqual(on_fail_mock.record.test_name,
+             actual_record.test_name)
+    self.assertEqual(on_fail_mock.record.begin_time,
+             actual_record.begin_time)
+    self.assertEqual(on_fail_mock.record.end_time, actual_record.end_time)
+    self.assertEqual(on_fail_mock.record.stacktrace,
+             actual_record.stacktrace)
+    self.assertEqual(on_fail_mock.record.extras, actual_record.extras)
+    self.assertEqual(on_fail_mock.record.extra_errors,
+             actual_record.extra_errors)
+    # But they are not the same object.
+    self.assertIsNot(on_fail_mock.record, actual_record)
 
-    def test_on_fail_cannot_modify_original_record(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def on_fail(self, record):
-                record.test_name = 'blah'
+  def test_on_fail_cannot_modify_original_record(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def on_fail(self, record):
+        record.test_name = 'blah'
 
-            def test_something(self):
-                asserts.assert_true(False, MSG_EXPECTED_EXCEPTION)
+      def test_something(self):
+        asserts.assert_true(False, MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, 'test_something')
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, 'test_something')
 
-    def test_on_fail_executed_if_both_test_and_teardown_test_fails(self):
-        on_fail_mock = mock.MagicMock()
+  def test_on_fail_executed_if_both_test_and_teardown_test_fails(self):
+    on_fail_mock = mock.MagicMock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def on_fail(self, record):
-                on_fail_mock("on_fail")
+    class MockBaseTest(base_test.BaseTestClass):
+      def on_fail(self, record):
+        on_fail_mock("on_fail")
 
-            def on_pass(self, record):
-                never_call()
+      def on_pass(self, record):
+        never_call()
 
-            def teardown_test(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION + 'ha')
+      def teardown_test(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION + 'ha')
 
-            def test_something(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+      def test_something(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        on_fail_mock.assert_called_once_with("on_fail")
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extra_errors['teardown_test'].details,
-                         'This is an expected exception.ha')
-        self.assertIsNone(actual_record.extras)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    on_fail_mock.assert_called_once_with("on_fail")
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extra_errors['teardown_test'].details,
+             'This is an expected exception.ha')
+    self.assertIsNone(actual_record.extras)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_on_fail_executed_if_setup_test_fails_by_exception(self):
-        my_mock = mock.MagicMock()
+  def test_on_fail_executed_if_setup_test_fails_by_exception(self):
+    my_mock = mock.MagicMock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_test(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_test(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-            def on_fail(self, record):
-                my_mock("on_fail")
+      def on_fail(self, record):
+        my_mock("on_fail")
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        my_mock.assert_called_once_with("on_fail")
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    my_mock.assert_called_once_with("on_fail")
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_on_fail_executed_if_setup_class_fails_by_exception(self):
-        my_mock = mock.MagicMock()
+  def test_on_fail_executed_if_setup_class_fails_by_exception(self):
+    my_mock = mock.MagicMock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_class(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_class(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-            def on_fail(self, record):
-                my_mock("on_fail")
+      def on_fail(self, record):
+        my_mock("on_fail")
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        my_mock.assert_called_once_with("on_fail")
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, 'setup_class')
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
-        expected_summary = ("Error 1, Executed 0, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 1")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    my_mock.assert_called_once_with("on_fail")
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, 'setup_class')
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
+    expected_summary = ("Error 1, Executed 0, Failed 0, Passed 0, "
+              "Requested 1, Skipped 1")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_on_fail_triggered_by_setup_class_failure_then_fail_too(self):
-        """Errors thrown from on_fail should be captured."""
+  def test_on_fail_triggered_by_setup_class_failure_then_fail_too(self):
+    """Errors thrown from on_fail should be captured."""
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_class(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_class(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-            def on_fail(self, record):
-                raise Exception('Failure in on_fail.')
+      def on_fail(self, record):
+        raise Exception('Failure in on_fail.')
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        setup_class_record = bt_cls.results.error[0]
-        self.assertEqual(setup_class_record.test_name, 'setup_class')
-        self.assertEqual(setup_class_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(setup_class_record.extra_errors['on_fail'].details,
-                         'Failure in on_fail.')
-        expected_summary = ("Error 1, Executed 0, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 1")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    setup_class_record = bt_cls.results.error[0]
+    self.assertEqual(setup_class_record.test_name, 'setup_class')
+    self.assertEqual(setup_class_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(setup_class_record.extra_errors['on_fail'].details,
+             'Failure in on_fail.')
+    expected_summary = ("Error 1, Executed 0, Failed 0, Passed 0, "
+              "Requested 1, Skipped 1")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_failure_to_call_procedure_function_is_recorded(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def on_fail(self):
-                pass
+  def test_failure_to_call_procedure_function_is_recorded(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def on_fail(self):
+        pass
 
-            def test_something(self):
-                asserts.assert_true(False, MSG_EXPECTED_EXCEPTION)
+      def test_something(self):
+        asserts.assert_true(False, MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.failed[0]
-        self.assertIn('on_fail', actual_record.extra_errors)
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
-        expected_summary = ("Error 0, Executed 1, Failed 1, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.failed[0]
+    self.assertIn('on_fail', actual_record.extra_errors)
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
+    expected_summary = ("Error 0, Executed 1, Failed 1, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_failure_in_procedure_functions_is_recorded(self):
-        expected_msg = "Something failed in on_pass."
+  def test_failure_in_procedure_functions_is_recorded(self):
+    expected_msg = "Something failed in on_pass."
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def on_pass(self, record):
-                raise Exception(expected_msg)
+    class MockBaseTest(base_test.BaseTestClass):
+      def on_pass(self, record):
+        raise Exception(expected_msg)
 
-            def test_something(self):
-                asserts.explicit_pass(MSG_EXPECTED_EXCEPTION)
+      def test_something(self):
+        asserts.explicit_pass(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.extra_errors['on_pass'].details,
-                         expected_msg)
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.extra_errors['on_pass'].details,
+             expected_msg)
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_both_teardown_and_test_body_raise_exceptions(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def teardown_test(self):
-                asserts.assert_true(False, MSG_EXPECTED_EXCEPTION)
+  def test_both_teardown_and_test_body_raise_exceptions(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def teardown_test(self):
+        asserts.assert_true(False, MSG_EXPECTED_EXCEPTION)
 
-            def test_something(self):
-                raise Exception("Test Body Exception.")
+      def test_something(self):
+        raise Exception("Test Body Exception.")
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, "Test Body Exception.")
-        self.assertIsNone(actual_record.extras)
-        self.assertEqual(actual_record.extra_errors['teardown_test'].details,
-                         MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extra_errors['teardown_test'].extras)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, "Test Body Exception.")
+    self.assertIsNone(actual_record.extras)
+    self.assertEqual(actual_record.extra_errors['teardown_test'].details,
+             MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extra_errors['teardown_test'].extras)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_exception_objects_in_record(self):
-        """Checks that the exception objects are correctly tallied.
-        """
-        expected_termination_signal = Exception('Test Body Exception.')
-        expected_extra_error = Exception('teardown_test Exception.')
+  def test_exception_objects_in_record(self):
+    """Checks that the exception objects are correctly tallied.
+    """
+    expected_termination_signal = Exception('Test Body Exception.')
+    expected_extra_error = Exception('teardown_test Exception.')
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def teardown_test(self):
-                raise expected_extra_error
+    class MockBaseTest(base_test.BaseTestClass):
+      def teardown_test(self):
+        raise expected_extra_error
 
-            def test_something(self):
-                raise expected_termination_signal
+      def test_something(self):
+        raise expected_termination_signal
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        self.assertIs(actual_record.termination_signal.exception,
-                      expected_termination_signal)
-        self.assertIsNotNone(actual_record.termination_signal.stacktrace)
-        self.assertEqual(len(actual_record.extra_errors), 1)
-        extra_error = actual_record.extra_errors['teardown_test']
-        self.assertIs(extra_error.exception, expected_extra_error)
-        self.assertIsNotNone(extra_error.stacktrace)
-        self.assertIsNone(actual_record.extras)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    self.assertIs(actual_record.termination_signal.exception,
+            expected_termination_signal)
+    self.assertIsNotNone(actual_record.termination_signal.stacktrace)
+    self.assertEqual(len(actual_record.extra_errors), 1)
+    extra_error = actual_record.extra_errors['teardown_test']
+    self.assertIs(extra_error.exception, expected_extra_error)
+    self.assertIsNotNone(extra_error.stacktrace)
+    self.assertIsNone(actual_record.extras)
 
-    def test_promote_extra_errors_to_termination_signal(self):
-        """If no termination signal is specified, use the first extra error as
-        the termination signal.
-        """
-        expected_extra_error = Exception('teardown_test Exception.')
+  def test_promote_extra_errors_to_termination_signal(self):
+    """If no termination signal is specified, use the first extra error as
+    the termination signal.
+    """
+    expected_extra_error = Exception('teardown_test Exception.')
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def teardown_test(self):
-                raise expected_extra_error
+    class MockBaseTest(base_test.BaseTestClass):
+      def teardown_test(self):
+        raise expected_extra_error
 
-            def test_something(self):
-                pass
+      def test_something(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        self.assertFalse(actual_record.extra_errors)
-        self.assertEqual(actual_record.details, 'teardown_test Exception.')
-        self.assertIsNotNone(actual_record.stacktrace)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    self.assertFalse(actual_record.extra_errors)
+    self.assertEqual(actual_record.details, 'teardown_test Exception.')
+    self.assertIsNotNone(actual_record.stacktrace)
 
-    def test_explicit_pass_but_teardown_test_raises_an_exception(self):
-        """Test record result should be marked as ERROR as opposed to PASS.
-        """
+  def test_explicit_pass_but_teardown_test_raises_an_exception(self):
+    """Test record result should be marked as ERROR as opposed to PASS.
+    """
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def teardown_test(self):
-                asserts.assert_true(False, MSG_EXPECTED_EXCEPTION)
+    class MockBaseTest(base_test.BaseTestClass):
+      def teardown_test(self):
+        asserts.assert_true(False, MSG_EXPECTED_EXCEPTION)
 
-            def test_something(self):
-                asserts.explicit_pass('Test Passed!')
+      def test_something(self):
+        asserts.explicit_pass('Test Passed!')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, 'Test Passed!')
-        self.assertIsNone(actual_record.extras)
-        self.assertEqual(actual_record.extra_errors['teardown_test'].details,
-                         MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extra_errors['teardown_test'].extras)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, 'Test Passed!')
+    self.assertIsNone(actual_record.extras)
+    self.assertEqual(actual_record.extra_errors['teardown_test'].details,
+             MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extra_errors['teardown_test'].extras)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_on_pass_cannot_modify_original_record(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def on_pass(self, record):
-                record.test_name = 'blah'
+  def test_on_pass_cannot_modify_original_record(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def on_pass(self, record):
+        record.test_name = 'blah'
 
-            def test_something(self):
-                asserts.explicit_pass('Extra pass!')
+      def test_something(self):
+        asserts.explicit_pass('Extra pass!')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.test_name, 'test_something')
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.test_name, 'test_something')
 
-    def test_on_pass_raise_exception(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def on_pass(self, record):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+  def test_on_pass_raise_exception(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def on_pass(self, record):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-            def test_something(self):
-                asserts.explicit_pass(MSG_EXPECTED_EXCEPTION,
-                                      extras=MOCK_EXTRA)
+      def test_something(self):
+        asserts.explicit_pass(MSG_EXPECTED_EXCEPTION,
+                    extras=MOCK_EXTRA)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
-        self.assertEqual(actual_record.extra_errors['on_pass'].details,
-                         MSG_EXPECTED_EXCEPTION)
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    self.assertEqual(actual_record.extra_errors['on_pass'].details,
+             MSG_EXPECTED_EXCEPTION)
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_on_fail_raise_exception(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def on_fail(self, record):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+  def test_on_fail_raise_exception(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def on_fail(self, record):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-            def test_something(self):
-                asserts.fail(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
+      def test_something(self):
+        asserts.fail(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, self.mock_test_name)
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
-        self.assertEqual(actual_record.extra_errors['on_fail'].details,
-                         MSG_EXPECTED_EXCEPTION)
-        expected_summary = ("Error 0, Executed 1, Failed 1, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, self.mock_test_name)
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    self.assertEqual(actual_record.extra_errors['on_fail'].details,
+             MSG_EXPECTED_EXCEPTION)
+    expected_summary = ("Error 0, Executed 1, Failed 1, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_abort_class_setup_class(self):
-        """A class was intentionally aborted by the test.
+  def test_abort_class_setup_class(self):
+    """A class was intentionally aborted by the test.
 
-        This is not considered an error as the abort class is used as a skip
-        signal for the entire class, which is different from raising other
-        exceptions in `setup_class`.
-        """
+    This is not considered an error as the abort class is used as a skip
+    signal for the entire class, which is different from raising other
+    exceptions in `setup_class`.
+    """
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_class(self):
-                asserts.abort_class(MSG_EXPECTED_EXCEPTION)
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_class(self):
+        asserts.abort_class(MSG_EXPECTED_EXCEPTION)
 
-            def test_1(self):
-                never_call()
+      def test_1(self):
+        never_call()
 
-            def test_2(self):
-                never_call()
+      def test_2(self):
+        never_call()
 
-            def test_3(self):
-                never_call()
+      def test_3(self):
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_1", "test_2", "test_3"])
-        self.assertEqual(len(bt_cls.results.skipped), 3)
-        self.assertEqual(bt_cls.results.summary_str(),
-                         ("Error 0, Executed 0, Failed 0, Passed 0, "
-                          "Requested 3, Skipped 3"))
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+    self.assertEqual(len(bt_cls.results.skipped), 3)
+    self.assertEqual(bt_cls.results.summary_str(),
+             ("Error 0, Executed 0, Failed 0, Passed 0, "
+              "Requested 3, Skipped 3"))
 
-    def test_abort_class_in_setup_test(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_test(self):
-                asserts.abort_class(MSG_EXPECTED_EXCEPTION)
+  def test_abort_class_in_setup_test(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_test(self):
+        asserts.abort_class(MSG_EXPECTED_EXCEPTION)
 
-            def test_1(self):
-                never_call()
+      def test_1(self):
+        never_call()
 
-            def test_2(self):
-                never_call()
+      def test_2(self):
+        never_call()
 
-            def test_3(self):
-                never_call()
+      def test_3(self):
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_1", "test_2", "test_3"])
-        self.assertEqual(len(bt_cls.results.skipped), 2)
-        self.assertEqual(bt_cls.results.summary_str(),
-                         ("Error 0, Executed 1, Failed 1, Passed 0, "
-                          "Requested 3, Skipped 2"))
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+    self.assertEqual(len(bt_cls.results.skipped), 2)
+    self.assertEqual(bt_cls.results.summary_str(),
+             ("Error 0, Executed 1, Failed 1, Passed 0, "
+              "Requested 3, Skipped 2"))
 
-    def test_abort_class_in_on_fail(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_1(self):
-                asserts.fail(MSG_EXPECTED_EXCEPTION)
+  def test_abort_class_in_on_fail(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_1(self):
+        asserts.fail(MSG_EXPECTED_EXCEPTION)
 
-            def test_2(self):
-                never_call()
+      def test_2(self):
+        never_call()
 
-            def test_3(self):
-                never_call()
+      def test_3(self):
+        never_call()
 
-            def on_fail(self, record):
-                asserts.abort_class(MSG_EXPECTED_EXCEPTION)
+      def on_fail(self, record):
+        asserts.abort_class(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_1", "test_2", "test_3"])
-        self.assertEqual(len(bt_cls.results.skipped), 2)
-        self.assertEqual(bt_cls.results.summary_str(),
-                         ("Error 0, Executed 1, Failed 1, Passed 0, "
-                          "Requested 3, Skipped 2"))
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+    self.assertEqual(len(bt_cls.results.skipped), 2)
+    self.assertEqual(bt_cls.results.summary_str(),
+             ("Error 0, Executed 1, Failed 1, Passed 0, "
+              "Requested 3, Skipped 2"))
 
-    def test_setup_and_teardown_execution_count(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                pass
+  def test_setup_and_teardown_execution_count(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        pass
 
-            def test_func2(self):
-                pass
+      def test_func2(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.setup_class = mock.Mock()
-        bt_cls.teardown_class = mock.Mock()
-        bt_cls.setup_test = mock.Mock()
-        bt_cls.teardown_test = mock.Mock()
-        bt_cls.run()
-        self.assertEqual(bt_cls.setup_class.call_count, 1)
-        self.assertEqual(bt_cls.teardown_class.call_count, 1)
-        self.assertEqual(bt_cls.setup_test.call_count, 2)
-        self.assertEqual(bt_cls.teardown_test.call_count, 2)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.setup_class = mock.Mock()
+    bt_cls.teardown_class = mock.Mock()
+    bt_cls.setup_test = mock.Mock()
+    bt_cls.teardown_test = mock.Mock()
+    bt_cls.run()
+    self.assertEqual(bt_cls.setup_class.call_count, 1)
+    self.assertEqual(bt_cls.teardown_class.call_count, 1)
+    self.assertEqual(bt_cls.setup_test.call_count, 2)
+    self.assertEqual(bt_cls.teardown_test.call_count, 2)
 
-    def test_abort_class_in_test(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_1(self):
-                pass
+  def test_abort_class_in_test(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_1(self):
+        pass
 
-            def test_2(self):
-                asserts.abort_class(MSG_EXPECTED_EXCEPTION)
-                never_call()
+      def test_2(self):
+        asserts.abort_class(MSG_EXPECTED_EXCEPTION)
+        never_call()
 
-            def test_3(self):
-                never_call()
+      def test_3(self):
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_1", "test_2", "test_3"])
-        self.assertEqual(bt_cls.results.passed[0].test_name, "test_1")
-        self.assertEqual(bt_cls.results.failed[0].details,
-                         MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(bt_cls.results.summary_str(),
-                         ("Error 0, Executed 2, Failed 1, Passed 1, "
-                          "Requested 3, Skipped 1"))
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+    self.assertEqual(bt_cls.results.passed[0].test_name, "test_1")
+    self.assertEqual(bt_cls.results.failed[0].details,
+             MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(bt_cls.results.summary_str(),
+             ("Error 0, Executed 2, Failed 1, Passed 1, "
+              "Requested 3, Skipped 1"))
 
-    def test_abort_all_in_setup_class(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_class(self):
-                asserts.abort_all(MSG_EXPECTED_EXCEPTION)
+  def test_abort_all_in_setup_class(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_class(self):
+        asserts.abort_all(MSG_EXPECTED_EXCEPTION)
 
-            def test_1(self):
-                never_call()
+      def test_1(self):
+        never_call()
 
-            def test_2(self):
-                never_call()
+      def test_2(self):
+        never_call()
 
-            def test_3(self):
-                never_call()
+      def test_3(self):
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        with self.assertRaisesRegex(signals.TestAbortAll,
-                                    MSG_EXPECTED_EXCEPTION) as context:
-            bt_cls.run(test_names=["test_1", "test_2", "test_3"])
-        self.assertTrue(hasattr(context.exception, 'results'))
-        self.assertEqual(bt_cls.results.summary_str(),
-                         ("Error 0, Executed 0, Failed 0, Passed 0, "
-                          "Requested 3, Skipped 3"))
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    with self.assertRaisesRegex(signals.TestAbortAll,
+                  MSG_EXPECTED_EXCEPTION) as context:
+      bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+    self.assertTrue(hasattr(context.exception, 'results'))
+    self.assertEqual(bt_cls.results.summary_str(),
+             ("Error 0, Executed 0, Failed 0, Passed 0, "
+              "Requested 3, Skipped 3"))
 
-    def test_abort_all_in_teardown_class(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_1(self):
-                pass
+  def test_abort_all_in_teardown_class(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_1(self):
+        pass
 
-            def test_2(self):
-                pass
+      def test_2(self):
+        pass
 
-            def teardown_class(self):
-                asserts.abort_all(MSG_EXPECTED_EXCEPTION)
+      def teardown_class(self):
+        asserts.abort_all(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        with self.assertRaisesRegex(signals.TestAbortAll,
-                                    MSG_EXPECTED_EXCEPTION) as context:
-            bt_cls.run(test_names=["test_1", "test_2"])
-        self.assertTrue(hasattr(context.exception, 'results'))
-        self.assertEqual(bt_cls.results.summary_str(),
-                         ("Error 0, Executed 2, Failed 0, Passed 2, "
-                          "Requested 2, Skipped 0"))
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    with self.assertRaisesRegex(signals.TestAbortAll,
+                  MSG_EXPECTED_EXCEPTION) as context:
+      bt_cls.run(test_names=["test_1", "test_2"])
+    self.assertTrue(hasattr(context.exception, 'results'))
+    self.assertEqual(bt_cls.results.summary_str(),
+             ("Error 0, Executed 2, Failed 0, Passed 2, "
+              "Requested 2, Skipped 0"))
 
-    def test_abort_all_in_setup_test(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_test(self):
-                asserts.abort_all(MSG_EXPECTED_EXCEPTION)
+  def test_abort_all_in_setup_test(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_test(self):
+        asserts.abort_all(MSG_EXPECTED_EXCEPTION)
 
-            def test_1(self):
-                never_call()
+      def test_1(self):
+        never_call()
 
-            def test_2(self):
-                never_call()
+      def test_2(self):
+        never_call()
 
-            def test_3(self):
-                never_call()
+      def test_3(self):
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        with self.assertRaisesRegex(signals.TestAbortAll,
-                                    MSG_EXPECTED_EXCEPTION) as context:
-            bt_cls.run(test_names=["test_1", "test_2", "test_3"])
-        self.assertTrue(hasattr(context.exception, 'results'))
-        self.assertEqual(bt_cls.results.summary_str(),
-                         ("Error 0, Executed 1, Failed 1, Passed 0, "
-                          "Requested 3, Skipped 2"))
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    with self.assertRaisesRegex(signals.TestAbortAll,
+                  MSG_EXPECTED_EXCEPTION) as context:
+      bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+    self.assertTrue(hasattr(context.exception, 'results'))
+    self.assertEqual(bt_cls.results.summary_str(),
+             ("Error 0, Executed 1, Failed 1, Passed 0, "
+              "Requested 3, Skipped 2"))
 
-    def test_abort_all_in_on_fail(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_1(self):
-                asserts.fail(MSG_EXPECTED_EXCEPTION)
+  def test_abort_all_in_on_fail(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_1(self):
+        asserts.fail(MSG_EXPECTED_EXCEPTION)
 
-            def test_2(self):
-                never_call()
+      def test_2(self):
+        never_call()
 
-            def test_3(self):
-                never_call()
+      def test_3(self):
+        never_call()
 
-            def on_fail(self, record):
-                asserts.abort_all(MSG_EXPECTED_EXCEPTION)
+      def on_fail(self, record):
+        asserts.abort_all(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        with self.assertRaisesRegex(signals.TestAbortAll,
-                                    MSG_EXPECTED_EXCEPTION) as context:
-            bt_cls.run(test_names=["test_1", "test_2", "test_3"])
-        self.assertTrue(hasattr(context.exception, 'results'))
-        self.assertEqual(bt_cls.results.summary_str(),
-                         ("Error 0, Executed 1, Failed 1, Passed 0, "
-                          "Requested 3, Skipped 2"))
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    with self.assertRaisesRegex(signals.TestAbortAll,
+                  MSG_EXPECTED_EXCEPTION) as context:
+      bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+    self.assertTrue(hasattr(context.exception, 'results'))
+    self.assertEqual(bt_cls.results.summary_str(),
+             ("Error 0, Executed 1, Failed 1, Passed 0, "
+              "Requested 3, Skipped 2"))
 
-    def test_abort_all_in_on_fail_from_setup_class(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_class(self):
-                asserts.fail(MSG_UNEXPECTED_EXCEPTION)
+  def test_abort_all_in_on_fail_from_setup_class(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_class(self):
+        asserts.fail(MSG_UNEXPECTED_EXCEPTION)
 
-            def test_1(self):
-                never_call()
+      def test_1(self):
+        never_call()
 
-            def test_2(self):
-                never_call()
+      def test_2(self):
+        never_call()
 
-            def test_3(self):
-                never_call()
+      def test_3(self):
+        never_call()
 
-            def on_fail(self, record):
-                asserts.abort_all(MSG_EXPECTED_EXCEPTION)
+      def on_fail(self, record):
+        asserts.abort_all(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        with self.assertRaisesRegex(signals.TestAbortAll,
-                                    MSG_EXPECTED_EXCEPTION) as context:
-            bt_cls.run(test_names=["test_1", "test_2", "test_3"])
-        setup_class_record = bt_cls.results.error[0]
-        self.assertEqual(setup_class_record.test_name, 'setup_class')
-        self.assertTrue(hasattr(context.exception, 'results'))
-        self.assertEqual(bt_cls.results.summary_str(),
-                         ("Error 1, Executed 0, Failed 0, Passed 0, "
-                          "Requested 3, Skipped 3"))
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    with self.assertRaisesRegex(signals.TestAbortAll,
+                  MSG_EXPECTED_EXCEPTION) as context:
+      bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+    setup_class_record = bt_cls.results.error[0]
+    self.assertEqual(setup_class_record.test_name, 'setup_class')
+    self.assertTrue(hasattr(context.exception, 'results'))
+    self.assertEqual(bt_cls.results.summary_str(),
+             ("Error 1, Executed 0, Failed 0, Passed 0, "
+              "Requested 3, Skipped 3"))
 
-    def test_abort_all_in_test(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_1(self):
-                pass
+  def test_abort_all_in_test(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_1(self):
+        pass
 
-            def test_2(self):
-                asserts.abort_all(MSG_EXPECTED_EXCEPTION)
-                never_call()
+      def test_2(self):
+        asserts.abort_all(MSG_EXPECTED_EXCEPTION)
+        never_call()
 
-            def test_3(self):
-                never_call()
+      def test_3(self):
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        with self.assertRaisesRegex(signals.TestAbortAll,
-                                    MSG_EXPECTED_EXCEPTION) as context:
-            bt_cls.run(test_names=["test_1", "test_2", "test_3"])
-        self.assertTrue(hasattr(context.exception, 'results'))
-        self.assertEqual(bt_cls.results.passed[0].test_name, "test_1")
-        self.assertEqual(bt_cls.results.failed[0].details,
-                         MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(bt_cls.results.summary_str(),
-                         ("Error 0, Executed 2, Failed 1, Passed 1, "
-                          "Requested 3, Skipped 1"))
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    with self.assertRaisesRegex(signals.TestAbortAll,
+                  MSG_EXPECTED_EXCEPTION) as context:
+      bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+    self.assertTrue(hasattr(context.exception, 'results'))
+    self.assertEqual(bt_cls.results.passed[0].test_name, "test_1")
+    self.assertEqual(bt_cls.results.failed[0].details,
+             MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(bt_cls.results.summary_str(),
+             ("Error 0, Executed 2, Failed 1, Passed 1, "
+              "Requested 3, Skipped 1"))
 
-    def test_uncaught_exception(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
-                never_call()
+  def test_uncaught_exception(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_func"])
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
-        # Stacktraces can vary. Just check for key words
-        self.assertIn('test_method()', actual_record.stacktrace)
-        self.assertIn('raise Exception(MSG_EXPECTED_EXCEPTION)',
-                      actual_record.stacktrace)
-        self.assertIn('Exception: This is an expected exception.',
-                      actual_record.stacktrace)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_func"])
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
+    # Stacktraces can vary. Just check for key words
+    self.assertIn('test_method()', actual_record.stacktrace)
+    self.assertIn('raise Exception(MSG_EXPECTED_EXCEPTION)',
+            actual_record.stacktrace)
+    self.assertIn('Exception: This is an expected exception.',
+            actual_record.stacktrace)
 
-    def test_fail(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                asserts.fail(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
-                never_call()
+  def test_fail(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        asserts.fail(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_func"])
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_func"])
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_assert_true(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                asserts.assert_true(False,
-                                    MSG_EXPECTED_EXCEPTION,
-                                    extras=MOCK_EXTRA)
-                never_call()
+  def test_assert_true(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        asserts.assert_true(False,
+                  MSG_EXPECTED_EXCEPTION,
+                  extras=MOCK_EXTRA)
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_func"])
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_func"])
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_assert_equal_pass(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                asserts.assert_equal(1, 1, extras=MOCK_EXTRA)
+  def test_assert_equal_pass(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        asserts.assert_equal(1, 1, extras=MOCK_EXTRA)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertIsNone(actual_record.details)
-        self.assertIsNone(actual_record.extras)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertIsNone(actual_record.details)
+    self.assertIsNone(actual_record.extras)
 
-    def test_assert_equal_fail(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                asserts.assert_equal(1, 2, extras=MOCK_EXTRA)
+  def test_assert_equal_fail(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        asserts.assert_equal(1, 2, extras=MOCK_EXTRA)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertEqual(actual_record.details, "1 != 2")
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertEqual(actual_record.details, "1 != 2")
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_assert_equal_fail_with_msg(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                asserts.assert_equal(1,
-                                     2,
-                                     msg=MSG_EXPECTED_EXCEPTION,
-                                     extras=MOCK_EXTRA)
+  def test_assert_equal_fail_with_msg(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        asserts.assert_equal(1,
+                   2,
+                   msg=MSG_EXPECTED_EXCEPTION,
+                   extras=MOCK_EXTRA)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        expected_msg = "1 != 2 " + MSG_EXPECTED_EXCEPTION
-        self.assertEqual(actual_record.details, expected_msg)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    expected_msg = "1 != 2 " + MSG_EXPECTED_EXCEPTION
+    self.assertEqual(actual_record.details, expected_msg)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_assert_raises_pass(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                with asserts.assert_raises(SomeError, extras=MOCK_EXTRA):
-                    raise SomeError(MSG_EXPECTED_EXCEPTION)
+  def test_assert_raises_pass(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        with asserts.assert_raises(SomeError, extras=MOCK_EXTRA):
+          raise SomeError(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertIsNone(actual_record.details)
-        self.assertIsNone(actual_record.extras)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertIsNone(actual_record.details)
+    self.assertIsNone(actual_record.extras)
 
-    def test_assert_raises_fail_with_noop(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                with asserts.assert_raises(SomeError, extras=MOCK_EXTRA):
-                    pass
+  def test_assert_raises_fail_with_noop(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        with asserts.assert_raises(SomeError, extras=MOCK_EXTRA):
+          pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertEqual(actual_record.details, "SomeError not raised")
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertEqual(actual_record.details, "SomeError not raised")
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_assert_raises_fail_with_wrong_error(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                with asserts.assert_raises(SomeError, extras=MOCK_EXTRA):
-                    raise AttributeError(MSG_UNEXPECTED_EXCEPTION)
+  def test_assert_raises_fail_with_wrong_error(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        with asserts.assert_raises(SomeError, extras=MOCK_EXTRA):
+          raise AttributeError(MSG_UNEXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertEqual(actual_record.details, MSG_UNEXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertEqual(actual_record.details, MSG_UNEXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
 
-    def test_assert_raises_regex_pass(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                with asserts.assert_raises_regex(
-                        SomeError,
-                        expected_regex=MSG_EXPECTED_EXCEPTION,
-                        extras=MOCK_EXTRA):
-                    raise SomeError(MSG_EXPECTED_EXCEPTION)
+  def test_assert_raises_regex_pass(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        with asserts.assert_raises_regex(
+            SomeError,
+            expected_regex=MSG_EXPECTED_EXCEPTION,
+            extras=MOCK_EXTRA):
+          raise SomeError(MSG_EXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertIsNone(actual_record.details)
-        self.assertIsNone(actual_record.extras)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertIsNone(actual_record.details)
+    self.assertIsNone(actual_record.extras)
 
-    def test_assert_raises_regex_fail_with_noop(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                with asserts.assert_raises_regex(
-                        SomeError,
-                        expected_regex=MSG_EXPECTED_EXCEPTION,
-                        extras=MOCK_EXTRA):
-                    pass
+  def test_assert_raises_regex_fail_with_noop(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        with asserts.assert_raises_regex(
+            SomeError,
+            expected_regex=MSG_EXPECTED_EXCEPTION,
+            extras=MOCK_EXTRA):
+          pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertEqual(actual_record.details, "SomeError not raised")
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertEqual(actual_record.details, "SomeError not raised")
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_assert_raises_fail_with_wrong_regex(self):
-        wrong_msg = "ha"
+  def test_assert_raises_fail_with_wrong_regex(self):
+    wrong_msg = "ha"
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                with asserts.assert_raises_regex(
-                        SomeError,
-                        expected_regex=MSG_EXPECTED_EXCEPTION,
-                        extras=MOCK_EXTRA):
-                    raise SomeError(wrong_msg)
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        with asserts.assert_raises_regex(
+            SomeError,
+            expected_regex=MSG_EXPECTED_EXCEPTION,
+            extras=MOCK_EXTRA):
+          raise SomeError(wrong_msg)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        expected_details = ('"This is an expected exception." does not match '
-                            '"%s"') % wrong_msg
-        self.assertEqual(actual_record.details, expected_details)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    expected_details = ('"This is an expected exception." does not match '
+              '"%s"') % wrong_msg
+    self.assertEqual(actual_record.details, expected_details)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_assert_raises_regex_fail_with_wrong_error(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                with asserts.assert_raises_regex(
-                        SomeError,
-                        expected_regex=MSG_EXPECTED_EXCEPTION,
-                        extras=MOCK_EXTRA):
-                    raise AttributeError(MSG_UNEXPECTED_EXCEPTION)
+  def test_assert_raises_regex_fail_with_wrong_error(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        with asserts.assert_raises_regex(
+            SomeError,
+            expected_regex=MSG_EXPECTED_EXCEPTION,
+            extras=MOCK_EXTRA):
+          raise AttributeError(MSG_UNEXPECTED_EXCEPTION)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertEqual(actual_record.details, MSG_UNEXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertEqual(actual_record.details, MSG_UNEXPECTED_EXCEPTION)
+    self.assertIsNone(actual_record.extras)
 
-    def test_explicit_pass(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                asserts.explicit_pass(MSG_EXPECTED_EXCEPTION,
-                                      extras=MOCK_EXTRA)
-                never_call()
+  def test_explicit_pass(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        asserts.explicit_pass(MSG_EXPECTED_EXCEPTION,
+                    extras=MOCK_EXTRA)
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_func"])
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_func"])
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_implicit_pass(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                pass
+  def test_implicit_pass(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_func"])
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertIsNone(actual_record.details)
-        self.assertIsNone(actual_record.extras)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_func"])
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertIsNone(actual_record.details)
+    self.assertIsNone(actual_record.extras)
 
-    def test_skip(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                asserts.skip(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
-                never_call()
+  def test_skip(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        asserts.skip(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_func"])
-        actual_record = bt_cls.results.skipped[0]
-        self.assertIsNotNone(actual_record.begin_time)
-        self.assertIsNotNone(actual_record.end_time)
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_func"])
+    actual_record = bt_cls.results.skipped[0]
+    self.assertIsNotNone(actual_record.begin_time)
+    self.assertIsNotNone(actual_record.end_time)
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_skip_if(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                asserts.skip_if(False, MSG_UNEXPECTED_EXCEPTION)
-                asserts.skip_if(True,
-                                MSG_EXPECTED_EXCEPTION,
-                                extras=MOCK_EXTRA)
-                never_call()
+  def test_skip_if(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        asserts.skip_if(False, MSG_UNEXPECTED_EXCEPTION)
+        asserts.skip_if(True,
+                MSG_EXPECTED_EXCEPTION,
+                extras=MOCK_EXTRA)
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_func"])
-        actual_record = bt_cls.results.skipped[0]
-        self.assertIsNotNone(actual_record.begin_time)
-        self.assertIsNotNone(actual_record.end_time)
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_func"])
+    actual_record = bt_cls.results.skipped[0]
+    self.assertIsNotNone(actual_record.begin_time)
+    self.assertIsNotNone(actual_record.end_time)
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_skip_in_setup_test(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_test(self):
-                asserts.skip(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
+  def test_skip_in_setup_test(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_test(self):
+        asserts.skip(MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA)
 
-            def test_func(self):
-                never_call()
+      def test_func(self):
+        never_call()
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_func"])
-        actual_record = bt_cls.results.skipped[0]
-        self.assertIsNotNone(actual_record.begin_time)
-        self.assertIsNotNone(actual_record.end_time)
-        self.assertEqual(actual_record.test_name, "test_func")
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_func"])
+    actual_record = bt_cls.results.skipped[0]
+    self.assertIsNotNone(actual_record.begin_time)
+    self.assertIsNotNone(actual_record.end_time)
+    self.assertEqual(actual_record.test_name, "test_func")
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_expect_true(self):
-        must_call = mock.Mock()
-        must_call2 = mock.Mock()
+  def test_expect_true(self):
+    must_call = mock.Mock()
+    must_call2 = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                expects.expect_true(False,
-                                    MSG_EXPECTED_EXCEPTION,
-                                    extras=MOCK_EXTRA)
-                must_call('ha')
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        expects.expect_true(False,
+                  MSG_EXPECTED_EXCEPTION,
+                  extras=MOCK_EXTRA)
+        must_call('ha')
 
-            def on_fail(self, record):
-                must_call2('on_fail')
+      def on_fail(self, record):
+        must_call2('on_fail')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=['test_func'])
-        must_call.assert_called_once_with('ha')
-        must_call2.assert_called_once_with('on_fail')
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, 'test_func')
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=['test_func'])
+    must_call.assert_called_once_with('ha')
+    must_call2.assert_called_once_with('on_fail')
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, 'test_func')
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_expect_multiple_fails(self):
-        must_call = mock.Mock()
-        must_call2 = mock.Mock()
+  def test_expect_multiple_fails(self):
+    must_call = mock.Mock()
+    must_call2 = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                expects.expect_true(False, 'msg 1', extras='1')
-                expects.expect_true(False, 'msg 2', extras='2')
-                must_call('ha')
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        expects.expect_true(False, 'msg 1', extras='1')
+        expects.expect_true(False, 'msg 2', extras='2')
+        must_call('ha')
 
-            def on_fail(self, record):
-                must_call2('on_fail')
+      def on_fail(self, record):
+        must_call2('on_fail')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=['test_func'])
-        must_call.assert_called_once_with('ha')
-        must_call2.assert_called_once_with('on_fail')
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, 'test_func')
-        self.assertEqual(actual_record.details, 'msg 1')
-        self.assertEqual(actual_record.extras, '1')
-        self.assertEqual(len(actual_record.extra_errors), 1)
-        second_error = list(actual_record.extra_errors.values())[0]
-        self.assertEqual(second_error.details, 'msg 2')
-        self.assertEqual(second_error.extras, '2')
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=['test_func'])
+    must_call.assert_called_once_with('ha')
+    must_call2.assert_called_once_with('on_fail')
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, 'test_func')
+    self.assertEqual(actual_record.details, 'msg 1')
+    self.assertEqual(actual_record.extras, '1')
+    self.assertEqual(len(actual_record.extra_errors), 1)
+    second_error = list(actual_record.extra_errors.values())[0]
+    self.assertEqual(second_error.details, 'msg 2')
+    self.assertEqual(second_error.extras, '2')
 
-    def test_expect_two_tests(self):
-        """Errors in `expect` should not leak across tests.
-        """
-        must_call = mock.Mock()
+  def test_expect_two_tests(self):
+    """Errors in `expect` should not leak across tests.
+    """
+    must_call = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_1(self):
-                expects.expect_true(False,
-                                    MSG_EXPECTED_EXCEPTION,
-                                    extras=MOCK_EXTRA)
-                must_call('ha')
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_1(self):
+        expects.expect_true(False,
+                  MSG_EXPECTED_EXCEPTION,
+                  extras=MOCK_EXTRA)
+        must_call('ha')
 
-            def test_2(self):
-                pass
+      def test_2(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=['test_1', 'test_2'])
-        must_call.assert_called_once_with('ha')
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, 'test_1')
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
-        another_record = bt_cls.results.passed[0]
-        self.assertEqual(another_record.test_name, 'test_2')
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=['test_1', 'test_2'])
+    must_call.assert_called_once_with('ha')
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, 'test_1')
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    another_record = bt_cls.results.passed[0]
+    self.assertEqual(another_record.test_name, 'test_2')
 
-    def test_expect_no_op(self):
-        """Tests don't fail when expect is not triggered.
-        """
-        must_call = mock.Mock()
+  def test_expect_no_op(self):
+    """Tests don't fail when expect is not triggered.
+    """
+    must_call = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_1(self):
-                expects.expect_true(True,
-                                    MSG_EXPECTED_EXCEPTION,
-                                    extras=MOCK_EXTRA)
-                must_call('ha')
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_1(self):
+        expects.expect_true(True,
+                  MSG_EXPECTED_EXCEPTION,
+                  extras=MOCK_EXTRA)
+        must_call('ha')
 
-            def test_2(self):
-                expects.expect_false(False,
-                                     MSG_EXPECTED_EXCEPTION,
-                                     extras=MOCK_EXTRA)
-                must_call('ha')
+      def test_2(self):
+        expects.expect_false(False,
+                   MSG_EXPECTED_EXCEPTION,
+                   extras=MOCK_EXTRA)
+        must_call('ha')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=['test_1', 'test_2'])
-        must_call.assert_called_with('ha')
-        self.assertEqual(len(bt_cls.results.passed), 2)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=['test_1', 'test_2'])
+    must_call.assert_called_with('ha')
+    self.assertEqual(len(bt_cls.results.passed), 2)
 
-    @mock.patch('mobly.records.TestSummaryWriter.dump')
-    def test_expect_in_setup_class(self, mock_dump):
-        must_call = mock.Mock()
-        must_call2 = mock.Mock()
+  @mock.patch('mobly.records.TestSummaryWriter.dump')
+  def test_expect_in_setup_class(self, mock_dump):
+    must_call = mock.Mock()
+    must_call2 = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_class(self):
-                expects.expect_true(False,
-                                    MSG_EXPECTED_EXCEPTION,
-                                    extras=MOCK_EXTRA)
-                must_call('ha')
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_class(self):
+        expects.expect_true(False,
+                  MSG_EXPECTED_EXCEPTION,
+                  extras=MOCK_EXTRA)
+        must_call('ha')
 
-            def test_func(self):
-                pass
+      def test_func(self):
+        pass
 
-            def on_fail(self, record):
-                must_call2('on_fail')
+      def on_fail(self, record):
+        must_call2('on_fail')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        must_call.assert_called_once_with('ha')
-        must_call2.assert_called_once_with('on_fail')
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, 'setup_class')
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
-        # Verify the class record is written out correctly.
-        setup_class_dict = mock_dump.call_args_list[1][0][0]
-        self.assertIsNotNone(setup_class_dict['Begin Time'])
-        self.assertIsNotNone(setup_class_dict['End Time'])
-        self.assertEqual(setup_class_dict['Test Name'], 'setup_class')
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    must_call.assert_called_once_with('ha')
+    must_call2.assert_called_once_with('on_fail')
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, 'setup_class')
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    # Verify the class record is written out correctly.
+    setup_class_dict = mock_dump.call_args_list[1][0][0]
+    self.assertIsNotNone(setup_class_dict['Begin Time'])
+    self.assertIsNotNone(setup_class_dict['End Time'])
+    self.assertEqual(setup_class_dict['Test Name'], 'setup_class')
 
-    @mock.patch('mobly.records.TestSummaryWriter.dump')
-    def test_expect_in_setup_class_and_on_fail(self, mock_dump):
-        must_call = mock.Mock()
-        must_call2 = mock.Mock()
+  @mock.patch('mobly.records.TestSummaryWriter.dump')
+  def test_expect_in_setup_class_and_on_fail(self, mock_dump):
+    must_call = mock.Mock()
+    must_call2 = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_class(self):
-                expects.expect_true(False,
-                                    'Failure in setup_class',
-                                    extras=MOCK_EXTRA)
-                must_call('ha')
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_class(self):
+        expects.expect_true(False,
+                  'Failure in setup_class',
+                  extras=MOCK_EXTRA)
+        must_call('ha')
 
-            def test_func(self):
-                pass
+      def test_func(self):
+        pass
 
-            def on_fail(self, record):
-                expects.expect_true(False,
-                                    'Failure in on_fail',
-                                    extras=MOCK_EXTRA)
-                must_call2('on_fail')
+      def on_fail(self, record):
+        expects.expect_true(False,
+                  'Failure in on_fail',
+                  extras=MOCK_EXTRA)
+        must_call2('on_fail')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        must_call.assert_called_once_with('ha')
-        must_call2.assert_called_once_with('on_fail')
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, 'setup_class')
-        self.assertEqual(actual_record.details, 'Failure in setup_class')
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
-        on_fail_error = next(iter(actual_record.extra_errors.values()))
-        self.assertEqual(on_fail_error.details, 'Failure in on_fail')
-        self.assertEqual(on_fail_error.extras, MOCK_EXTRA)
-        # Verify the class record is written out correctly.
-        setup_class_dict = mock_dump.call_args_list[1][0][0]
-        self.assertIsNotNone(setup_class_dict['Begin Time'])
-        self.assertIsNotNone(setup_class_dict['End Time'])
-        self.assertEqual(setup_class_dict['Test Name'], 'setup_class')
-        # Verify the on_fail error is recorded in summary result.
-        extra_error_dict = next(iter(
-            setup_class_dict['Extra Errors'].values()))
-        self.assertEqual(extra_error_dict['Details'], 'Failure in on_fail')
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    must_call.assert_called_once_with('ha')
+    must_call2.assert_called_once_with('on_fail')
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, 'setup_class')
+    self.assertEqual(actual_record.details, 'Failure in setup_class')
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    on_fail_error = next(iter(actual_record.extra_errors.values()))
+    self.assertEqual(on_fail_error.details, 'Failure in on_fail')
+    self.assertEqual(on_fail_error.extras, MOCK_EXTRA)
+    # Verify the class record is written out correctly.
+    setup_class_dict = mock_dump.call_args_list[1][0][0]
+    self.assertIsNotNone(setup_class_dict['Begin Time'])
+    self.assertIsNotNone(setup_class_dict['End Time'])
+    self.assertEqual(setup_class_dict['Test Name'], 'setup_class')
+    # Verify the on_fail error is recorded in summary result.
+    extra_error_dict = next(iter(
+      setup_class_dict['Extra Errors'].values()))
+    self.assertEqual(extra_error_dict['Details'], 'Failure in on_fail')
 
-    def test_expect_in_teardown_class(self):
-        must_call = mock.Mock()
+  def test_expect_in_teardown_class(self):
+    must_call = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                pass
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        pass
 
-            def teardown_class(self):
-                expects.expect_true(False,
-                                    MSG_EXPECTED_EXCEPTION,
-                                    extras=MOCK_EXTRA)
-                must_call('ha')
+      def teardown_class(self):
+        expects.expect_true(False,
+                  MSG_EXPECTED_EXCEPTION,
+                  extras=MOCK_EXTRA)
+        must_call('ha')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        must_call.assert_called_once_with('ha')
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, 'teardown_class')
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    must_call.assert_called_once_with('ha')
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, 'teardown_class')
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_expect_in_setup_test(self):
-        must_call = mock.Mock()
-        must_call2 = mock.Mock()
+  def test_expect_in_setup_test(self):
+    must_call = mock.Mock()
+    must_call2 = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_test(self):
-                expects.expect_true(False,
-                                    MSG_EXPECTED_EXCEPTION,
-                                    extras=MOCK_EXTRA)
-                must_call('ha')
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_test(self):
+        expects.expect_true(False,
+                  MSG_EXPECTED_EXCEPTION,
+                  extras=MOCK_EXTRA)
+        must_call('ha')
 
-            def test_func(self):
-                pass
+      def test_func(self):
+        pass
 
-            def on_fail(self, record):
-                must_call2('on_fail')
+      def on_fail(self, record):
+        must_call2('on_fail')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        must_call.assert_called_once_with('ha')
-        must_call2.assert_called_once_with('on_fail')
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, 'test_func')
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    must_call.assert_called_once_with('ha')
+    must_call2.assert_called_once_with('on_fail')
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, 'test_func')
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_expect_in_teardown_test(self):
-        must_call = mock.Mock()
-        must_call2 = mock.Mock()
+  def test_expect_in_teardown_test(self):
+    must_call = mock.Mock()
+    must_call2 = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                pass
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        pass
 
-            def teardown_test(self):
-                expects.expect_true(False,
-                                    MSG_EXPECTED_EXCEPTION,
-                                    extras=MOCK_EXTRA)
-                must_call('ha')
+      def teardown_test(self):
+        expects.expect_true(False,
+                  MSG_EXPECTED_EXCEPTION,
+                  extras=MOCK_EXTRA)
+        must_call('ha')
 
-            def on_fail(self, record):
-                must_call2('on_fail')
+      def on_fail(self, record):
+        must_call2('on_fail')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=['test_func'])
-        must_call.assert_called_once_with('ha')
-        must_call2.assert_called_once_with('on_fail')
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, 'test_func')
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=['test_func'])
+    must_call.assert_called_once_with('ha')
+    must_call2.assert_called_once_with('on_fail')
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, 'test_func')
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_expect_false(self):
-        must_call = mock.Mock()
+  def test_expect_false(self):
+    must_call = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                expects.expect_false(True,
-                                     MSG_EXPECTED_EXCEPTION,
-                                     extras=MOCK_EXTRA)
-                must_call('ha')
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        expects.expect_false(True,
+                   MSG_EXPECTED_EXCEPTION,
+                   extras=MOCK_EXTRA)
+        must_call('ha')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=['test_func'])
-        must_call.assert_called_once_with('ha')
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, 'test_func')
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=['test_func'])
+    must_call.assert_called_once_with('ha')
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, 'test_func')
+    self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_expect_equal(self):
-        must_call = mock.Mock()
+  def test_expect_equal(self):
+    must_call = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                expects.expect_equal(1,
-                                     2,
-                                     MSG_EXPECTED_EXCEPTION,
-                                     extras=MOCK_EXTRA)
-                must_call('ha')
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        expects.expect_equal(1,
+                   2,
+                   MSG_EXPECTED_EXCEPTION,
+                   extras=MOCK_EXTRA)
+        must_call('ha')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=['test_func'])
-        must_call.assert_called_once_with('ha')
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, 'test_func')
-        self.assertEqual(actual_record.details,
-                         '1 != 2 ' + MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=['test_func'])
+    must_call.assert_called_once_with('ha')
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, 'test_func')
+    self.assertEqual(actual_record.details,
+             '1 != 2 ' + MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_expect_no_raises_default_msg(self):
-        must_call = mock.Mock()
+  def test_expect_no_raises_default_msg(self):
+    must_call = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                with expects.expect_no_raises(extras=MOCK_EXTRA):
-                    raise Exception(MSG_EXPECTED_EXCEPTION)
-                must_call('ha')
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        with expects.expect_no_raises(extras=MOCK_EXTRA):
+          raise Exception(MSG_EXPECTED_EXCEPTION)
+        must_call('ha')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=['test_func'])
-        must_call.assert_called_once_with('ha')
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, 'test_func')
-        self.assertEqual(
-            actual_record.details,
-            'Got an unexpected exception: %s' % MSG_EXPECTED_EXCEPTION)
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=['test_func'])
+    must_call.assert_called_once_with('ha')
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, 'test_func')
+    self.assertEqual(
+      actual_record.details,
+      'Got an unexpected exception: %s' % MSG_EXPECTED_EXCEPTION)
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_expect_no_raises_custom_msg(self):
-        must_call = mock.Mock()
-        msg = 'Some step unexpected failed'
+  def test_expect_no_raises_custom_msg(self):
+    must_call = mock.Mock()
+    msg = 'Some step unexpected failed'
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                with expects.expect_no_raises(message=msg, extras=MOCK_EXTRA):
-                    raise Exception(MSG_EXPECTED_EXCEPTION)
-                must_call('ha')
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        with expects.expect_no_raises(message=msg, extras=MOCK_EXTRA):
+          raise Exception(MSG_EXPECTED_EXCEPTION)
+        must_call('ha')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=['test_func'])
-        must_call.assert_called_once_with('ha')
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, 'test_func')
-        self.assertEqual(actual_record.details,
-                         '%s: %s' % (msg, MSG_EXPECTED_EXCEPTION))
-        self.assertEqual(actual_record.extras, MOCK_EXTRA)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=['test_func'])
+    must_call.assert_called_once_with('ha')
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, 'test_func')
+    self.assertEqual(actual_record.details,
+             '%s: %s' % (msg, MSG_EXPECTED_EXCEPTION))
+    self.assertEqual(actual_record.extras, MOCK_EXTRA)
 
-    def test_expect_true_and_assert_true(self):
-        """Error thrown by assert_true should be considered the termination.
-        """
-        must_call = mock.Mock()
+  def test_expect_true_and_assert_true(self):
+    """Error thrown by assert_true should be considered the termination.
+    """
+    must_call = mock.Mock()
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                expects.expect_true(False,
-                                    MSG_EXPECTED_EXCEPTION,
-                                    extras=MOCK_EXTRA)
-                must_call('ha')
-                asserts.assert_true(False, 'failed from assert_true')
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        expects.expect_true(False,
+                  MSG_EXPECTED_EXCEPTION,
+                  extras=MOCK_EXTRA)
+        must_call('ha')
+        asserts.assert_true(False, 'failed from assert_true')
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=['test_func'])
-        must_call.assert_called_once_with('ha')
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, 'test_func')
-        self.assertEqual(actual_record.details, 'failed from assert_true')
-        self.assertIsNone(actual_record.extras)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=['test_func'])
+    must_call.assert_called_once_with('ha')
+    actual_record = bt_cls.results.failed[0]
+    self.assertEqual(actual_record.test_name, 'test_func')
+    self.assertEqual(actual_record.details, 'failed from assert_true')
+    self.assertIsNone(actual_record.extras)
 
-    def test_unpack_userparams_required(self):
-        """Missing a required param should raise an error."""
-        required = ["some_param"]
-        bc = base_test.BaseTestClass(self.mock_test_cls_configs)
-        bc.unpack_userparams(required)
-        expected_value = self.mock_test_cls_configs.user_params["some_param"]
-        self.assertEqual(bc.some_param, expected_value)
+  def test_unpack_userparams_required(self):
+    """Missing a required param should raise an error."""
+    required = ["some_param"]
+    bc = base_test.BaseTestClass(self.mock_test_cls_configs)
+    bc.unpack_userparams(required)
+    expected_value = self.mock_test_cls_configs.user_params["some_param"]
+    self.assertEqual(bc.some_param, expected_value)
 
-    def test_unpack_userparams_required_missing(self):
-        """Missing a required param should raise an error."""
-        required = ["something"]
-        bc = base_test.BaseTestClass(self.mock_test_cls_configs)
-        expected_msg = ('Missing required user param "%s" in test '
-                        'configuration.') % required[0]
-        with self.assertRaisesRegex(base_test.Error, expected_msg):
-            bc.unpack_userparams(required)
+  def test_unpack_userparams_required_missing(self):
+    """Missing a required param should raise an error."""
+    required = ["something"]
+    bc = base_test.BaseTestClass(self.mock_test_cls_configs)
+    expected_msg = ('Missing required user param "%s" in test '
+            'configuration.') % required[0]
+    with self.assertRaisesRegex(base_test.Error, expected_msg):
+      bc.unpack_userparams(required)
 
-    def test_unpack_userparams_optional(self):
-        """If an optional param is specified, the value should be what's in the
-        config.
-        """
-        opt = ["some_param"]
-        bc = base_test.BaseTestClass(self.mock_test_cls_configs)
-        bc.unpack_userparams(opt_param_names=opt)
-        expected_value = self.mock_test_cls_configs.user_params["some_param"]
-        self.assertEqual(bc.some_param, expected_value)
+  def test_unpack_userparams_optional(self):
+    """If an optional param is specified, the value should be what's in the
+    config.
+    """
+    opt = ["some_param"]
+    bc = base_test.BaseTestClass(self.mock_test_cls_configs)
+    bc.unpack_userparams(opt_param_names=opt)
+    expected_value = self.mock_test_cls_configs.user_params["some_param"]
+    self.assertEqual(bc.some_param, expected_value)
 
-    def test_unpack_userparams_optional_with_default(self):
-        """If an optional param is specified with a default value, and the
-        param is not in the config, the value should be the default value.
-        """
-        bc = base_test.BaseTestClass(self.mock_test_cls_configs)
-        bc.unpack_userparams(optional_thing="whatever")
-        self.assertEqual(bc.optional_thing, "whatever")
+  def test_unpack_userparams_optional_with_default(self):
+    """If an optional param is specified with a default value, and the
+    param is not in the config, the value should be the default value.
+    """
+    bc = base_test.BaseTestClass(self.mock_test_cls_configs)
+    bc.unpack_userparams(optional_thing="whatever")
+    self.assertEqual(bc.optional_thing, "whatever")
 
-    def test_unpack_userparams_default_overwrite_by_optional_param_list(self):
-        """If an optional param is specified in kwargs, and the param is in the
-        config, the value should be the one in the config.
-        """
-        bc = base_test.BaseTestClass(self.mock_test_cls_configs)
-        bc.unpack_userparams(some_param="whatever")
-        expected_value = self.mock_test_cls_configs.user_params["some_param"]
-        self.assertEqual(bc.some_param, expected_value)
+  def test_unpack_userparams_default_overwrite_by_optional_param_list(self):
+    """If an optional param is specified in kwargs, and the param is in the
+    config, the value should be the one in the config.
+    """
+    bc = base_test.BaseTestClass(self.mock_test_cls_configs)
+    bc.unpack_userparams(some_param="whatever")
+    expected_value = self.mock_test_cls_configs.user_params["some_param"]
+    self.assertEqual(bc.some_param, expected_value)
 
-    def test_unpack_userparams_default_overwrite_by_required_param_list(self):
-        """If an optional param is specified in kwargs, the param is in the
-        required param list, and the param is not specified in the config, the
-        param's alue should be the default value and there should be no error
-        thrown.
-        """
-        bc = base_test.BaseTestClass(self.mock_test_cls_configs)
-        bc.unpack_userparams(req_param_names=['a_kwarg_param'],
-                             a_kwarg_param="whatever")
-        self.assertEqual(bc.a_kwarg_param, "whatever")
+  def test_unpack_userparams_default_overwrite_by_required_param_list(self):
+    """If an optional param is specified in kwargs, the param is in the
+    required param list, and the param is not specified in the config, the
+    param's alue should be the default value and there should be no error
+    thrown.
+    """
+    bc = base_test.BaseTestClass(self.mock_test_cls_configs)
+    bc.unpack_userparams(req_param_names=['a_kwarg_param'],
+               a_kwarg_param="whatever")
+    self.assertEqual(bc.a_kwarg_param, "whatever")
 
-    def test_unpack_userparams_optional_missing(self):
-        """Missing an optional param should not raise an error."""
-        opt = ["something"]
-        bc = base_test.BaseTestClass(self.mock_test_cls_configs)
-        bc.unpack_userparams(opt_param_names=opt)
+  def test_unpack_userparams_optional_missing(self):
+    """Missing an optional param should not raise an error."""
+    opt = ["something"]
+    bc = base_test.BaseTestClass(self.mock_test_cls_configs)
+    bc.unpack_userparams(opt_param_names=opt)
 
-    def test_unpack_userparams_basic(self):
-        """Required and optional params are unpacked properly."""
-        required = ["something"]
-        optional = ["something_else"]
-        configs = self.mock_test_cls_configs.copy()
-        configs.user_params["something"] = 42
-        configs.user_params["something_else"] = 53
-        bc = base_test.BaseTestClass(configs)
-        bc.unpack_userparams(req_param_names=required,
-                             opt_param_names=optional)
-        self.assertEqual(bc.something, 42)
-        self.assertEqual(bc.something_else, 53)
+  def test_unpack_userparams_basic(self):
+    """Required and optional params are unpacked properly."""
+    required = ["something"]
+    optional = ["something_else"]
+    configs = self.mock_test_cls_configs.copy()
+    configs.user_params["something"] = 42
+    configs.user_params["something_else"] = 53
+    bc = base_test.BaseTestClass(configs)
+    bc.unpack_userparams(req_param_names=required,
+               opt_param_names=optional)
+    self.assertEqual(bc.something, 42)
+    self.assertEqual(bc.something_else, 53)
 
-    def test_unpack_userparams_default_overwrite(self):
-        default_arg_val = "haha"
-        actual_arg_val = "wawa"
-        arg_name = "arg1"
-        configs = self.mock_test_cls_configs.copy()
-        configs.user_params[arg_name] = actual_arg_val
-        bc = base_test.BaseTestClass(configs)
-        bc.unpack_userparams(opt_param_names=[arg_name], arg1=default_arg_val)
-        self.assertEqual(bc.arg1, actual_arg_val)
+  def test_unpack_userparams_default_overwrite(self):
+    default_arg_val = "haha"
+    actual_arg_val = "wawa"
+    arg_name = "arg1"
+    configs = self.mock_test_cls_configs.copy()
+    configs.user_params[arg_name] = actual_arg_val
+    bc = base_test.BaseTestClass(configs)
+    bc.unpack_userparams(opt_param_names=[arg_name], arg1=default_arg_val)
+    self.assertEqual(bc.arg1, actual_arg_val)
 
-    def test_unpack_userparams_default_None(self):
-        bc = base_test.BaseTestClass(self.mock_test_cls_configs)
-        bc.unpack_userparams(arg1="haha")
-        self.assertEqual(bc.arg1, "haha")
+  def test_unpack_userparams_default_None(self):
+    bc = base_test.BaseTestClass(self.mock_test_cls_configs)
+    bc.unpack_userparams(arg1="haha")
+    self.assertEqual(bc.arg1, "haha")
 
-    def test_setup_generated_tests_failure(self):
-        """Test code path for setup_generated_tests failure.
+  def test_setup_generated_tests_failure(self):
+    """Test code path for setup_generated_tests failure.
 
-        When setup_generated_tests fails, pre-execution calculation is
-        incomplete and the number of tests requested is unknown. This is a
-        fatal issue that blocks any test execution in a class.
+    When setup_generated_tests fails, pre-execution calculation is
+    incomplete and the number of tests requested is unknown. This is a
+    fatal issue that blocks any test execution in a class.
 
-        A class level error record is generated.
-        Unlike `setup_class` failure, no test is considered "skipped" in this
-        case as execution stage never started.
-        """
+    A class level error record is generated.
+    Unlike `setup_class` failure, no test is considered "skipped" in this
+    case as execution stage never started.
+    """
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_generated_tests(self):
-                raise Exception(MSG_EXPECTED_EXCEPTION)
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_generated_tests(self):
+        raise Exception(MSG_EXPECTED_EXCEPTION)
 
-            def logic(self, a, b):
-                pass
+      def logic(self, a, b):
+        pass
 
-            def test_foo(self):
-                pass
+      def test_foo(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        self.assertEqual(len(bt_cls.results.requested), 0)
-        class_record = bt_cls.results.error[0]
-        self.assertEqual(class_record.test_name, 'setup_generated_tests')
-        self.assertEqual(bt_cls.results.skipped, [])
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    self.assertEqual(len(bt_cls.results.requested), 0)
+    class_record = bt_cls.results.error[0]
+    self.assertEqual(class_record.test_name, 'setup_generated_tests')
+    self.assertEqual(bt_cls.results.skipped, [])
 
-    def test_generate_tests_run(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_generated_tests(self):
-                self.generate_tests(test_logic=self.logic,
-                                    name_func=self.name_gen,
-                                    arg_sets=[(1, 2), (3, 4)])
+  def test_generate_tests_run(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_generated_tests(self):
+        self.generate_tests(test_logic=self.logic,
+                  name_func=self.name_gen,
+                  arg_sets=[(1, 2), (3, 4)])
 
-            def name_gen(self, a, b):
-                return 'test_%s_%s' % (a, b)
+      def name_gen(self, a, b):
+        return 'test_%s_%s' % (a, b)
 
-            def logic(self, a, b):
-                pass
+      def logic(self, a, b):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        self.assertEqual(len(bt_cls.results.requested), 2)
-        self.assertEqual(len(bt_cls.results.passed), 2)
-        self.assertIsNone(bt_cls.results.passed[0].uid)
-        self.assertIsNone(bt_cls.results.passed[1].uid)
-        self.assertEqual(bt_cls.results.passed[0].test_name, 'test_1_2')
-        self.assertEqual(bt_cls.results.passed[1].test_name, 'test_3_4')
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    self.assertEqual(len(bt_cls.results.requested), 2)
+    self.assertEqual(len(bt_cls.results.passed), 2)
+    self.assertIsNone(bt_cls.results.passed[0].uid)
+    self.assertIsNone(bt_cls.results.passed[1].uid)
+    self.assertEqual(bt_cls.results.passed[0].test_name, 'test_1_2')
+    self.assertEqual(bt_cls.results.passed[1].test_name, 'test_3_4')
 
-    def test_generate_tests_with_uid(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_generated_tests(self):
-                self.generate_tests(test_logic=self.logic,
-                                    name_func=self.name_gen,
-                                    uid_func=self.uid_logic,
-                                    arg_sets=[(1, 2), (3, 4)])
+  def test_generate_tests_with_uid(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_generated_tests(self):
+        self.generate_tests(test_logic=self.logic,
+                  name_func=self.name_gen,
+                  uid_func=self.uid_logic,
+                  arg_sets=[(1, 2), (3, 4)])
 
-            def name_gen(self, a, b):
-                return 'test_%s_%s' % (a, b)
+      def name_gen(self, a, b):
+        return 'test_%s_%s' % (a, b)
 
-            def uid_logic(self, a, b):
-                return 'uid-%s-%s' % (a, b)
+      def uid_logic(self, a, b):
+        return 'uid-%s-%s' % (a, b)
 
-            def logic(self, a, b):
-                pass
+      def logic(self, a, b):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        self.assertEqual(bt_cls.results.passed[0].uid, 'uid-1-2')
-        self.assertEqual(bt_cls.results.passed[1].uid, 'uid-3-4')
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    self.assertEqual(bt_cls.results.passed[0].uid, 'uid-1-2')
+    self.assertEqual(bt_cls.results.passed[1].uid, 'uid-3-4')
 
-    def test_generate_tests_with_none_uid(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_generated_tests(self):
-                self.generate_tests(test_logic=self.logic,
-                                    name_func=self.name_gen,
-                                    uid_func=self.uid_logic,
-                                    arg_sets=[(1, 2), (3, 4)])
+  def test_generate_tests_with_none_uid(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_generated_tests(self):
+        self.generate_tests(test_logic=self.logic,
+                  name_func=self.name_gen,
+                  uid_func=self.uid_logic,
+                  arg_sets=[(1, 2), (3, 4)])
 
-            def name_gen(self, a, b):
-                return 'test_%s_%s' % (a, b)
+      def name_gen(self, a, b):
+        return 'test_%s_%s' % (a, b)
 
-            def uid_logic(self, a, b):
-                if a == 1:
-                    return None
-                return 'uid-3-4'
+      def uid_logic(self, a, b):
+        if a == 1:
+          return None
+        return 'uid-3-4'
 
-            def logic(self, a, b):
-                pass
+      def logic(self, a, b):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        self.assertIsNone(bt_cls.results.passed[0].uid)
-        self.assertEqual(bt_cls.results.passed[1].uid, 'uid-3-4')
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    self.assertIsNone(bt_cls.results.passed[0].uid)
+    self.assertEqual(bt_cls.results.passed[1].uid, 'uid-3-4')
 
-    def test_generate_tests_selected_run(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_generated_tests(self):
-                self.generate_tests(test_logic=self.logic,
-                                    name_func=self.name_gen,
-                                    arg_sets=[(1, 2), (3, 4)])
+  def test_generate_tests_selected_run(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_generated_tests(self):
+        self.generate_tests(test_logic=self.logic,
+                  name_func=self.name_gen,
+                  arg_sets=[(1, 2), (3, 4)])
 
-            def name_gen(self, a, b):
-                return 'test_%s_%s' % (a, b)
+      def name_gen(self, a, b):
+        return 'test_%s_%s' % (a, b)
 
-            def logic(self, a, b):
-                pass
+      def logic(self, a, b):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=['test_3_4'])
-        self.assertEqual(len(bt_cls.results.requested), 1)
-        self.assertEqual(len(bt_cls.results.passed), 1)
-        self.assertEqual(bt_cls.results.passed[0].test_name, 'test_3_4')
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=['test_3_4'])
+    self.assertEqual(len(bt_cls.results.requested), 1)
+    self.assertEqual(len(bt_cls.results.passed), 1)
+    self.assertEqual(bt_cls.results.passed[0].test_name, 'test_3_4')
 
-    def test_generate_tests_call_outside_of_setup_generated_tests(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_ha(self):
-                self.generate_tests(test_logic=self.logic,
-                                    name_func=self.name_gen,
-                                    arg_sets=[(1, 2), (3, 4)])
+  def test_generate_tests_call_outside_of_setup_generated_tests(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_ha(self):
+        self.generate_tests(test_logic=self.logic,
+                  name_func=self.name_gen,
+                  arg_sets=[(1, 2), (3, 4)])
 
-            def name_gen(self, a, b):
-                return 'test_%s_%s' % (a, b)
+      def name_gen(self, a, b):
+        return 'test_%s_%s' % (a, b)
 
-            def logic(self, a, b):
-                pass
+      def logic(self, a, b):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        utils.validate_test_result(bt_cls.results)
-        self.assertEqual(actual_record.test_name, "test_ha")
-        self.assertEqual(
-            actual_record.details,
-            '"generate_tests" cannot be called outside of setup_generated_tests'
-        )
-        expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
-                            "Requested 1, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    utils.validate_test_result(bt_cls.results)
+    self.assertEqual(actual_record.test_name, "test_ha")
+    self.assertEqual(
+      actual_record.details,
+      '"generate_tests" cannot be called outside of setup_generated_tests'
+    )
+    expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
+              "Requested 1, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_generate_tests_dup_test_name(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def setup_generated_tests(self):
-                self.generate_tests(test_logic=self.logic,
-                                    name_func=self.name_gen,
-                                    arg_sets=[(1, 2), (3, 4)])
+  def test_generate_tests_dup_test_name(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def setup_generated_tests(self):
+        self.generate_tests(test_logic=self.logic,
+                  name_func=self.name_gen,
+                  arg_sets=[(1, 2), (3, 4)])
 
-            def name_gen(self, a, b):
-                return 'ha'
+      def name_gen(self, a, b):
+        return 'ha'
 
-            def logic(self, a, b):
-                pass
+      def logic(self, a, b):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.error[0]
-        self.assertEqual(actual_record.test_name, "setup_generated_tests")
-        self.assertEqual(
-            actual_record.details,
-            'During test generation of "logic": Test name "ha" already exists'
-            ', cannot be duplicated!')
-        expected_summary = ("Error 1, Executed 0, Failed 0, Passed 0, "
-                            "Requested 0, Skipped 0")
-        self.assertEqual(bt_cls.results.summary_str(), expected_summary)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.error[0]
+    self.assertEqual(actual_record.test_name, "setup_generated_tests")
+    self.assertEqual(
+      actual_record.details,
+      'During test generation of "logic": Test name "ha" already exists'
+      ', cannot be duplicated!')
+    expected_summary = ("Error 1, Executed 0, Failed 0, Passed 0, "
+              "Requested 0, Skipped 0")
+    self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
-    def test_write_user_data(self):
-        content = {'a': 1}
+  def test_write_user_data(self):
+    content = {'a': 1}
 
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_something(self):
-                self.record_data(content)
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_something(self):
+        self.record_data(content)
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run(test_names=["test_something"])
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.test_name, "test_something")
-        hit = False
-        with io.open(self.summary_file, 'r', encoding='utf-8') as f:
-            for c in yaml.safe_load_all(f):
-                if c['Type'] != records.TestSummaryEntryType.USER_DATA.value:
-                    continue
-                hit = True
-                self.assertEqual(c['a'], content['a'])
-                self.assertIsNotNone(c['timestamp'])
-        self.assertTrue(hit)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run(test_names=["test_something"])
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.test_name, "test_something")
+    hit = False
+    with io.open(self.summary_file, 'r', encoding='utf-8') as f:
+      for c in yaml.safe_load_all(f):
+        if c['Type'] != records.TestSummaryEntryType.USER_DATA.value:
+          continue
+        hit = True
+        self.assertEqual(c['a'], content['a'])
+        self.assertIsNotNone(c['timestamp'])
+    self.assertTrue(hit)
 
-    def test_record_controller_info(self):
-        """Verifies that controller info is correctly recorded.
+  def test_record_controller_info(self):
+    """Verifies that controller info is correctly recorded.
 
-        1. Info added in test is recorded.
-        2. Info of multiple controller types are recorded.
-        """
-        mock_test_config = self.mock_test_cls_configs.copy()
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        mock_ctrlr_2_config_name = mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        my_config = [{'serial': 'xxxx', 'magic': 'Magic'}]
-        mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
-        mock_test_config.controller_configs[
-            mock_ctrlr_2_config_name] = copy.copy(my_config)
+    1. Info added in test is recorded.
+    2. Info of multiple controller types are recorded.
+    """
+    mock_test_config = self.mock_test_cls_configs.copy()
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    mock_ctrlr_2_config_name = mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    my_config = [{'serial': 'xxxx', 'magic': 'Magic'}]
+    mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
+    mock_test_config.controller_configs[
+      mock_ctrlr_2_config_name] = copy.copy(my_config)
 
-        class ControllerInfoTest(base_test.BaseTestClass):
-            """Registers two different controller types and modifies controller
-            info at runtime.
-            """
+    class ControllerInfoTest(base_test.BaseTestClass):
+      """Registers two different controller types and modifies controller
+      info at runtime.
+      """
 
-            def setup_class(self):
-                self.register_controller(mock_controller)
-                second_controller = self.register_controller(
-                    mock_second_controller)[0]
-                # This should appear in recorded controller info.
-                second_controller.set_magic('haha')
+      def setup_class(self):
+        self.register_controller(mock_controller)
+        second_controller = self.register_controller(
+          mock_second_controller)[0]
+        # This should appear in recorded controller info.
+        second_controller.set_magic('haha')
 
-            def test_func(self):
-                pass
+      def test_func(self):
+        pass
 
-        bt_cls = ControllerInfoTest(mock_test_config)
-        bt_cls.run()
-        info1 = bt_cls.results.controller_info[0]
-        info2 = bt_cls.results.controller_info[1]
-        self.assertNotEqual(info1, info2)
-        self.assertEqual(info1.test_class, 'ControllerInfoTest')
-        self.assertEqual(info1.controller_name, 'MagicDevice')
-        self.assertEqual(info1.controller_info, [{
-            'MyMagic': {
-                'magic': 'Magic'
-            }
-        }])
-        self.assertEqual(info2.test_class, 'ControllerInfoTest')
-        self.assertEqual(info2.controller_name, 'AnotherMagicDevice')
-        self.assertEqual(info2.controller_info, [{
-            'MyOtherMagic': {
-                'magic': 'Magic',
-                'extra_magic': 'haha'
-            }
-        }])
+    bt_cls = ControllerInfoTest(mock_test_config)
+    bt_cls.run()
+    info1 = bt_cls.results.controller_info[0]
+    info2 = bt_cls.results.controller_info[1]
+    self.assertNotEqual(info1, info2)
+    self.assertEqual(info1.test_class, 'ControllerInfoTest')
+    self.assertEqual(info1.controller_name, 'MagicDevice')
+    self.assertEqual(info1.controller_info, [{
+      'MyMagic': {
+        'magic': 'Magic'
+      }
+    }])
+    self.assertEqual(info2.test_class, 'ControllerInfoTest')
+    self.assertEqual(info2.controller_name, 'AnotherMagicDevice')
+    self.assertEqual(info2.controller_info, [{
+      'MyOtherMagic': {
+        'magic': 'Magic',
+        'extra_magic': 'haha'
+      }
+    }])
 
-    def test_record_controller_info_fail(self):
-        mock_test_config = self.mock_test_cls_configs.copy()
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        mock_ctrlr_2_config_name = mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        my_config = [{'serial': 'xxxx', 'magic': 'Magic'}]
-        mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
-        mock_test_config.controller_configs[
-            mock_ctrlr_2_config_name] = copy.copy(my_config)
+  def test_record_controller_info_fail(self):
+    mock_test_config = self.mock_test_cls_configs.copy()
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    mock_ctrlr_2_config_name = mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    my_config = [{'serial': 'xxxx', 'magic': 'Magic'}]
+    mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
+    mock_test_config.controller_configs[
+      mock_ctrlr_2_config_name] = copy.copy(my_config)
 
-        class ControllerInfoTest(base_test.BaseTestClass):
-            """Registers two different controller types and modifies controller
-            info at runtime.
-            """
+    class ControllerInfoTest(base_test.BaseTestClass):
+      """Registers two different controller types and modifies controller
+      info at runtime.
+      """
 
-            def setup_class(self):
-                device = self.register_controller(mock_controller)[0]
-                device.who_am_i = mock.MagicMock()
-                device.who_am_i.side_effect = Exception('Some failure')
-                second_controller = self.register_controller(
-                    mock_second_controller)[0]
-                # This should appear in recorded controller info.
-                second_controller.set_magic('haha')
+      def setup_class(self):
+        device = self.register_controller(mock_controller)[0]
+        device.who_am_i = mock.MagicMock()
+        device.who_am_i.side_effect = Exception('Some failure')
+        second_controller = self.register_controller(
+          mock_second_controller)[0]
+        # This should appear in recorded controller info.
+        second_controller.set_magic('haha')
 
-            def test_func(self):
-                pass
+      def test_func(self):
+        pass
 
-        bt_cls = ControllerInfoTest(mock_test_config)
-        bt_cls.run()
-        info = bt_cls.results.controller_info[0]
-        self.assertEqual(len(bt_cls.results.controller_info), 1)
-        self.assertEqual(info.test_class, 'ControllerInfoTest')
-        self.assertEqual(info.controller_name, 'AnotherMagicDevice')
-        self.assertEqual(info.controller_info, [{
-            'MyOtherMagic': {
-                'magic': 'Magic',
-                'extra_magic': 'haha'
-            }
-        }])
-        record = bt_cls.results.error[0]
-        print(record.to_dict())
-        self.assertEqual(record.test_name, 'clean_up')
-        self.assertIsNotNone(record.begin_time)
-        self.assertIsNotNone(record.end_time)
-        expected_msg = ('Failed to collect controller info from '
-                        'mock_controller: Some failure')
-        self.assertEqual(record.details, expected_msg)
+    bt_cls = ControllerInfoTest(mock_test_config)
+    bt_cls.run()
+    info = bt_cls.results.controller_info[0]
+    self.assertEqual(len(bt_cls.results.controller_info), 1)
+    self.assertEqual(info.test_class, 'ControllerInfoTest')
+    self.assertEqual(info.controller_name, 'AnotherMagicDevice')
+    self.assertEqual(info.controller_info, [{
+      'MyOtherMagic': {
+        'magic': 'Magic',
+        'extra_magic': 'haha'
+      }
+    }])
+    record = bt_cls.results.error[0]
+    print(record.to_dict())
+    self.assertEqual(record.test_name, 'clean_up')
+    self.assertIsNotNone(record.begin_time)
+    self.assertIsNotNone(record.end_time)
+    expected_msg = ('Failed to collect controller info from '
+            'mock_controller: Some failure')
+    self.assertEqual(record.details, expected_msg)
 
-    def test_uid(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            @records.uid('some-uid')
-            def test_func(self):
-                pass
+  def test_uid(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      @records.uid('some-uid')
+      def test_func(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.passed[0]
-        self.assertEqual(actual_record.uid, 'some-uid')
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.passed[0]
+    self.assertEqual(actual_record.uid, 'some-uid')
 
-    def test_uid_not_specified(self):
-        class MockBaseTest(base_test.BaseTestClass):
-            def test_func(self):
-                pass
+  def test_uid_not_specified(self):
+    class MockBaseTest(base_test.BaseTestClass):
+      def test_func(self):
+        pass
 
-        bt_cls = MockBaseTest(self.mock_test_cls_configs)
-        bt_cls.run()
-        actual_record = bt_cls.results.passed[0]
-        self.assertIsNone(actual_record.uid)
+    bt_cls = MockBaseTest(self.mock_test_cls_configs)
+    bt_cls.run()
+    actual_record = bt_cls.results.passed[0]
+    self.assertIsNone(actual_record.uid)
 
-    def test_uid_is_none(self):
-        with self.assertRaisesRegex(ValueError, 'UID cannot be None.'):
+  def test_uid_is_none(self):
+    with self.assertRaisesRegex(ValueError, 'UID cannot be None.'):
 
-            class MockBaseTest(base_test.BaseTestClass):
-                @records.uid(None)
-                def not_a_test(self):
-                    pass
+      class MockBaseTest(base_test.BaseTestClass):
+        @records.uid(None)
+        def not_a_test(self):
+          pass
 
-    def test_log_stage_always_logs_end_statement(self):
-        instance = base_test.BaseTestClass(self.mock_test_cls_configs)
-        instance.current_test_info = mock.Mock()
-        instance.current_test_info.name = 'TestClass'
+  def test_log_stage_always_logs_end_statement(self):
+    instance = base_test.BaseTestClass(self.mock_test_cls_configs)
+    instance.current_test_info = mock.Mock()
+    instance.current_test_info.name = 'TestClass'
 
-        class RecoverableError(Exception):
-            pass
+    class RecoverableError(Exception):
+      pass
 
-        with mock.patch('mobly.base_test.logging') as logging_patch:
-            try:
-                with instance._log_test_stage('stage'):
-                    raise RecoverableError('Force stage to fail.')
-            except RecoverableError:
-                pass
+    with mock.patch('mobly.base_test.logging') as logging_patch:
+      try:
+        with instance._log_test_stage('stage'):
+          raise RecoverableError('Force stage to fail.')
+      except RecoverableError:
+        pass
 
-        logging_patch.debug.assert_called_with('[TestClass]#stage <<< END <<<')
+    logging_patch.debug.assert_called_with('[TestClass]#stage <<< END <<<')
 
 
 if __name__ == "__main__":
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/config_parser_test.py b/tests/mobly/config_parser_test.py
index 59cd1d2..2fc8b7d 100644
--- a/tests/mobly/config_parser_test.py
+++ b/tests/mobly/config_parser_test.py
@@ -22,59 +22,59 @@
 
 
 class OutputTest(unittest.TestCase):
-    """This test class has unit tests for the implementation of Mobly's output
-    files.
-    """
+  """This test class has unit tests for the implementation of Mobly's output
+  files.
+  """
 
-    def setUp(self):
-        self.tmp_dir = tempfile.mkdtemp()
+  def setUp(self):
+    self.tmp_dir = tempfile.mkdtemp()
 
-    def tearDown(self):
-        shutil.rmtree(self.tmp_dir)
+  def tearDown(self):
+    shutil.rmtree(self.tmp_dir)
 
-    def test__load_config_file(self):
-        tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
-        with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
-            f.write(u'TestBeds:\n')
-            f.write(u'  # A test bed where adb will find Android devices.\n')
-            f.write(u'  - Name: SampleTestBed\n')
-            f.write(u'    Controllers:\n')
-            f.write(u'        AndroidDevice: \'*\'\n')
+  def test__load_config_file(self):
+    tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
+    with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
+      f.write(u'TestBeds:\n')
+      f.write(u'  # A test bed where adb will find Android devices.\n')
+      f.write(u'  - Name: SampleTestBed\n')
+      f.write(u'    Controllers:\n')
+      f.write(u'        AndroidDevice: \'*\'\n')
 
-        config = config_parser._load_config_file(tmp_file_path)
-        self.assertEqual(config['TestBeds'][0]['Name'], u'SampleTestBed')
+    config = config_parser._load_config_file(tmp_file_path)
+    self.assertEqual(config['TestBeds'][0]['Name'], u'SampleTestBed')
 
-    def test__load_config_file_with_unicode(self):
-        tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
-        with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
-            f.write(u'TestBeds:\n')
-            f.write(u'  # A test bed where adb will find Android devices.\n')
-            f.write(u'  - Name: \u901a\n')
-            f.write(u'    Controllers:\n')
-            f.write(u'        AndroidDevice: \'*\'\n')
+  def test__load_config_file_with_unicode(self):
+    tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
+    with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
+      f.write(u'TestBeds:\n')
+      f.write(u'  # A test bed where adb will find Android devices.\n')
+      f.write(u'  - Name: \u901a\n')
+      f.write(u'    Controllers:\n')
+      f.write(u'        AndroidDevice: \'*\'\n')
 
-        config = config_parser._load_config_file(tmp_file_path)
-        self.assertEqual(config['TestBeds'][0]['Name'], u'\u901a')
+    config = config_parser._load_config_file(tmp_file_path)
+    self.assertEqual(config['TestBeds'][0]['Name'], u'\u901a')
 
-    def test_run_config_type(self):
-        config = config_parser.TestRunConfig()
-        self.assertNotIn('summary_writer', str(config))
-        self.assertNotIn('register_controller', str(config))
+  def test_run_config_type(self):
+    config = config_parser.TestRunConfig()
+    self.assertNotIn('summary_writer', str(config))
+    self.assertNotIn('register_controller', str(config))
 
-    def test_run_config_controller_configs_is_already_initialized(self):
-        config = config_parser.TestRunConfig()
-        expected_value = 'SOME_VALUE'
-        self.assertEqual(
-            config.controller_configs.get('NON_EXISTENT_KEY', expected_value),
-            expected_value)
+  def test_run_config_controller_configs_is_already_initialized(self):
+    config = config_parser.TestRunConfig()
+    expected_value = 'SOME_VALUE'
+    self.assertEqual(
+      config.controller_configs.get('NON_EXISTENT_KEY', expected_value),
+      expected_value)
 
-    def test_run_config_user_params_is_already_initialized(self):
-        config = config_parser.TestRunConfig()
-        expected_value = 'SOME_VALUE'
-        self.assertEqual(
-            config.user_params.get('NON_EXISTENT_KEY', expected_value),
-            expected_value)
+  def test_run_config_user_params_is_already_initialized(self):
+    config = config_parser.TestRunConfig()
+    expected_value = 'SOME_VALUE'
+    self.assertEqual(
+      config.user_params.get('NON_EXISTENT_KEY', expected_value),
+      expected_value)
 
 
 if __name__ == '__main__':
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/controller_manager_test.py b/tests/mobly/controller_manager_test.py
index 6bfb6b7..130a464 100755
--- a/tests/mobly/controller_manager_test.py
+++ b/tests/mobly/controller_manager_test.py
@@ -23,216 +23,216 @@
 
 
 class ControllerManagerTest(unittest.TestCase):
-    """Unit tests for Mobly's ControllerManager."""
+  """Unit tests for Mobly's ControllerManager."""
 
-    def test_verify_controller_module(self):
+  def test_verify_controller_module(self):
+    controller_manager.verify_controller_module(mock_controller)
+
+  def test_verify_controller_module_null_attr(self):
+    try:
+      tmp = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+      mock_controller.MOBLY_CONTROLLER_CONFIG_NAME = None
+      msg = 'Controller interface .* in .* cannot be null.'
+      with self.assertRaisesRegex(signals.ControllerError, msg):
         controller_manager.verify_controller_module(mock_controller)
+    finally:
+      mock_controller.MOBLY_CONTROLLER_CONFIG_NAME = tmp
 
-    def test_verify_controller_module_null_attr(self):
-        try:
-            tmp = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-            mock_controller.MOBLY_CONTROLLER_CONFIG_NAME = None
-            msg = 'Controller interface .* in .* cannot be null.'
-            with self.assertRaisesRegex(signals.ControllerError, msg):
-                controller_manager.verify_controller_module(mock_controller)
-        finally:
-            mock_controller.MOBLY_CONTROLLER_CONFIG_NAME = tmp
+  def test_verify_controller_module_missing_attr(self):
+    try:
+      tmp = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+      delattr(mock_controller, 'MOBLY_CONTROLLER_CONFIG_NAME')
+      msg = 'Module .* missing required controller module attribute'
+      with self.assertRaisesRegex(signals.ControllerError, msg):
+        controller_manager.verify_controller_module(mock_controller)
+    finally:
+      setattr(mock_controller, 'MOBLY_CONTROLLER_CONFIG_NAME', tmp)
 
-    def test_verify_controller_module_missing_attr(self):
-        try:
-            tmp = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-            delattr(mock_controller, 'MOBLY_CONTROLLER_CONFIG_NAME')
-            msg = 'Module .* missing required controller module attribute'
-            with self.assertRaisesRegex(signals.ControllerError, msg):
-                controller_manager.verify_controller_module(mock_controller)
-        finally:
-            setattr(mock_controller, 'MOBLY_CONTROLLER_CONFIG_NAME', tmp)
+  def test_register_controller_no_config(self):
+    c_manager = controller_manager.ControllerManager('SomeClass', {})
+    with self.assertRaisesRegex(signals.ControllerError,
+                  'No corresponding config found for'):
+      c_manager.register_controller(mock_controller)
 
-    def test_register_controller_no_config(self):
-        c_manager = controller_manager.ControllerManager('SomeClass', {})
-        with self.assertRaisesRegex(signals.ControllerError,
-                                    'No corresponding config found for'):
-            c_manager.register_controller(mock_controller)
+  def test_register_controller_no_config_for_not_required(self):
+    c_manager = controller_manager.ControllerManager('SomeClass', {})
+    self.assertIsNone(
+      c_manager.register_controller(mock_controller, required=False))
 
-    def test_register_controller_no_config_for_not_required(self):
-        c_manager = controller_manager.ControllerManager('SomeClass', {})
-        self.assertIsNone(
-            c_manager.register_controller(mock_controller, required=False))
+  def test_register_controller_dup_register(self):
+    """Verifies correctness of registration, internal tally of controllers
+    objects, and the right error happen when a controller module is
+    registered twice.
+    """
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    c_manager.register_controller(mock_controller)
+    registered_name = 'mock_controller'
+    self.assertTrue(registered_name in c_manager._controller_objects)
+    mock_ctrlrs = c_manager._controller_objects[registered_name]
+    self.assertEqual(mock_ctrlrs[0].magic, 'magic1')
+    self.assertEqual(mock_ctrlrs[1].magic, 'magic2')
+    self.assertTrue(c_manager._controller_modules[registered_name])
+    expected_msg = 'Controller module .* has already been registered.'
+    with self.assertRaisesRegex(signals.ControllerError, expected_msg):
+      c_manager.register_controller(mock_controller)
 
-    def test_register_controller_dup_register(self):
-        """Verifies correctness of registration, internal tally of controllers
-        objects, and the right error happen when a controller module is
-        registered twice.
-        """
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        c_manager.register_controller(mock_controller)
-        registered_name = 'mock_controller'
-        self.assertTrue(registered_name in c_manager._controller_objects)
-        mock_ctrlrs = c_manager._controller_objects[registered_name]
-        self.assertEqual(mock_ctrlrs[0].magic, 'magic1')
-        self.assertEqual(mock_ctrlrs[1].magic, 'magic2')
-        self.assertTrue(c_manager._controller_modules[registered_name])
-        expected_msg = 'Controller module .* has already been registered.'
-        with self.assertRaisesRegex(signals.ControllerError, expected_msg):
-            c_manager.register_controller(mock_controller)
+  def test_register_controller_return_value(self):
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    magic_devices = c_manager.register_controller(mock_controller)
+    self.assertEqual(magic_devices[0].magic, 'magic1')
+    self.assertEqual(magic_devices[1].magic, 'magic2')
 
-    def test_register_controller_return_value(self):
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        magic_devices = c_manager.register_controller(mock_controller)
-        self.assertEqual(magic_devices[0].magic, 'magic1')
-        self.assertEqual(magic_devices[1].magic, 'magic2')
+  def test_register_controller_change_return_value(self):
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    magic_devices = c_manager.register_controller(mock_controller)
+    magic1 = magic_devices.pop(0)
+    self.assertIs(magic1,
+            c_manager._controller_objects['mock_controller'][0])
+    self.assertEqual(
+      len(c_manager._controller_objects['mock_controller']), 2)
 
-    def test_register_controller_change_return_value(self):
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        magic_devices = c_manager.register_controller(mock_controller)
-        magic1 = magic_devices.pop(0)
-        self.assertIs(magic1,
-                      c_manager._controller_objects['mock_controller'][0])
-        self.assertEqual(
-            len(c_manager._controller_objects['mock_controller']), 2)
+  def test_register_controller_less_than_min_number(self):
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    expected_msg = 'Expected to get at least 3 controller objects, got 2.'
+    with self.assertRaisesRegex(signals.ControllerError, expected_msg):
+      c_manager.register_controller(mock_controller, min_number=3)
 
-    def test_register_controller_less_than_min_number(self):
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        expected_msg = 'Expected to get at least 3 controller objects, got 2.'
-        with self.assertRaisesRegex(signals.ControllerError, expected_msg):
-            c_manager.register_controller(mock_controller, min_number=3)
+  @mock.patch('yaml.dump', side_effect=TypeError('ha'))
+  def test_get_controller_info_record_not_serializable(self, _):
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    c_manager.register_controller(mock_controller)
+    record = c_manager.get_controller_info_records()[0]
+    actual_controller_info = record.controller_info
+    self.assertEqual(actual_controller_info,
+             "[{'MyMagic': 'magic1'}, {'MyMagic': 'magic2'}]")
 
-    @mock.patch('yaml.dump', side_effect=TypeError('ha'))
-    def test_get_controller_info_record_not_serializable(self, _):
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        c_manager.register_controller(mock_controller)
-        record = c_manager.get_controller_info_records()[0]
-        actual_controller_info = record.controller_info
-        self.assertEqual(actual_controller_info,
-                         "[{'MyMagic': 'magic1'}, {'MyMagic': 'magic2'}]")
+  def test_controller_record_exists_without_get_info(self):
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    get_info = getattr(mock_controller, 'get_info')
+    delattr(mock_controller, 'get_info')
+    try:
+      c_manager.register_controller(mock_controller)
+      record = c_manager.get_controller_info_records()[0]
+      self.assertIsNone(record.controller_info)
+      self.assertEqual(record.test_class, 'SomeClass')
+      self.assertEqual(record.controller_name, 'MagicDevice')
+    finally:
+      setattr(mock_controller, 'get_info', get_info)
 
-    def test_controller_record_exists_without_get_info(self):
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        get_info = getattr(mock_controller, 'get_info')
-        delattr(mock_controller, 'get_info')
-        try:
-            c_manager.register_controller(mock_controller)
-            record = c_manager.get_controller_info_records()[0]
-            self.assertIsNone(record.controller_info)
-            self.assertEqual(record.test_class, 'SomeClass')
-            self.assertEqual(record.controller_name, 'MagicDevice')
-        finally:
-            setattr(mock_controller, 'get_info', get_info)
+  @mock.patch('tests.lib.mock_controller.get_info')
+  def test_get_controller_info_records_empty(self, mock_get_info_func):
+    mock_get_info_func.return_value = None
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    c_manager.register_controller(mock_controller)
+    record = c_manager.get_controller_info_records()[0]
+    self.assertIsNone(record.controller_info)
+    self.assertEqual(record.test_class, 'SomeClass')
+    self.assertEqual(record.controller_name, 'MagicDevice')
 
-    @mock.patch('tests.lib.mock_controller.get_info')
-    def test_get_controller_info_records_empty(self, mock_get_info_func):
-        mock_get_info_func.return_value = None
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        c_manager.register_controller(mock_controller)
-        record = c_manager.get_controller_info_records()[0]
-        self.assertIsNone(record.controller_info)
-        self.assertEqual(record.test_class, 'SomeClass')
-        self.assertEqual(record.controller_name, 'MagicDevice')
+  @mock.patch('mobly.expects._ExpectErrorRecorder.add_error')
+  @mock.patch('tests.lib.mock_controller.get_info')
+  def test_get_controller_info_records_error(self, mock_get_info_func,
+                         mock_add_error):
+    mock_get_info_func.side_effect = Exception('Record info failed.')
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    c_manager.register_controller(mock_controller)
+    self.assertFalse(c_manager.get_controller_info_records())
+    mock_add_error.assert_called_once()
+    error_record = mock_add_error.call_args[0][0]
+    self.assertIn('Record info failed.', error_record.stacktrace)
 
-    @mock.patch('mobly.expects._ExpectErrorRecorder.add_error')
-    @mock.patch('tests.lib.mock_controller.get_info')
-    def test_get_controller_info_records_error(self, mock_get_info_func,
-                                               mock_add_error):
-        mock_get_info_func.side_effect = Exception('Record info failed.')
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        c_manager.register_controller(mock_controller)
-        self.assertFalse(c_manager.get_controller_info_records())
-        mock_add_error.assert_called_once()
-        error_record = mock_add_error.call_args[0][0]
-        self.assertIn('Record info failed.', error_record.stacktrace)
+  def test_get_controller_info_records(self):
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    c_manager.register_controller(mock_controller)
+    record = c_manager.get_controller_info_records()[0]
+    record_dict = record.to_dict()
+    record_dict.pop('Timestamp')
+    self.assertEqual(
+      record_dict, {
+        'Controller Info': [{
+          'MyMagic': 'magic1'
+        }, {
+          'MyMagic': 'magic2'
+        }],
+        'Controller Name': 'MagicDevice',
+        'Test Class': 'SomeClass'
+      })
 
-    def test_get_controller_info_records(self):
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        c_manager.register_controller(mock_controller)
-        record = c_manager.get_controller_info_records()[0]
-        record_dict = record.to_dict()
-        record_dict.pop('Timestamp')
-        self.assertEqual(
-            record_dict, {
-                'Controller Info': [{
-                    'MyMagic': 'magic1'
-                }, {
-                    'MyMagic': 'magic2'
-                }],
-                'Controller Name': 'MagicDevice',
-                'Test Class': 'SomeClass'
-            })
+  def test_get_controller_info_without_registration(self):
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    self.assertFalse(c_manager.get_controller_info_records())
 
-    def test_get_controller_info_without_registration(self):
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        self.assertFalse(c_manager.get_controller_info_records())
+  @mock.patch('tests.lib.mock_controller.destroy')
+  def test_unregister_controller(self, mock_destroy_func):
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    objects = c_manager.register_controller(mock_controller)
+    c_manager.unregister_controllers()
+    mock_destroy_func.assert_called_once_with(objects)
+    self.assertFalse(c_manager._controller_objects)
+    self.assertFalse(c_manager._controller_modules)
 
-    @mock.patch('tests.lib.mock_controller.destroy')
-    def test_unregister_controller(self, mock_destroy_func):
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        objects = c_manager.register_controller(mock_controller)
-        c_manager.unregister_controllers()
-        mock_destroy_func.assert_called_once_with(objects)
-        self.assertFalse(c_manager._controller_objects)
-        self.assertFalse(c_manager._controller_modules)
+  @mock.patch('mobly.expects._ExpectErrorRecorder.add_error')
+  @mock.patch('tests.lib.mock_controller.destroy')
+  def test_unregister_controller_error(self, mock_destroy_func,
+                     mock_add_error):
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    c_manager.register_controller(mock_controller)
+    mock_destroy_func.side_effect = Exception('Failed in destroy.')
+    c_manager.unregister_controllers()
+    mock_add_error.assert_called_once()
+    error_record = mock_add_error.call_args[0][0]
+    self.assertIn('Failed in destroy.', error_record.stacktrace)
+    self.assertFalse(c_manager._controller_objects)
+    self.assertFalse(c_manager._controller_modules)
 
-    @mock.patch('mobly.expects._ExpectErrorRecorder.add_error')
-    @mock.patch('tests.lib.mock_controller.destroy')
-    def test_unregister_controller_error(self, mock_destroy_func,
-                                         mock_add_error):
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        c_manager.register_controller(mock_controller)
-        mock_destroy_func.side_effect = Exception('Failed in destroy.')
-        c_manager.unregister_controllers()
-        mock_add_error.assert_called_once()
-        error_record = mock_add_error.call_args[0][0]
-        self.assertIn('Failed in destroy.', error_record.stacktrace)
-        self.assertFalse(c_manager._controller_objects)
-        self.assertFalse(c_manager._controller_modules)
-
-    @mock.patch('tests.lib.mock_controller.destroy')
-    def test_unregister_controller_without_registration(
-            self, mock_destroy_func):
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
-        c_manager = controller_manager.ControllerManager(
-            'SomeClass', controller_configs)
-        c_manager.unregister_controllers()
-        mock_destroy_func.assert_not_called()
-        self.assertFalse(c_manager._controller_objects)
-        self.assertFalse(c_manager._controller_modules)
+  @mock.patch('tests.lib.mock_controller.destroy')
+  def test_unregister_controller_without_registration(
+      self, mock_destroy_func):
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
+    c_manager = controller_manager.ControllerManager(
+      'SomeClass', controller_configs)
+    c_manager.unregister_controllers()
+    mock_destroy_func.assert_not_called()
+    self.assertFalse(c_manager._controller_objects)
+    self.assertFalse(c_manager._controller_modules)
 
 
 if __name__ == "__main__":
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/controllers/android_device_test.py b/tests/mobly/controllers/android_device_test.py
index 435f3f1..579b50f 100755
--- a/tests/mobly/controllers/android_device_test.py
+++ b/tests/mobly/controllers/android_device_test.py
@@ -42,1274 +42,1274 @@
 
 
 class AndroidDeviceTest(unittest.TestCase):
-    """This test class has unit tests for the implementation of everything
-    under mobly.controllers.android_device.
+  """This test class has unit tests for the implementation of everything
+  under mobly.controllers.android_device.
+  """
+
+  def setUp(self):
+    # Set log_path to logging since mobly logger setup is not called.
+    if not hasattr(logging, 'log_path'):
+      setattr(logging, 'log_path', '/tmp/logs')
+    # Creates a temp dir to be used by tests in this test class.
+    self.tmp_dir = tempfile.mkdtemp()
+
+  def tearDown(self):
+    """Removes the temp dir.
     """
+    shutil.rmtree(self.tmp_dir)
 
-    def setUp(self):
-        # Set log_path to logging since mobly logger setup is not called.
-        if not hasattr(logging, 'log_path'):
-            setattr(logging, 'log_path', '/tmp/logs')
-        # Creates a temp dir to be used by tests in this test class.
-        self.tmp_dir = tempfile.mkdtemp()
+  # Tests for android_device module functions.
+  # These tests use mock AndroidDevice instances.
 
-    def tearDown(self):
-        """Removes the temp dir.
-        """
-        shutil.rmtree(self.tmp_dir)
+  @mock.patch.object(android_device,
+             'get_all_instances',
+             new=mock_android_device.get_all_instances)
+  @mock.patch.object(android_device,
+             'list_adb_devices',
+             new=mock_android_device.list_adb_devices)
+  @mock.patch.object(android_device,
+             'list_adb_devices_by_usb_id',
+             new=mock_android_device.list_adb_devices)
+  def test_create_with_pickup_all(self):
+    pick_all_token = android_device.ANDROID_DEVICE_PICK_ALL_TOKEN
+    actual_ads = android_device.create(pick_all_token)
+    for actual, expected in zip(actual_ads,
+                  mock_android_device.get_mock_ads(5)):
+      self.assertEqual(actual.serial, expected.serial)
 
-    # Tests for android_device module functions.
-    # These tests use mock AndroidDevice instances.
+  @mock.patch.object(android_device,
+             'get_instances',
+             new=mock_android_device.get_instances)
+  @mock.patch.object(android_device,
+             'list_adb_devices',
+             new=mock_android_device.list_adb_devices)
+  @mock.patch.object(android_device,
+             'list_adb_devices_by_usb_id',
+             new=mock_android_device.list_adb_devices)
+  def test_create_with_string_list(self):
+    string_list = [u'1', '2']
+    actual_ads = android_device.create(string_list)
+    for actual_ad, expected_serial in zip(actual_ads, ['1', '2']):
+      self.assertEqual(actual_ad.serial, expected_serial)
 
-    @mock.patch.object(android_device,
-                       'get_all_instances',
-                       new=mock_android_device.get_all_instances)
-    @mock.patch.object(android_device,
-                       'list_adb_devices',
-                       new=mock_android_device.list_adb_devices)
-    @mock.patch.object(android_device,
-                       'list_adb_devices_by_usb_id',
-                       new=mock_android_device.list_adb_devices)
-    def test_create_with_pickup_all(self):
-        pick_all_token = android_device.ANDROID_DEVICE_PICK_ALL_TOKEN
-        actual_ads = android_device.create(pick_all_token)
-        for actual, expected in zip(actual_ads,
-                                    mock_android_device.get_mock_ads(5)):
-            self.assertEqual(actual.serial, expected.serial)
+  @mock.patch.object(android_device,
+             'get_instances_with_configs',
+             new=mock_android_device.get_instances_with_configs)
+  @mock.patch.object(android_device,
+             'list_adb_devices',
+             new=mock_android_device.list_adb_devices)
+  @mock.patch.object(android_device,
+             'list_adb_devices_by_usb_id',
+             new=mock_android_device.list_adb_devices)
+  def test_create_with_dict_list(self):
+    string_list = [{'serial': '1'}, {'serial': '2'}]
+    actual_ads = android_device.create(string_list)
+    for actual_ad, expected_serial in zip(actual_ads, ['1', '2']):
+      self.assertEqual(actual_ad.serial, expected_serial)
 
-    @mock.patch.object(android_device,
-                       'get_instances',
-                       new=mock_android_device.get_instances)
-    @mock.patch.object(android_device,
-                       'list_adb_devices',
-                       new=mock_android_device.list_adb_devices)
-    @mock.patch.object(android_device,
-                       'list_adb_devices_by_usb_id',
-                       new=mock_android_device.list_adb_devices)
-    def test_create_with_string_list(self):
-        string_list = [u'1', '2']
-        actual_ads = android_device.create(string_list)
-        for actual_ad, expected_serial in zip(actual_ads, ['1', '2']):
-            self.assertEqual(actual_ad.serial, expected_serial)
+  @mock.patch.object(android_device,
+             'get_instances_with_configs',
+             new=mock_android_device.get_instances_with_configs)
+  @mock.patch.object(android_device,
+             'list_adb_devices',
+             new=mock_android_device.list_adb_devices)
+  @mock.patch.object(android_device,
+             'list_adb_devices_by_usb_id',
+             return_value=['usb:1'])
+  def test_create_with_usb_id(self, mock_list_adb_devices_by_usb_id):
+    string_list = [{'serial': '1'}, {'serial': '2'}, {'serial': 'usb:1'}]
+    actual_ads = android_device.create(string_list)
+    for actual_ad, expected_serial in zip(actual_ads, ['1', '2', 'usb:1']):
+      self.assertEqual(actual_ad.serial, expected_serial)
 
-    @mock.patch.object(android_device,
-                       'get_instances_with_configs',
-                       new=mock_android_device.get_instances_with_configs)
-    @mock.patch.object(android_device,
-                       'list_adb_devices',
-                       new=mock_android_device.list_adb_devices)
-    @mock.patch.object(android_device,
-                       'list_adb_devices_by_usb_id',
-                       new=mock_android_device.list_adb_devices)
-    def test_create_with_dict_list(self):
-        string_list = [{'serial': '1'}, {'serial': '2'}]
-        actual_ads = android_device.create(string_list)
-        for actual_ad, expected_serial in zip(actual_ads, ['1', '2']):
-            self.assertEqual(actual_ad.serial, expected_serial)
+  def test_create_with_empty_config(self):
+    expected_msg = android_device.ANDROID_DEVICE_EMPTY_CONFIG_MSG
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      android_device.create([])
 
-    @mock.patch.object(android_device,
-                       'get_instances_with_configs',
-                       new=mock_android_device.get_instances_with_configs)
-    @mock.patch.object(android_device,
-                       'list_adb_devices',
-                       new=mock_android_device.list_adb_devices)
-    @mock.patch.object(android_device,
-                       'list_adb_devices_by_usb_id',
-                       return_value=['usb:1'])
-    def test_create_with_usb_id(self, mock_list_adb_devices_by_usb_id):
-        string_list = [{'serial': '1'}, {'serial': '2'}, {'serial': 'usb:1'}]
-        actual_ads = android_device.create(string_list)
-        for actual_ad, expected_serial in zip(actual_ads, ['1', '2', 'usb:1']):
-            self.assertEqual(actual_ad.serial, expected_serial)
+  def test_create_with_not_list_config(self):
+    expected_msg = android_device.ANDROID_DEVICE_NOT_LIST_CONFIG_MSG
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      android_device.create('HAHA')
 
-    def test_create_with_empty_config(self):
-        expected_msg = android_device.ANDROID_DEVICE_EMPTY_CONFIG_MSG
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            android_device.create([])
+  def test_create_with_no_valid_config(self):
+    expected_msg = 'No valid config found in: .*'
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      android_device.create([1])
 
-    def test_create_with_not_list_config(self):
-        expected_msg = android_device.ANDROID_DEVICE_NOT_LIST_CONFIG_MSG
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            android_device.create('HAHA')
+  def test_get_devices_success_with_extra_field(self):
+    ads = mock_android_device.get_mock_ads(5)
+    expected_label = 'selected'
+    expected_count = 2
+    for ad in ads[:expected_count]:
+      ad.label = expected_label
+    selected_ads = android_device.get_devices(ads, label=expected_label)
+    self.assertEqual(expected_count, len(selected_ads))
+    for ad in selected_ads:
+      self.assertEqual(ad.label, expected_label)
 
-    def test_create_with_no_valid_config(self):
-        expected_msg = 'No valid config found in: .*'
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            android_device.create([1])
+  def test_get_devices_no_match(self):
+    ads = mock_android_device.get_mock_ads(5)
+    expected_msg = ('Could not find a target device that matches condition'
+            ": {'label': 'selected'}.")
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      selected_ads = android_device.get_devices(ads, label='selected')
 
-    def test_get_devices_success_with_extra_field(self):
-        ads = mock_android_device.get_mock_ads(5)
-        expected_label = 'selected'
-        expected_count = 2
-        for ad in ads[:expected_count]:
-            ad.label = expected_label
-        selected_ads = android_device.get_devices(ads, label=expected_label)
-        self.assertEqual(expected_count, len(selected_ads))
-        for ad in selected_ads:
-            self.assertEqual(ad.label, expected_label)
+  def test_get_device_success_with_serial(self):
+    ads = mock_android_device.get_mock_ads(5)
+    expected_serial = '0'
+    ad = android_device.get_device(ads, serial=expected_serial)
+    self.assertEqual(ad.serial, expected_serial)
 
-    def test_get_devices_no_match(self):
-        ads = mock_android_device.get_mock_ads(5)
-        expected_msg = ('Could not find a target device that matches condition'
-                        ": {'label': 'selected'}.")
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            selected_ads = android_device.get_devices(ads, label='selected')
+  def test_get_device_success_with_serial_and_extra_field(self):
+    ads = mock_android_device.get_mock_ads(5)
+    expected_serial = '1'
+    expected_h_port = 5555
+    ads[1].h_port = expected_h_port
+    ad = android_device.get_device(ads,
+                     serial=expected_serial,
+                     h_port=expected_h_port)
+    self.assertEqual(ad.serial, expected_serial)
+    self.assertEqual(ad.h_port, expected_h_port)
 
-    def test_get_device_success_with_serial(self):
-        ads = mock_android_device.get_mock_ads(5)
-        expected_serial = '0'
-        ad = android_device.get_device(ads, serial=expected_serial)
-        self.assertEqual(ad.serial, expected_serial)
+  def test_get_device_no_match(self):
+    ads = mock_android_device.get_mock_ads(5)
+    expected_msg = ('Could not find a target device that matches condition'
+            ": {'serial': 5}.")
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      ad = android_device.get_device(ads, serial=len(ads))
 
-    def test_get_device_success_with_serial_and_extra_field(self):
-        ads = mock_android_device.get_mock_ads(5)
-        expected_serial = '1'
-        expected_h_port = 5555
-        ads[1].h_port = expected_h_port
-        ad = android_device.get_device(ads,
-                                       serial=expected_serial,
-                                       h_port=expected_h_port)
-        self.assertEqual(ad.serial, expected_serial)
-        self.assertEqual(ad.h_port, expected_h_port)
+  def test_get_device_too_many_matches(self):
+    ads = mock_android_device.get_mock_ads(5)
+    target_serial = ads[1].serial = ads[0].serial
+    expected_msg = r"More than one device matched: \['0', '0'\]"
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      android_device.get_device(ads, serial=target_serial)
 
-    def test_get_device_no_match(self):
-        ads = mock_android_device.get_mock_ads(5)
-        expected_msg = ('Could not find a target device that matches condition'
-                        ": {'serial': 5}.")
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            ad = android_device.get_device(ads, serial=len(ads))
+  def test_start_services_on_ads(self):
+    """Makes sure when an AndroidDevice fails to start some services, all
+    AndroidDevice objects get cleaned up.
+    """
+    msg = 'Some error happened.'
+    ads = mock_android_device.get_mock_ads(3)
+    for ad in ads:
+      ad.services.logcat.start = mock.MagicMock()
+      ad.services.stop_all = mock.MagicMock()
+      ad.skip_logcat = False
+      ad.is_required = True
+    ads[1].services.logcat.start = mock.MagicMock(
+      side_effect=android_device.Error(msg))
+    with self.assertRaisesRegex(android_device.Error, msg):
+      android_device._start_services_on_ads(ads)
+    ads[0].services.stop_all.assert_called_once_with()
+    ads[1].services.stop_all.assert_called_once_with()
+    ads[2].services.stop_all.assert_called_once_with()
 
-    def test_get_device_too_many_matches(self):
-        ads = mock_android_device.get_mock_ads(5)
-        target_serial = ads[1].serial = ads[0].serial
-        expected_msg = r"More than one device matched: \['0', '0'\]"
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            android_device.get_device(ads, serial=target_serial)
+  def test_start_services_on_ads_skip_logcat(self):
+    ads = mock_android_device.get_mock_ads(3)
+    ads[0].services.logcat.start = mock.MagicMock()
+    ads[1].services.logcat.start = mock.MagicMock()
+    ads[2].services.logcat.start = mock.MagicMock(
+      side_effect=Exception('Should not have called this.'))
+    ads[2].skip_logcat = True
+    android_device._start_services_on_ads(ads)
 
-    def test_start_services_on_ads(self):
-        """Makes sure when an AndroidDevice fails to start some services, all
-        AndroidDevice objects get cleaned up.
-        """
-        msg = 'Some error happened.'
-        ads = mock_android_device.get_mock_ads(3)
-        for ad in ads:
-            ad.services.logcat.start = mock.MagicMock()
-            ad.services.stop_all = mock.MagicMock()
-            ad.skip_logcat = False
-            ad.is_required = True
-        ads[1].services.logcat.start = mock.MagicMock(
-            side_effect=android_device.Error(msg))
-        with self.assertRaisesRegex(android_device.Error, msg):
-            android_device._start_services_on_ads(ads)
-        ads[0].services.stop_all.assert_called_once_with()
-        ads[1].services.stop_all.assert_called_once_with()
-        ads[2].services.stop_all.assert_called_once_with()
+  def test_take_bug_reports(self):
+    ads = mock_android_device.get_mock_ads(3)
+    android_device.take_bug_reports(ads, 'test_something', 'sometime')
+    ads[0].take_bug_report.assert_called_once_with(
+      test_name='test_something',
+      begin_time='sometime',
+      destination=None)
+    ads[1].take_bug_report.assert_called_once_with(
+      test_name='test_something',
+      begin_time='sometime',
+      destination=None)
+    ads[2].take_bug_report.assert_called_once_with(
+      test_name='test_something',
+      begin_time='sometime',
+      destination=None)
 
-    def test_start_services_on_ads_skip_logcat(self):
-        ads = mock_android_device.get_mock_ads(3)
-        ads[0].services.logcat.start = mock.MagicMock()
-        ads[1].services.logcat.start = mock.MagicMock()
-        ads[2].services.logcat.start = mock.MagicMock(
-            side_effect=Exception('Should not have called this.'))
-        ads[2].skip_logcat = True
-        android_device._start_services_on_ads(ads)
+  def test_take_bug_reports_with_int_begin_time(self):
+    ads = mock_android_device.get_mock_ads(3)
+    android_device.take_bug_reports(ads, 'test_something', 123)
+    ads[0].take_bug_report.assert_called_once_with(
+      test_name='test_something', begin_time='123', destination=None)
+    ads[1].take_bug_report.assert_called_once_with(
+      test_name='test_something', begin_time='123', destination=None)
+    ads[2].take_bug_report.assert_called_once_with(
+      test_name='test_something', begin_time='123', destination=None)
 
-    def test_take_bug_reports(self):
-        ads = mock_android_device.get_mock_ads(3)
-        android_device.take_bug_reports(ads, 'test_something', 'sometime')
-        ads[0].take_bug_report.assert_called_once_with(
-            test_name='test_something',
-            begin_time='sometime',
-            destination=None)
-        ads[1].take_bug_report.assert_called_once_with(
-            test_name='test_something',
-            begin_time='sometime',
-            destination=None)
-        ads[2].take_bug_report.assert_called_once_with(
-            test_name='test_something',
-            begin_time='sometime',
-            destination=None)
+  @mock.patch('mobly.logger.get_log_file_timestamp')
+  def test_take_bug_reports_with_none_values(self,
+                         get_log_file_timestamp_mock):
+    mock_timestamp = '07-22-2019_17-55-30-765'
+    get_log_file_timestamp_mock.return_value = mock_timestamp
+    ads = mock_android_device.get_mock_ads(3)
+    android_device.take_bug_reports(ads)
+    ads[0].take_bug_report.assert_called_once_with(
+      test_name=None, begin_time=mock_timestamp, destination=None)
+    ads[1].take_bug_report.assert_called_once_with(
+      test_name=None, begin_time=mock_timestamp, destination=None)
+    ads[2].take_bug_report.assert_called_once_with(
+      test_name=None, begin_time=mock_timestamp, destination=None)
 
-    def test_take_bug_reports_with_int_begin_time(self):
-        ads = mock_android_device.get_mock_ads(3)
-        android_device.take_bug_reports(ads, 'test_something', 123)
-        ads[0].take_bug_report.assert_called_once_with(
-            test_name='test_something', begin_time='123', destination=None)
-        ads[1].take_bug_report.assert_called_once_with(
-            test_name='test_something', begin_time='123', destination=None)
-        ads[2].take_bug_report.assert_called_once_with(
-            test_name='test_something', begin_time='123', destination=None)
+  # Tests for android_device.AndroidDevice class.
+  # These tests mock out any interaction with the OS and real android device
+  # in AndroidDeivce.
 
-    @mock.patch('mobly.logger.get_log_file_timestamp')
-    def test_take_bug_reports_with_none_values(self,
-                                               get_log_file_timestamp_mock):
-        mock_timestamp = '07-22-2019_17-55-30-765'
-        get_log_file_timestamp_mock.return_value = mock_timestamp
-        ads = mock_android_device.get_mock_ads(3)
-        android_device.take_bug_reports(ads)
-        ads[0].take_bug_report.assert_called_once_with(
-            test_name=None, begin_time=mock_timestamp, destination=None)
-        ads[1].take_bug_report.assert_called_once_with(
-            test_name=None, begin_time=mock_timestamp, destination=None)
-        ads[2].take_bug_report.assert_called_once_with(
-            test_name=None, begin_time=mock_timestamp, destination=None)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  def test_AndroidDevice_instantiation(self, MockFastboot, MockAdbProxy):
+    """Verifies the AndroidDevice object's basic attributes are correctly
+    set after instantiation.
+    """
+    mock_serial = 1
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    self.assertEqual(ad.serial, '1')
+    self.assertEqual(ad.model, 'fakemodel')
+    expected_lp = os.path.join(logging.log_path,
+                   'AndroidDevice%s' % mock_serial)
+    self.assertEqual(ad.log_path, expected_lp)
+    self.assertIsNotNone(ad.services.logcat)
+    self.assertIsNotNone(ad.services.snippets)
 
-    # Tests for android_device.AndroidDevice class.
-    # These tests mock out any interaction with the OS and real android device
-    # in AndroidDeivce.
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(1))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy(1))
+  @mock.patch('mobly.utils.create_dir')
+  def test_AndroidDevice_load_config(self, create_dir_mock, FastbootProxy,
+                     MockAdbProxy):
+    mock_serial = '1'
+    config = {
+      'space': 'the final frontier',
+      'number': 1,
+      'debug_tag': 'my_tag'
+    }
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    ad.load_config(config)
+    self.assertEqual(ad.space, 'the final frontier')
+    self.assertEqual(ad.number, 1)
+    self.assertEqual(ad.debug_tag, 'my_tag')
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    def test_AndroidDevice_instantiation(self, MockFastboot, MockAdbProxy):
-        """Verifies the AndroidDevice object's basic attributes are correctly
-        set after instantiation.
-        """
-        mock_serial = 1
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        self.assertEqual(ad.serial, '1')
-        self.assertEqual(ad.model, 'fakemodel')
-        expected_lp = os.path.join(logging.log_path,
-                                   'AndroidDevice%s' % mock_serial)
-        self.assertEqual(ad.log_path, expected_lp)
-        self.assertIsNotNone(ad.services.logcat)
-        self.assertIsNotNone(ad.services.snippets)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(1))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy(1))
+  @mock.patch('mobly.utils.create_dir')
+  def test_AndroidDevice_load_config_dup(self, create_dir_mock,
+                       FastbootProxy, MockAdbProxy):
+    mock_serial = '1'
+    config = {'serial': 'new_serial'}
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    with self.assertRaisesRegex(android_device.DeviceError,
+                  'Attribute serial already exists with'):
+      ad.load_config(config)
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(1))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy(1))
-    @mock.patch('mobly.utils.create_dir')
-    def test_AndroidDevice_load_config(self, create_dir_mock, FastbootProxy,
-                                       MockAdbProxy):
-        mock_serial = '1'
-        config = {
-            'space': 'the final frontier',
-            'number': 1,
-            'debug_tag': 'my_tag'
-        }
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        ad.load_config(config)
-        self.assertEqual(ad.space, 'the final frontier')
-        self.assertEqual(ad.number, 1)
-        self.assertEqual(ad.debug_tag, 'my_tag')
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  def test_AndroidDevice_build_info(self, MockFastboot, MockAdbProxy):
+    """Verifies the AndroidDevice object's basic attributes are correctly
+    set after instantiation.
+    """
+    ad = android_device.AndroidDevice(serial='1')
+    build_info = ad.build_info
+    self.assertEqual(build_info['build_id'], 'AB42')
+    self.assertEqual(build_info['build_type'], 'userdebug')
+    self.assertEqual(build_info['build_version_codename'], 'Z')
+    self.assertEqual(build_info['build_version_sdk'], '28')
+    self.assertEqual(build_info['build_product'], 'FakeModel')
+    self.assertEqual(build_info['build_characteristics'], 'emulator,phone')
+    self.assertEqual(build_info['product_name'], 'FakeModel')
+    self.assertEqual(build_info['debuggable'], '1')
+    self.assertEqual(build_info['hardware'], 'marlin')
+    self.assertEqual(len(build_info),
+             len(android_device.CACHED_SYSTEM_PROPS))
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(1))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy(1))
-    @mock.patch('mobly.utils.create_dir')
-    def test_AndroidDevice_load_config_dup(self, create_dir_mock,
-                                           FastbootProxy, MockAdbProxy):
-        mock_serial = '1'
-        config = {'serial': 'new_serial'}
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        with self.assertRaisesRegex(android_device.DeviceError,
-                                    'Attribute serial already exists with'):
-            ad.load_config(config)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(
+          '1',
+          mock_properties={
+            'ro.build.id': 'AB42',
+            'ro.build.type': 'userdebug',
+          }))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  def test_AndroidDevice_build_info_with_minimal_properties(
+      self, MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    build_info = ad.build_info
+    self.assertEqual(build_info['build_id'], 'AB42')
+    self.assertEqual(build_info['build_type'], 'userdebug')
+    self.assertEqual(build_info['build_version_codename'], '')
+    self.assertEqual(build_info['build_version_sdk'], '')
+    self.assertEqual(build_info['build_product'], '')
+    self.assertEqual(build_info['build_characteristics'], '')
+    self.assertEqual(build_info['product_name'], '')
+    self.assertEqual(build_info['debuggable'], '')
+    self.assertEqual(build_info['hardware'], '')
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    def test_AndroidDevice_build_info(self, MockFastboot, MockAdbProxy):
-        """Verifies the AndroidDevice object's basic attributes are correctly
-        set after instantiation.
-        """
-        ad = android_device.AndroidDevice(serial='1')
-        build_info = ad.build_info
-        self.assertEqual(build_info['build_id'], 'AB42')
-        self.assertEqual(build_info['build_type'], 'userdebug')
-        self.assertEqual(build_info['build_version_codename'], 'Z')
-        self.assertEqual(build_info['build_version_sdk'], '28')
-        self.assertEqual(build_info['build_product'], 'FakeModel')
-        self.assertEqual(build_info['build_characteristics'], 'emulator,phone')
-        self.assertEqual(build_info['product_name'], 'FakeModel')
-        self.assertEqual(build_info['debuggable'], '1')
-        self.assertEqual(build_info['hardware'], 'marlin')
-        self.assertEqual(len(build_info),
-                         len(android_device.CACHED_SYSTEM_PROPS))
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  def test_AndroidDevice_build_info_cached(self, MockFastboot, MockAdbProxy):
+    """Verifies the AndroidDevice object's basic attributes are correctly
+    set after instantiation.
+    """
+    ad = android_device.AndroidDevice(serial='1')
+    _ = ad.build_info
+    _ = ad.build_info
+    _ = ad.build_info
+    self.assertEqual(ad.adb.getprops_call_count, 1)
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(
-                    '1',
-                    mock_properties={
-                        'ro.build.id': 'AB42',
-                        'ro.build.type': 'userdebug',
-                    }))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    def test_AndroidDevice_build_info_with_minimal_properties(
-            self, MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        build_info = ad.build_info
-        self.assertEqual(build_info['build_id'], 'AB42')
-        self.assertEqual(build_info['build_type'], 'userdebug')
-        self.assertEqual(build_info['build_version_codename'], '')
-        self.assertEqual(build_info['build_version_sdk'], '')
-        self.assertEqual(build_info['build_product'], '')
-        self.assertEqual(build_info['build_characteristics'], '')
-        self.assertEqual(build_info['product_name'], '')
-        self.assertEqual(build_info['debuggable'], '')
-        self.assertEqual(build_info['hardware'], '')
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(
+          '1',
+          mock_properties={
+            'ro.build.id': 'AB42',
+            'ro.build.type': 'userdebug',
+            'ro.debuggable': '1',
+          }))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  def test_AndroidDevice_is_rootable_when_userdebug_device(
+      self, MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    self.assertTrue(ad.is_rootable)
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    def test_AndroidDevice_build_info_cached(self, MockFastboot, MockAdbProxy):
-        """Verifies the AndroidDevice object's basic attributes are correctly
-        set after instantiation.
-        """
-        ad = android_device.AndroidDevice(serial='1')
-        _ = ad.build_info
-        _ = ad.build_info
-        _ = ad.build_info
-        self.assertEqual(ad.adb.getprops_call_count, 1)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(
+          '1',
+          mock_properties={
+            'ro.build.id': 'AB42',
+            'ro.build.type': 'user',
+            'ro.debuggable': '0',
+          }))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  def test_AndroidDevice_is_rootable_when_user_device(
+      self, MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    self.assertFalse(ad.is_rootable)
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(
-                    '1',
-                    mock_properties={
-                        'ro.build.id': 'AB42',
-                        'ro.build.type': 'userdebug',
-                        'ro.debuggable': '1',
-                    }))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    def test_AndroidDevice_is_rootable_when_userdebug_device(
-            self, MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        self.assertTrue(ad.is_rootable)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  def test_AndroidDevice_device_info(self, MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial=1)
+    device_info = ad.device_info
+    self.assertEqual(device_info['serial'], '1')
+    self.assertEqual(device_info['model'], 'fakemodel')
+    self.assertEqual(device_info['build_info']['build_id'], 'AB42')
+    self.assertEqual(device_info['build_info']['build_type'], 'userdebug')
+    ad.add_device_info('sim_type', 'Fi')
+    ad.add_device_info('build_id', 'CD42')
+    device_info = ad.device_info
+    self.assertEqual(device_info['user_added_info']['sim_type'], 'Fi')
+    self.assertEqual(device_info['user_added_info']['build_id'], 'CD42')
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(
-                    '1',
-                    mock_properties={
-                        'ro.build.id': 'AB42',
-                        'ro.build.type': 'user',
-                        'ro.debuggable': '0',
-                    }))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    def test_AndroidDevice_is_rootable_when_user_device(
-            self, MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        self.assertFalse(ad.is_rootable)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  def test_AndroidDevice_serial_is_valid(self, MockFastboot, MockAdbProxy):
+    """Verifies that the serial is a primitive string type and serializable.
+    """
+    ad = android_device.AndroidDevice(serial=1)
+    # In py2, checks that ad.serial is not the backported py3 str type,
+    # which is not dumpable by yaml in py2.
+    # In py3, new_str is equivalent to str, so this check is not
+    # appropirate in py3.
+    if sys.version_info < (3, 0):
+      self.assertFalse(isinstance(ad.serial, new_str))
+    self.assertTrue(isinstance(ad.serial, str))
+    yaml.safe_dump(ad.serial)
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    def test_AndroidDevice_device_info(self, MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial=1)
-        device_info = ad.device_info
-        self.assertEqual(device_info['serial'], '1')
-        self.assertEqual(device_info['model'], 'fakemodel')
-        self.assertEqual(device_info['build_info']['build_id'], 'AB42')
-        self.assertEqual(device_info['build_info']['build_type'], 'userdebug')
-        ad.add_device_info('sim_type', 'Fi')
-        ad.add_device_info('build_id', 'CD42')
-        device_info = ad.device_info
-        self.assertEqual(device_info['user_added_info']['sim_type'], 'Fi')
-        self.assertEqual(device_info['user_added_info']['build_id'], 'CD42')
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  def test_AndroidDevice_is_emulator_when_realish_device(
+      self, MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    self.assertFalse(ad.is_emulator)
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    def test_AndroidDevice_serial_is_valid(self, MockFastboot, MockAdbProxy):
-        """Verifies that the serial is a primitive string type and serializable.
-        """
-        ad = android_device.AndroidDevice(serial=1)
-        # In py2, checks that ad.serial is not the backported py3 str type,
-        # which is not dumpable by yaml in py2.
-        # In py3, new_str is equivalent to str, so this check is not
-        # appropirate in py3.
-        if sys.version_info < (3, 0):
-            self.assertFalse(isinstance(ad.serial, new_str))
-        self.assertTrue(isinstance(ad.serial, str))
-        yaml.safe_dump(ad.serial)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('localhost:123'))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+    return_value=mock_android_device.MockFastbootProxy('localhost:123'))
+  def test_AndroidDevice_is_emulator_when_local_networked_device(
+      self, MockFastboot, MockAdbProxy):
+    # Although these devices are usually emulators, there might be a reason
+    # to do this with a real device.
+    ad = android_device.AndroidDevice(serial='localhost:123')
+    self.assertFalse(ad.is_emulator)
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    def test_AndroidDevice_is_emulator_when_realish_device(
-            self, MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        self.assertFalse(ad.is_emulator)
+  @mock.patch(
+    'mobly.controllers.android_device_lib.adb.AdbProxy',
+    return_value=mock_android_device.MockAdbProxy('example.com:123'))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+    return_value=mock_android_device.MockFastbootProxy('example:123'))
+  def test_AndroidDevice_is_emulator_when_remote_networked_device(
+      self, MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='example.com:123')
+    self.assertFalse(ad.is_emulator)
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('localhost:123'))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-        return_value=mock_android_device.MockFastbootProxy('localhost:123'))
-    def test_AndroidDevice_is_emulator_when_local_networked_device(
-            self, MockFastboot, MockAdbProxy):
-        # Although these devices are usually emulators, there might be a reason
-        # to do this with a real device.
-        ad = android_device.AndroidDevice(serial='localhost:123')
-        self.assertFalse(ad.is_emulator)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(
+          'localhost:5554',
+          mock_properties={
+            'ro.hardware': 'ranchu',
+            'ro.build.id': 'AB42',
+            'ro.build.type': 'userdebug',
+          }))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+    return_value=mock_android_device.MockFastbootProxy('localhost:5554'))
+  def test_AndroidDevice_is_emulator_when_ranchu_device(
+      self, MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='localhost:5554')
+    self.assertTrue(ad.is_emulator)
 
-    @mock.patch(
-        'mobly.controllers.android_device_lib.adb.AdbProxy',
-        return_value=mock_android_device.MockAdbProxy('example.com:123'))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-        return_value=mock_android_device.MockFastbootProxy('example:123'))
-    def test_AndroidDevice_is_emulator_when_remote_networked_device(
-            self, MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='example.com:123')
-        self.assertFalse(ad.is_emulator)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(
+          '1',
+          mock_properties={
+            'ro.build.id': 'AB42',
+            'ro.build.type': 'userdebug',
+            'ro.hardware': 'goldfish',
+          }))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  def test_AndroidDevice_is_emulator_when_goldfish_device(
+      self, MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    self.assertTrue(ad.is_emulator)
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(
-                    'localhost:5554',
-                    mock_properties={
-                        'ro.hardware': 'ranchu',
-                        'ro.build.id': 'AB42',
-                        'ro.build.type': 'userdebug',
-                    }))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-        return_value=mock_android_device.MockFastbootProxy('localhost:5554'))
-    def test_AndroidDevice_is_emulator_when_ranchu_device(
-            self, MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='localhost:5554')
-        self.assertTrue(ad.is_emulator)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(
+          'example.com:123',
+          mock_properties={
+            'ro.build.id': 'AB42',
+            'ro.build.type': 'userdebug',
+            'ro.build.characteristics': 'emulator',
+          }))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+    return_value=mock_android_device.MockFastbootProxy('example.com:123'))
+  def test_AndroidDevice_is_emulator_when_emulator_characteristic(
+      self, MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='example.com:123')
+    self.assertTrue(ad.is_emulator)
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(
-                    '1',
-                    mock_properties={
-                        'ro.build.id': 'AB42',
-                        'ro.build.type': 'userdebug',
-                        'ro.hardware': 'goldfish',
-                    }))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    def test_AndroidDevice_is_emulator_when_goldfish_device(
-            self, MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        self.assertTrue(ad.is_emulator)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('emulator-5554'))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+    return_value=mock_android_device.MockFastbootProxy('emulator-5554'))
+  def test_AndroidDevice_is_emulator_when_emulator_serial(
+      self, MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='emulator-5554')
+    self.assertTrue(ad.is_emulator)
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(
-                    'example.com:123',
-                    mock_properties={
-                        'ro.build.id': 'AB42',
-                        'ro.build.type': 'userdebug',
-                        'ro.build.characteristics': 'emulator',
-                    }))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-        return_value=mock_android_device.MockFastbootProxy('example.com:123'))
-    def test_AndroidDevice_is_emulator_when_emulator_characteristic(
-            self, MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='example.com:123')
-        self.assertTrue(ad.is_emulator)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.logger.get_log_file_timestamp')
+  def test_AndroidDevice_generate_filename_default(
+      self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
+    mock_serial = 1
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
+    filename = ad.generate_filename('MagicLog')
+    self.assertEqual(filename,
+             'MagicLog,1,fakemodel,07-22-2019_17-53-34-450')
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('emulator-5554'))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-        return_value=mock_android_device.MockFastbootProxy('emulator-5554'))
-    def test_AndroidDevice_is_emulator_when_emulator_serial(
-            self, MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='emulator-5554')
-        self.assertTrue(ad.is_emulator)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.logger.get_log_file_timestamp')
+  @mock.patch('mobly.logger.sanitize_filename')
+  def test_AndroidDevice_generate_filename_assert_sanitation(
+      self, sanitize_filename_mock, get_log_file_timestamp_mock,
+      MockFastboot, MockAdbProxy):
+    mock_serial = 1
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
+    filename = ad.generate_filename('MagicLog')
+    sanitize_filename_mock.assert_called_with(
+      'MagicLog,1,fakemodel,07-22-2019_17-53-34-450')
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.logger.get_log_file_timestamp')
-    def test_AndroidDevice_generate_filename_default(
-            self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
-        mock_serial = 1
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
-        filename = ad.generate_filename('MagicLog')
-        self.assertEqual(filename,
-                         'MagicLog,1,fakemodel,07-22-2019_17-53-34-450')
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.logger.get_log_file_timestamp')
+  def test_AndroidDevice_generate_filename_with_ext(
+      self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
+    mock_serial = 1
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
+    filename = ad.generate_filename('MagicLog', extension_name='log')
+    self.assertEqual(filename,
+             'MagicLog,1,fakemodel,07-22-2019_17-53-34-450.log')
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.logger.get_log_file_timestamp')
-    @mock.patch('mobly.logger.sanitize_filename')
-    def test_AndroidDevice_generate_filename_assert_sanitation(
-            self, sanitize_filename_mock, get_log_file_timestamp_mock,
-            MockFastboot, MockAdbProxy):
-        mock_serial = 1
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
-        filename = ad.generate_filename('MagicLog')
-        sanitize_filename_mock.assert_called_with(
-            'MagicLog,1,fakemodel,07-22-2019_17-53-34-450')
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.logger.get_log_file_timestamp')
+  def test_AndroidDevice_generate_filename_with_debug_tag(
+      self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
+    mock_serial = 1
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
+    ad.debug_tag = 'RoleX'
+    filename = ad.generate_filename('MagicLog')
+    self.assertEqual(filename,
+             'MagicLog,RoleX,1,fakemodel,07-22-2019_17-53-34-450')
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.logger.get_log_file_timestamp')
-    def test_AndroidDevice_generate_filename_with_ext(
-            self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
-        mock_serial = 1
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
-        filename = ad.generate_filename('MagicLog', extension_name='log')
-        self.assertEqual(filename,
-                         'MagicLog,1,fakemodel,07-22-2019_17-53-34-450.log')
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.logger.get_log_file_timestamp')
-    def test_AndroidDevice_generate_filename_with_debug_tag(
-            self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
-        mock_serial = 1
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
-        ad.debug_tag = 'RoleX'
-        filename = ad.generate_filename('MagicLog')
-        self.assertEqual(filename,
-                         'MagicLog,RoleX,1,fakemodel,07-22-2019_17-53-34-450')
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.logger.get_log_file_timestamp')
-    def test_AndroidDevice_generate_filename_with_runtime_info(
-            self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
-        mock_serial = 1
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
-        mock_record = mock.MagicMock(begin_time='1234567')
-        mock_test_info = runtime_test_info.RuntimeTestInfo(
-            'test_xyz', '/tmp/blah/', mock_record)
-        filename = ad.generate_filename('MagicLog',
-                                        time_identifier=mock_test_info)
-        self.assertEqual(filename, 'MagicLog,1,fakemodel,test_xyz-1234567')
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.logger.get_log_file_timestamp')
-    def test_AndroidDevice_generate_filename_with_custom_timestamp(
-            self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
-        mock_serial = 1
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
-        filename = ad.generate_filename('MagicLog',
-                                        time_identifier='my_special_time')
-        self.assertEqual(filename, 'MagicLog,1,fakemodel,my_special_time')
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(1))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy(1))
-    @mock.patch('mobly.utils.create_dir')
-    def test_AndroidDevice_take_bug_report(self, create_dir_mock,
-                                           FastbootProxy, MockAdbProxy):
-        """Verifies AndroidDevice.take_bug_report calls the correct adb command
-        and writes the bugreport file to the correct path.
-        """
-        mock_serial = '1'
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        output_path = ad.take_bug_report(test_name='test_something',
-                                         begin_time='sometime')
-        expected_path = os.path.join(logging.log_path,
-                                     'AndroidDevice%s' % ad.serial,
-                                     'BugReports')
-        create_dir_mock.assert_called_with(expected_path)
-        self.assertEqual(
-            output_path,
-            os.path.join(expected_path,
-                         'bugreport,test_something,1,fakemodel,sometime.zip'))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1',
-                                                              fail_br=True))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.create_dir')
-    def test_AndroidDevice_take_bug_report_fail(self, create_dir_mock,
-                                                FastbootProxy, MockAdbProxy):
-        """Verifies AndroidDevice.take_bug_report writes out the correct message
-        when taking bugreport fails.
-        """
-        mock_serial = '1'
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        expected_msg = '.* Failed to take bugreport.'
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            ad.take_bug_report(test_name='test_something',
-                               begin_time='sometime')
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.create_dir')
-    @mock.patch('mobly.logger.get_log_file_timestamp')
-    def test_AndroidDevice_take_bug_report_without_args(
-            self, get_log_file_timestamp_mock, create_dir_mock, FastbootProxy,
-            MockAdbProxy):
-        get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
-        mock_serial = '1'
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        output_path = ad.take_bug_report()
-        expected_path = os.path.join(logging.log_path,
-                                     'AndroidDevice%s' % ad.serial,
-                                     'BugReports')
-        self.assertEqual(
-            output_path,
-            os.path.join(expected_path,
-                         'bugreport,1,fakemodel,07-22-2019_17-53-34-450.zip'))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.create_dir')
-    @mock.patch('mobly.logger.get_log_file_timestamp')
-    def test_AndroidDevice_take_bug_report_with_only_test_name(
-            self, get_log_file_timestamp_mock, create_dir_mock, FastbootProxy,
-            MockAdbProxy):
-        get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
-        mock_serial = '1'
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        output_path = ad.take_bug_report(test_name='test_something')
-        expected_path = os.path.join(logging.log_path,
-                                     'AndroidDevice%s' % ad.serial,
-                                     'BugReports')
-        create_dir_mock.assert_called_with(expected_path)
-        self.assertEqual(
-            output_path,
-            os.path.join(
-                expected_path,
-                'bugreport,test_something,1,fakemodel,07-22-2019_17-53-34-450.zip'
-            ))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(1))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy(1))
-    @mock.patch('mobly.utils.create_dir')
-    def test_AndroidDevice_take_bug_report_with_only_begin_time(
-            self, create_dir_mock, FastbootProxy, MockAdbProxy):
-        mock_serial = '1'
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        output_path = ad.take_bug_report(begin_time='sometime')
-        expected_path = os.path.join(logging.log_path,
-                                     'AndroidDevice%s' % ad.serial,
-                                     'BugReports')
-        create_dir_mock.assert_called_with(expected_path)
-        self.assertEqual(
-            output_path,
-            os.path.join(expected_path, 'bugreport,1,fakemodel,sometime.zip'))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(1))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy(1))
-    @mock.patch('mobly.utils.create_dir')
-    def test_AndroidDevice_take_bug_report_with_int_begin_time(
-            self, create_dir_mock, FastbootProxy, MockAdbProxy):
-        mock_serial = '1'
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        output_path = ad.take_bug_report(begin_time=123)
-        expected_path = os.path.join(logging.log_path,
-                                     'AndroidDevice%s' % ad.serial,
-                                     'BugReports')
-        create_dir_mock.assert_called_with(expected_path)
-        self.assertEqual(
-            output_path,
-            os.path.join(expected_path, 'bugreport,1,fakemodel,123.zip'))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(1))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy(1))
-    @mock.patch('mobly.utils.create_dir')
-    def test_AndroidDevice_take_bug_report_with_positional_args(
-            self, create_dir_mock, FastbootProxy, MockAdbProxy):
-        mock_serial = '1'
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        output_path = ad.take_bug_report('test_something', 'sometime')
-        expected_path = os.path.join(logging.log_path,
-                                     'AndroidDevice%s' % ad.serial,
-                                     'BugReports')
-        create_dir_mock.assert_called_with(expected_path)
-        self.assertEqual(
-            output_path,
-            os.path.join(expected_path,
-                         'bugreport,test_something,1,fakemodel,sometime.zip'))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.create_dir')
-    def test_AndroidDevice_take_bug_report_with_destination(
-            self, create_dir_mock, FastbootProxy, MockAdbProxy):
-        mock_serial = '1'
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        dest = tempfile.gettempdir()
-        output_path = ad.take_bug_report(test_name="test_something",
-                                         begin_time="sometime",
-                                         destination=dest)
-        expected_path = os.path.join(dest)
-        create_dir_mock.assert_called_with(expected_path)
-        self.assertEqual(
-            output_path,
-            os.path.join(expected_path,
-                         'bugreport,test_something,1,fakemodel,sometime.zip'))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(
-                    '1', fail_br_before_N=True))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.create_dir')
-    def test_AndroidDevice_take_bug_report_fallback(self, create_dir_mock,
-                                                    FastbootProxy,
-                                                    MockAdbProxy):
-        """Verifies AndroidDevice.take_bug_report falls back to traditional
-        bugreport on builds that do not have bugreportz.
-        """
-        mock_serial = '1'
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        output_path = ad.take_bug_report(test_name='test_something',
-                                         begin_time='sometime')
-        expected_path = os.path.join(logging.log_path,
-                                     'AndroidDevice%s' % ad.serial,
-                                     'BugReports')
-        create_dir_mock.assert_called_with(expected_path)
-        self.assertEqual(
-            output_path,
-            os.path.join(expected_path,
-                         'bugreport,test_something,1,fakemodel,sometime.txt'))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.create_dir')
-    @mock.patch('mobly.logger.get_log_file_timestamp')
-    def test_AndroidDevice_take_screenshot(self, get_log_file_timestamp_mock,
-                                           create_dir_mock, FastbootProxy,
-                                           MockAdbProxy):
-        get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
-        mock_serial = '1'
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        full_pic_path = ad.take_screenshot(self.tmp_dir)
-        self.assertEqual(
-            full_pic_path,
-            os.path.join(self.tmp_dir,
-                         'screenshot,1,fakemodel,07-22-2019_17-53-34-450.png'))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.start_standing_subprocess',
-                return_value='process')
-    @mock.patch('mobly.utils.stop_standing_subprocess')
-    def test_AndroidDevice_change_log_path(self, stop_proc_mock,
-                                           start_proc_mock, FastbootProxy,
-                                           MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        old_path = ad.log_path
-        new_log_path = tempfile.mkdtemp()
-        ad.log_path = new_log_path
-        self.assertTrue(os.path.exists(new_log_path))
-        self.assertFalse(os.path.exists(old_path))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.start_standing_subprocess',
-                return_value='process')
-    @mock.patch('mobly.utils.stop_standing_subprocess')
-    def test_AndroidDevice_change_log_path_no_log_exists(
-            self, stop_proc_mock, start_proc_mock, FastbootProxy,
-            MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        old_path = ad.log_path
-        new_log_path = tempfile.mkdtemp()
-        ad.log_path = new_log_path
-        self.assertTrue(os.path.exists(new_log_path))
-        self.assertFalse(os.path.exists(old_path))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('127.0.0.1:5557')
-                )
-    @mock.patch(
-        'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-        return_value=mock_android_device.MockFastbootProxy('127.0.0.1:5557'))
-    @mock.patch('mobly.utils.start_standing_subprocess',
-                return_value='process')
-    @mock.patch('mobly.utils.stop_standing_subprocess')
-    def test_AndroidDevice_with_reserved_character_in_serial_log_path(
-            self, stop_proc_mock, start_proc_mock, FastbootProxy,
-            MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='127.0.0.1:5557')
-        base_log_path = os.path.basename(ad.log_path)
-        self.assertEqual(base_log_path, 'AndroidDevice127.0.0.1-5557')
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.create_dir')
-    @mock.patch('mobly.utils.start_standing_subprocess',
-                return_value='process')
-    @mock.patch('mobly.utils.stop_standing_subprocess')
-    @mock.patch.object(logcat.Logcat, '_open_logcat_file')
-    def test_AndroidDevice_change_log_path_with_service(
-            self, open_logcat_mock, stop_proc_mock, start_proc_mock,
-            creat_dir_mock, FastbootProxy, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        ad.services.logcat.start()
-        new_log_path = tempfile.mkdtemp()
-        expected_msg = '.* Cannot change `log_path` when there is service running.'
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            ad.log_path = new_log_path
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.create_dir')
-    @mock.patch('mobly.utils.start_standing_subprocess',
-                return_value='process')
-    @mock.patch('mobly.utils.stop_standing_subprocess')
-    def test_AndroidDevice_change_log_path_with_existing_file(
-            self, stop_proc_mock, start_proc_mock, creat_dir_mock,
-            FastbootProxy, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        new_log_path = tempfile.mkdtemp()
-        new_file_path = os.path.join(new_log_path, 'file.txt')
-        with io.open(new_file_path, 'w', encoding='utf-8') as f:
-            f.write(u'hahah.')
-        expected_msg = '.* Logs already exist .*'
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            ad.log_path = new_log_path
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.create_dir')
-    @mock.patch('mobly.utils.start_standing_subprocess',
-                return_value='process')
-    @mock.patch('mobly.utils.stop_standing_subprocess')
-    def test_AndroidDevice_update_serial(self, stop_proc_mock, start_proc_mock,
-                                         creat_dir_mock, FastbootProxy,
-                                         MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        ad.update_serial('2')
-        self.assertEqual(ad.serial, '2')
-        self.assertEqual(ad.debug_tag, ad.serial)
-        self.assertEqual(ad.adb.serial, ad.serial)
-        self.assertEqual(ad.fastboot.serial, ad.serial)
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.create_dir')
-    @mock.patch('mobly.utils.start_standing_subprocess',
-                return_value='process')
-    @mock.patch('mobly.utils.stop_standing_subprocess')
-    @mock.patch.object(logcat.Logcat, '_open_logcat_file')
-    def test_AndroidDevice_update_serial_with_service_running(
-            self, open_logcat_mock, stop_proc_mock, start_proc_mock,
-            creat_dir_mock, FastbootProxy, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        ad.services.logcat.start()
-        expected_msg = '.* Cannot change device serial number when there is service running.'
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            ad.update_serial('2')
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.snippet_client.SnippetClient')
-    @mock.patch('mobly.utils.get_available_host_port')
-    def test_AndroidDevice_load_snippet(self, MockGetPort, MockSnippetClient,
-                                        MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
-        self.assertTrue(hasattr(ad, 'snippet'))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.snippet_client.SnippetClient')
-    @mock.patch('mobly.utils.get_available_host_port')
-    def test_AndroidDevice_getattr(self, MockGetPort, MockSnippetClient,
-                                   MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
-        value = {'value': 42}
-        actual_value = getattr(ad, 'some_attr', value)
-        self.assertEqual(actual_value, value)
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.snippet_client.SnippetClient',
-        return_value=MockSnippetClient)
-    @mock.patch('mobly.utils.get_available_host_port')
-    def test_AndroidDevice_load_snippet_dup_package(self, MockGetPort,
-                                                    MockSnippetClient,
-                                                    MockFastboot,
-                                                    MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
-        expected_msg = ('Snippet package "%s" has already been loaded under '
-                        'name "snippet".') % MOCK_SNIPPET_PACKAGE_NAME
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            ad.load_snippet('snippet2', MOCK_SNIPPET_PACKAGE_NAME)
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.snippet_client.SnippetClient',
-        return_value=MockSnippetClient)
-    @mock.patch('mobly.utils.get_available_host_port')
-    def test_AndroidDevice_load_snippet_dup_snippet_name(
-            self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
-        expected_msg = ('.* Attribute "snippet" already exists, please use a '
-                        'different name.')
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME + 'haha')
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.snippet_client.SnippetClient')
-    @mock.patch('mobly.utils.get_available_host_port')
-    def test_AndroidDevice_load_snippet_dup_attribute_name(
-            self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        expected_msg = ('Attribute "%s" already exists, please use a different'
-                        ' name') % 'adb'
-        with self.assertRaisesRegex(android_device.Error, expected_msg):
-            ad.load_snippet('adb', MOCK_SNIPPET_PACKAGE_NAME)
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.snippet_client.SnippetClient')
-    @mock.patch('mobly.utils.get_available_host_port')
-    def test_AndroidDevice_load_snippet_start_app_fails(
-            self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy):
-        """Verifies that the correct exception is raised if start app failed.
-
-        It's possible that the `stop_app` call as part of the start app failure
-        teardown also fails. So we want the exception from the start app
-        failure.
-        """
-        expected_e = Exception('start failed.')
-        MockSnippetClient.start_app_and_connect = mock.Mock(
-            side_effect=expected_e)
-        MockSnippetClient.stop_app = mock.Mock(
-            side_effect=Exception('stop failed.'))
-        ad = android_device.AndroidDevice(serial='1')
-        try:
-            ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
-        except Exception as e:
-            assertIs(e, expected_e)
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.snippet_client.SnippetClient')
-    @mock.patch('mobly.utils.get_available_host_port')
-    def test_AndroidDevice_unload_snippet(self, MockGetPort, MockSnippetClient,
-                                          MockFastboot, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
-        ad.unload_snippet('snippet')
-        self.assertFalse(hasattr(ad, 'snippet'))
-        with self.assertRaisesRegex(
-                android_device.SnippetError,
-                '<AndroidDevice|1> No snippet registered with name "snippet"'):
-            ad.unload_snippet('snippet')
-        # Loading the same snippet again should succeed
-        ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
-        self.assertTrue(hasattr(ad, 'snippet'))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch(
-        'mobly.controllers.android_device_lib.snippet_client.SnippetClient')
-    @mock.patch('mobly.utils.get_available_host_port')
-    @mock.patch.object(logcat.Logcat, '_open_logcat_file')
-    def test_AndroidDevice_snippet_cleanup(self, open_logcat_mock, MockGetPort,
-                                           MockSnippetClient, MockFastboot,
-                                           MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        ad.services.start_all()
-        ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
-        ad.unload_snippet('snippet')
-        self.assertFalse(hasattr(ad, 'snippet'))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    def test_AndroidDevice_debug_tag(self, MockFastboot, MockAdbProxy):
-        mock_serial = '1'
-        ad = android_device.AndroidDevice(serial=mock_serial)
-        self.assertEqual(ad.debug_tag, '1')
-        try:
-            raise android_device.DeviceError(ad, 'Something')
-        except android_device.DeviceError as e:
-            self.assertEqual('<AndroidDevice|1> Something', str(e))
-        # Verify that debug tag's setter updates the debug prefix correctly.
-        ad.debug_tag = 'Mememe'
-        try:
-            raise android_device.DeviceError(ad, 'Something')
-        except android_device.DeviceError as e:
-            self.assertEqual('<AndroidDevice|Mememe> Something', str(e))
-        # Verify that repr is changed correctly.
-        try:
-            raise Exception(ad, 'Something')
-        except Exception as e:
-            self.assertEqual("(<AndroidDevice|Mememe>, 'Something')", str(e))
-
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.start_standing_subprocess',
-                return_value='process')
-    @mock.patch('mobly.utils.stop_standing_subprocess')
-    @mock.patch.object(logcat.Logcat, '_open_logcat_file')
-    def test_AndroidDevice_handle_usb_disconnect(self, open_logcat_mock,
-                                                 stop_proc_mock,
-                                                 start_proc_mock,
-                                                 FastbootProxy, MockAdbProxy):
-        class MockService(base_service.BaseService):
-            def __init__(self, device, configs=None):
-                self._alive = False
-                self.pause_called = False
-                self.resume_called = False
-
-            @property
-            def is_alive(self):
-                return self._alive
-
-            def start(self, configs=None):
-                self._alive = True
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.logger.get_log_file_timestamp')
+  def test_AndroidDevice_generate_filename_with_runtime_info(
+      self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
+    mock_serial = 1
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
+    mock_record = mock.MagicMock(begin_time='1234567')
+    mock_test_info = runtime_test_info.RuntimeTestInfo(
+      'test_xyz', '/tmp/blah/', mock_record)
+    filename = ad.generate_filename('MagicLog',
+                    time_identifier=mock_test_info)
+    self.assertEqual(filename, 'MagicLog,1,fakemodel,test_xyz-1234567')
 
-            def stop(self):
-                self._alive = False
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.logger.get_log_file_timestamp')
+  def test_AndroidDevice_generate_filename_with_custom_timestamp(
+      self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
+    mock_serial = 1
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
+    filename = ad.generate_filename('MagicLog',
+                    time_identifier='my_special_time')
+    self.assertEqual(filename, 'MagicLog,1,fakemodel,my_special_time')
 
-            def pause(self):
-                self._alive = False
-                self.pause_called = True
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(1))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy(1))
+  @mock.patch('mobly.utils.create_dir')
+  def test_AndroidDevice_take_bug_report(self, create_dir_mock,
+                       FastbootProxy, MockAdbProxy):
+    """Verifies AndroidDevice.take_bug_report calls the correct adb command
+    and writes the bugreport file to the correct path.
+    """
+    mock_serial = '1'
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    output_path = ad.take_bug_report(test_name='test_something',
+                     begin_time='sometime')
+    expected_path = os.path.join(logging.log_path,
+                   'AndroidDevice%s' % ad.serial,
+                   'BugReports')
+    create_dir_mock.assert_called_with(expected_path)
+    self.assertEqual(
+      output_path,
+      os.path.join(expected_path,
+             'bugreport,test_something,1,fakemodel,sometime.zip'))
 
-            def resume(self):
-                self._alive = True
-                self.resume_called = True
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1',
+                                fail_br=True))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.create_dir')
+  def test_AndroidDevice_take_bug_report_fail(self, create_dir_mock,
+                        FastbootProxy, MockAdbProxy):
+    """Verifies AndroidDevice.take_bug_report writes out the correct message
+    when taking bugreport fails.
+    """
+    mock_serial = '1'
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    expected_msg = '.* Failed to take bugreport.'
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      ad.take_bug_report(test_name='test_something',
+                 begin_time='sometime')
 
-        ad = android_device.AndroidDevice(serial='1')
-        ad.services.start_all()
-        ad.services.register('mock_service', MockService)
-        with ad.handle_usb_disconnect():
-            self.assertFalse(ad.services.is_any_alive)
-            self.assertTrue(ad.services.mock_service.pause_called)
-            self.assertFalse(ad.services.mock_service.resume_called)
-        self.assertTrue(ad.services.is_any_alive)
-        self.assertTrue(ad.services.mock_service.resume_called)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.create_dir')
+  @mock.patch('mobly.logger.get_log_file_timestamp')
+  def test_AndroidDevice_take_bug_report_without_args(
+      self, get_log_file_timestamp_mock, create_dir_mock, FastbootProxy,
+      MockAdbProxy):
+    get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
+    mock_serial = '1'
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    output_path = ad.take_bug_report()
+    expected_path = os.path.join(logging.log_path,
+                   'AndroidDevice%s' % ad.serial,
+                   'BugReports')
+    self.assertEqual(
+      output_path,
+      os.path.join(expected_path,
+             'bugreport,1,fakemodel,07-22-2019_17-53-34-450.zip'))
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.start_standing_subprocess',
-                return_value='process')
-    @mock.patch('mobly.utils.stop_standing_subprocess')
-    @mock.patch.object(logcat.Logcat, '_open_logcat_file')
-    def test_AndroidDevice_handle_reboot(self, open_logcat_mock,
-                                         stop_proc_mock, start_proc_mock,
-                                         FastbootProxy, MockAdbProxy):
-        class MockService(base_service.BaseService):
-            def __init__(self, device, configs=None):
-                self._alive = False
-                self.pause_called = False
-                self.resume_called = False
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.create_dir')
+  @mock.patch('mobly.logger.get_log_file_timestamp')
+  def test_AndroidDevice_take_bug_report_with_only_test_name(
+      self, get_log_file_timestamp_mock, create_dir_mock, FastbootProxy,
+      MockAdbProxy):
+    get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
+    mock_serial = '1'
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    output_path = ad.take_bug_report(test_name='test_something')
+    expected_path = os.path.join(logging.log_path,
+                   'AndroidDevice%s' % ad.serial,
+                   'BugReports')
+    create_dir_mock.assert_called_with(expected_path)
+    self.assertEqual(
+      output_path,
+      os.path.join(
+        expected_path,
+        'bugreport,test_something,1,fakemodel,07-22-2019_17-53-34-450.zip'
+      ))
 
-            @property
-            def is_alive(self):
-                return self._alive
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(1))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy(1))
+  @mock.patch('mobly.utils.create_dir')
+  def test_AndroidDevice_take_bug_report_with_only_begin_time(
+      self, create_dir_mock, FastbootProxy, MockAdbProxy):
+    mock_serial = '1'
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    output_path = ad.take_bug_report(begin_time='sometime')
+    expected_path = os.path.join(logging.log_path,
+                   'AndroidDevice%s' % ad.serial,
+                   'BugReports')
+    create_dir_mock.assert_called_with(expected_path)
+    self.assertEqual(
+      output_path,
+      os.path.join(expected_path, 'bugreport,1,fakemodel,sometime.zip'))
 
-            def start(self, configs=None):
-                self._alive = True
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(1))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy(1))
+  @mock.patch('mobly.utils.create_dir')
+  def test_AndroidDevice_take_bug_report_with_int_begin_time(
+      self, create_dir_mock, FastbootProxy, MockAdbProxy):
+    mock_serial = '1'
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    output_path = ad.take_bug_report(begin_time=123)
+    expected_path = os.path.join(logging.log_path,
+                   'AndroidDevice%s' % ad.serial,
+                   'BugReports')
+    create_dir_mock.assert_called_with(expected_path)
+    self.assertEqual(
+      output_path,
+      os.path.join(expected_path, 'bugreport,1,fakemodel,123.zip'))
 
-            def stop(self):
-                self._alive = False
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(1))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy(1))
+  @mock.patch('mobly.utils.create_dir')
+  def test_AndroidDevice_take_bug_report_with_positional_args(
+      self, create_dir_mock, FastbootProxy, MockAdbProxy):
+    mock_serial = '1'
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    output_path = ad.take_bug_report('test_something', 'sometime')
+    expected_path = os.path.join(logging.log_path,
+                   'AndroidDevice%s' % ad.serial,
+                   'BugReports')
+    create_dir_mock.assert_called_with(expected_path)
+    self.assertEqual(
+      output_path,
+      os.path.join(expected_path,
+             'bugreport,test_something,1,fakemodel,sometime.zip'))
 
-            def pause(self):
-                self._alive = False
-                self.pause_called = True
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.create_dir')
+  def test_AndroidDevice_take_bug_report_with_destination(
+      self, create_dir_mock, FastbootProxy, MockAdbProxy):
+    mock_serial = '1'
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    dest = tempfile.gettempdir()
+    output_path = ad.take_bug_report(test_name="test_something",
+                     begin_time="sometime",
+                     destination=dest)
+    expected_path = os.path.join(dest)
+    create_dir_mock.assert_called_with(expected_path)
+    self.assertEqual(
+      output_path,
+      os.path.join(expected_path,
+             'bugreport,test_something,1,fakemodel,sometime.zip'))
 
-            def resume(self):
-                self._alive = True
-                self.resume_called = True
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(
+          '1', fail_br_before_N=True))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.create_dir')
+  def test_AndroidDevice_take_bug_report_fallback(self, create_dir_mock,
+                          FastbootProxy,
+                          MockAdbProxy):
+    """Verifies AndroidDevice.take_bug_report falls back to traditional
+    bugreport on builds that do not have bugreportz.
+    """
+    mock_serial = '1'
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    output_path = ad.take_bug_report(test_name='test_something',
+                     begin_time='sometime')
+    expected_path = os.path.join(logging.log_path,
+                   'AndroidDevice%s' % ad.serial,
+                   'BugReports')
+    create_dir_mock.assert_called_with(expected_path)
+    self.assertEqual(
+      output_path,
+      os.path.join(expected_path,
+             'bugreport,test_something,1,fakemodel,sometime.txt'))
 
-        ad = android_device.AndroidDevice(serial='1')
-        ad.services.start_all()
-        ad.services.register('mock_service', MockService)
-        with ad.handle_reboot():
-            self.assertFalse(ad.services.is_any_alive)
-            self.assertFalse(ad.services.mock_service.pause_called)
-            self.assertFalse(ad.services.mock_service.resume_called)
-        self.assertTrue(ad.services.is_any_alive)
-        self.assertFalse(ad.services.mock_service.resume_called)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.create_dir')
+  @mock.patch('mobly.logger.get_log_file_timestamp')
+  def test_AndroidDevice_take_screenshot(self, get_log_file_timestamp_mock,
+                       create_dir_mock, FastbootProxy,
+                       MockAdbProxy):
+    get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
+    mock_serial = '1'
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    full_pic_path = ad.take_screenshot(self.tmp_dir)
+    self.assertEqual(
+      full_pic_path,
+      os.path.join(self.tmp_dir,
+             'screenshot,1,fakemodel,07-22-2019_17-53-34-450.png'))
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.start_standing_subprocess',
-                return_value='process')
-    @mock.patch('mobly.utils.stop_standing_subprocess')
-    @mock.patch.object(logcat.Logcat, '_open_logcat_file')
-    def test_AndroidDevice_handle_reboot_changes_build_info(
-            self, open_logcat_mock, stop_proc_mock, start_proc_mock,
-            FastbootProxy, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        with ad.handle_reboot():
-            ad.adb.mock_properties['ro.build.type'] = 'user'
-            ad.adb.mock_properties['ro.debuggable'] = '0'
-        self.assertEqual(ad.build_info['build_type'], 'user')
-        self.assertEqual(ad.build_info['debuggable'], '0')
-        self.assertFalse(ad.is_rootable)
-        self.assertEqual(ad.adb.getprops_call_count, 2)
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.start_standing_subprocess',
+        return_value='process')
+  @mock.patch('mobly.utils.stop_standing_subprocess')
+  def test_AndroidDevice_change_log_path(self, stop_proc_mock,
+                       start_proc_mock, FastbootProxy,
+                       MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    old_path = ad.log_path
+    new_log_path = tempfile.mkdtemp()
+    ad.log_path = new_log_path
+    self.assertTrue(os.path.exists(new_log_path))
+    self.assertFalse(os.path.exists(old_path))
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch('mobly.utils.start_standing_subprocess',
-                return_value='process')
-    @mock.patch('mobly.utils.stop_standing_subprocess')
-    @mock.patch.object(logcat.Logcat, '_open_logcat_file')
-    def test_AndroidDevice_handle_reboot_changes_build_info_with_caching(
-            self, open_logcat_mock, stop_proc_mock, start_proc_mock,
-            FastbootProxy, MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')  # Call getprops 1.
-        rootable_states = [ad.is_rootable]
-        with ad.handle_reboot():
-            rootable_states.append(ad.is_rootable)  # Call getprops 2.
-            ad.adb.mock_properties['ro.debuggable'] = '0'
-            rootable_states.append(ad.is_rootable)  # Call getprops 3.
-        # Call getprops 4, on context manager end.
-        rootable_states.append(ad.is_rootable)  # Cached call.
-        rootable_states.append(ad.is_rootable)  # Cached call.
-        self.assertEqual(ad.adb.getprops_call_count, 4)
-        self.assertEqual(rootable_states, [True, True, False, False, False])
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.start_standing_subprocess',
+        return_value='process')
+  @mock.patch('mobly.utils.stop_standing_subprocess')
+  def test_AndroidDevice_change_log_path_no_log_exists(
+      self, stop_proc_mock, start_proc_mock, FastbootProxy,
+      MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    old_path = ad.log_path
+    new_log_path = tempfile.mkdtemp()
+    ad.log_path = new_log_path
+    self.assertTrue(os.path.exists(new_log_path))
+    self.assertFalse(os.path.exists(old_path))
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch(
-        'mobly.controllers.android_device.AndroidDevice.is_boot_completed',
-        side_effect=[
-            False, False,
-            adb.AdbTimeoutError(['adb', 'shell', 'getprop sys.boot_completed'],
-                                timeout=5,
-                                serial=1), True
-        ])
-    @mock.patch('time.sleep', return_value=None)
-    @mock.patch('time.time', side_effect=[0, 5, 10, 15, 20, 25, 30])
-    def test_AndroidDevice_wait_for_completion_completed(
-            self, MockTime, MockSleep, MockIsBootCompleted, FastbootProxy,
-            MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        raised = False
-        try:
-            ad.wait_for_boot_completion()
-        except (adb.AdbError, adb.AdbTimeoutError):
-            raised = True
-        self.assertFalse(
-            raised,
-            'adb.AdbError or adb.AdbTimeoutError exception raised but not handled.'
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('127.0.0.1:5557')
         )
+  @mock.patch(
+    'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+    return_value=mock_android_device.MockFastbootProxy('127.0.0.1:5557'))
+  @mock.patch('mobly.utils.start_standing_subprocess',
+        return_value='process')
+  @mock.patch('mobly.utils.stop_standing_subprocess')
+  def test_AndroidDevice_with_reserved_character_in_serial_log_path(
+      self, stop_proc_mock, start_proc_mock, FastbootProxy,
+      MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='127.0.0.1:5557')
+    base_log_path = os.path.basename(ad.log_path)
+    self.assertEqual(base_log_path, 'AndroidDevice127.0.0.1-5557')
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy('1'))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy('1'))
-    @mock.patch(
-        'mobly.controllers.android_device.AndroidDevice.is_boot_completed',
-        side_effect=[
-            False, False,
-            adb.AdbTimeoutError(['adb', 'shell', 'getprop sys.boot_completed'],
-                                timeout=5,
-                                serial=1), False, False, False, False
-        ])
-    @mock.patch('time.sleep', return_value=None)
-    @mock.patch('time.time', side_effect=[0, 5, 10, 15, 20, 25, 30])
-    def test_AndroidDevice_wait_for_completion_never_boot(
-            self, MockTime, MockSleep, MockIsBootCompleted, FastbootProxy,
-            MockAdbProxy):
-        ad = android_device.AndroidDevice(serial='1')
-        raised = False
-        try:
-            with self.assertRaises(android_device.DeviceError):
-                ad.wait_for_boot_completion(timeout=20)
-        except (adb.AdbError, adb.AdbTimeoutError):
-            raised = True
-        self.assertFalse(
-            raised,
-            'adb.AdbError or adb.AdbTimeoutError exception raised but not handled.'
-        )
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.create_dir')
+  @mock.patch('mobly.utils.start_standing_subprocess',
+        return_value='process')
+  @mock.patch('mobly.utils.stop_standing_subprocess')
+  @mock.patch.object(logcat.Logcat, '_open_logcat_file')
+  def test_AndroidDevice_change_log_path_with_service(
+      self, open_logcat_mock, stop_proc_mock, start_proc_mock,
+      creat_dir_mock, FastbootProxy, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    ad.services.logcat.start()
+    new_log_path = tempfile.mkdtemp()
+    expected_msg = '.* Cannot change `log_path` when there is service running.'
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      ad.log_path = new_log_path
 
-    def test_AndroidDevice_parse_device_list_when_decode_error(self):
-        gbk_str = b'\xc4\xe3\xba\xc3'
-        raised = False
-        try:
-            android_device.parse_device_list(gbk_str, 'some_key')
-        except UnicodeDecodeError:
-            raised = True
-        self.assertTrue(
-            raised,
-            'did not raise an exception when parsing gbk bytes'
-        )
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.create_dir')
+  @mock.patch('mobly.utils.start_standing_subprocess',
+        return_value='process')
+  @mock.patch('mobly.utils.stop_standing_subprocess')
+  def test_AndroidDevice_change_log_path_with_existing_file(
+      self, stop_proc_mock, start_proc_mock, creat_dir_mock,
+      FastbootProxy, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    new_log_path = tempfile.mkdtemp()
+    new_file_path = os.path.join(new_log_path, 'file.txt')
+    with io.open(new_file_path, 'w', encoding='utf-8') as f:
+      f.write(u'hahah.')
+    expected_msg = '.* Logs already exist .*'
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      ad.log_path = new_log_path
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.create_dir')
+  @mock.patch('mobly.utils.start_standing_subprocess',
+        return_value='process')
+  @mock.patch('mobly.utils.stop_standing_subprocess')
+  def test_AndroidDevice_update_serial(self, stop_proc_mock, start_proc_mock,
+                     creat_dir_mock, FastbootProxy,
+                     MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    ad.update_serial('2')
+    self.assertEqual(ad.serial, '2')
+    self.assertEqual(ad.debug_tag, ad.serial)
+    self.assertEqual(ad.adb.serial, ad.serial)
+    self.assertEqual(ad.fastboot.serial, ad.serial)
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.create_dir')
+  @mock.patch('mobly.utils.start_standing_subprocess',
+        return_value='process')
+  @mock.patch('mobly.utils.stop_standing_subprocess')
+  @mock.patch.object(logcat.Logcat, '_open_logcat_file')
+  def test_AndroidDevice_update_serial_with_service_running(
+      self, open_logcat_mock, stop_proc_mock, start_proc_mock,
+      creat_dir_mock, FastbootProxy, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    ad.services.logcat.start()
+    expected_msg = '.* Cannot change device serial number when there is service running.'
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      ad.update_serial('2')
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.snippet_client.SnippetClient')
+  @mock.patch('mobly.utils.get_available_host_port')
+  def test_AndroidDevice_load_snippet(self, MockGetPort, MockSnippetClient,
+                    MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
+    self.assertTrue(hasattr(ad, 'snippet'))
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.snippet_client.SnippetClient')
+  @mock.patch('mobly.utils.get_available_host_port')
+  def test_AndroidDevice_getattr(self, MockGetPort, MockSnippetClient,
+                   MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
+    value = {'value': 42}
+    actual_value = getattr(ad, 'some_attr', value)
+    self.assertEqual(actual_value, value)
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.snippet_client.SnippetClient',
+    return_value=MockSnippetClient)
+  @mock.patch('mobly.utils.get_available_host_port')
+  def test_AndroidDevice_load_snippet_dup_package(self, MockGetPort,
+                          MockSnippetClient,
+                          MockFastboot,
+                          MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
+    expected_msg = ('Snippet package "%s" has already been loaded under '
+            'name "snippet".') % MOCK_SNIPPET_PACKAGE_NAME
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      ad.load_snippet('snippet2', MOCK_SNIPPET_PACKAGE_NAME)
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.snippet_client.SnippetClient',
+    return_value=MockSnippetClient)
+  @mock.patch('mobly.utils.get_available_host_port')
+  def test_AndroidDevice_load_snippet_dup_snippet_name(
+      self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
+    expected_msg = ('.* Attribute "snippet" already exists, please use a '
+            'different name.')
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME + 'haha')
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.snippet_client.SnippetClient')
+  @mock.patch('mobly.utils.get_available_host_port')
+  def test_AndroidDevice_load_snippet_dup_attribute_name(
+      self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    expected_msg = ('Attribute "%s" already exists, please use a different'
+            ' name') % 'adb'
+    with self.assertRaisesRegex(android_device.Error, expected_msg):
+      ad.load_snippet('adb', MOCK_SNIPPET_PACKAGE_NAME)
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.snippet_client.SnippetClient')
+  @mock.patch('mobly.utils.get_available_host_port')
+  def test_AndroidDevice_load_snippet_start_app_fails(
+      self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy):
+    """Verifies that the correct exception is raised if start app failed.
+
+    It's possible that the `stop_app` call as part of the start app failure
+    teardown also fails. So we want the exception from the start app
+    failure.
+    """
+    expected_e = Exception('start failed.')
+    MockSnippetClient.start_app_and_connect = mock.Mock(
+      side_effect=expected_e)
+    MockSnippetClient.stop_app = mock.Mock(
+      side_effect=Exception('stop failed.'))
+    ad = android_device.AndroidDevice(serial='1')
+    try:
+      ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
+    except Exception as e:
+      assertIs(e, expected_e)
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.snippet_client.SnippetClient')
+  @mock.patch('mobly.utils.get_available_host_port')
+  def test_AndroidDevice_unload_snippet(self, MockGetPort, MockSnippetClient,
+                      MockFastboot, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
+    ad.unload_snippet('snippet')
+    self.assertFalse(hasattr(ad, 'snippet'))
+    with self.assertRaisesRegex(
+        android_device.SnippetError,
+        '<AndroidDevice|1> No snippet registered with name "snippet"'):
+      ad.unload_snippet('snippet')
+    # Loading the same snippet again should succeed
+    ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
+    self.assertTrue(hasattr(ad, 'snippet'))
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch(
+    'mobly.controllers.android_device_lib.snippet_client.SnippetClient')
+  @mock.patch('mobly.utils.get_available_host_port')
+  @mock.patch.object(logcat.Logcat, '_open_logcat_file')
+  def test_AndroidDevice_snippet_cleanup(self, open_logcat_mock, MockGetPort,
+                       MockSnippetClient, MockFastboot,
+                       MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    ad.services.start_all()
+    ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
+    ad.unload_snippet('snippet')
+    self.assertFalse(hasattr(ad, 'snippet'))
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  def test_AndroidDevice_debug_tag(self, MockFastboot, MockAdbProxy):
+    mock_serial = '1'
+    ad = android_device.AndroidDevice(serial=mock_serial)
+    self.assertEqual(ad.debug_tag, '1')
+    try:
+      raise android_device.DeviceError(ad, 'Something')
+    except android_device.DeviceError as e:
+      self.assertEqual('<AndroidDevice|1> Something', str(e))
+    # Verify that debug tag's setter updates the debug prefix correctly.
+    ad.debug_tag = 'Mememe'
+    try:
+      raise android_device.DeviceError(ad, 'Something')
+    except android_device.DeviceError as e:
+      self.assertEqual('<AndroidDevice|Mememe> Something', str(e))
+    # Verify that repr is changed correctly.
+    try:
+      raise Exception(ad, 'Something')
+    except Exception as e:
+      self.assertEqual("(<AndroidDevice|Mememe>, 'Something')", str(e))
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.start_standing_subprocess',
+        return_value='process')
+  @mock.patch('mobly.utils.stop_standing_subprocess')
+  @mock.patch.object(logcat.Logcat, '_open_logcat_file')
+  def test_AndroidDevice_handle_usb_disconnect(self, open_logcat_mock,
+                         stop_proc_mock,
+                         start_proc_mock,
+                         FastbootProxy, MockAdbProxy):
+    class MockService(base_service.BaseService):
+      def __init__(self, device, configs=None):
+        self._alive = False
+        self.pause_called = False
+        self.resume_called = False
+
+      @property
+      def is_alive(self):
+        return self._alive
+
+      def start(self, configs=None):
+        self._alive = True
+
+      def stop(self):
+        self._alive = False
+
+      def pause(self):
+        self._alive = False
+        self.pause_called = True
+
+      def resume(self):
+        self._alive = True
+        self.resume_called = True
+
+    ad = android_device.AndroidDevice(serial='1')
+    ad.services.start_all()
+    ad.services.register('mock_service', MockService)
+    with ad.handle_usb_disconnect():
+      self.assertFalse(ad.services.is_any_alive)
+      self.assertTrue(ad.services.mock_service.pause_called)
+      self.assertFalse(ad.services.mock_service.resume_called)
+    self.assertTrue(ad.services.is_any_alive)
+    self.assertTrue(ad.services.mock_service.resume_called)
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.start_standing_subprocess',
+        return_value='process')
+  @mock.patch('mobly.utils.stop_standing_subprocess')
+  @mock.patch.object(logcat.Logcat, '_open_logcat_file')
+  def test_AndroidDevice_handle_reboot(self, open_logcat_mock,
+                     stop_proc_mock, start_proc_mock,
+                     FastbootProxy, MockAdbProxy):
+    class MockService(base_service.BaseService):
+      def __init__(self, device, configs=None):
+        self._alive = False
+        self.pause_called = False
+        self.resume_called = False
+
+      @property
+      def is_alive(self):
+        return self._alive
+
+      def start(self, configs=None):
+        self._alive = True
+
+      def stop(self):
+        self._alive = False
+
+      def pause(self):
+        self._alive = False
+        self.pause_called = True
+
+      def resume(self):
+        self._alive = True
+        self.resume_called = True
+
+    ad = android_device.AndroidDevice(serial='1')
+    ad.services.start_all()
+    ad.services.register('mock_service', MockService)
+    with ad.handle_reboot():
+      self.assertFalse(ad.services.is_any_alive)
+      self.assertFalse(ad.services.mock_service.pause_called)
+      self.assertFalse(ad.services.mock_service.resume_called)
+    self.assertTrue(ad.services.is_any_alive)
+    self.assertFalse(ad.services.mock_service.resume_called)
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.start_standing_subprocess',
+        return_value='process')
+  @mock.patch('mobly.utils.stop_standing_subprocess')
+  @mock.patch.object(logcat.Logcat, '_open_logcat_file')
+  def test_AndroidDevice_handle_reboot_changes_build_info(
+      self, open_logcat_mock, stop_proc_mock, start_proc_mock,
+      FastbootProxy, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    with ad.handle_reboot():
+      ad.adb.mock_properties['ro.build.type'] = 'user'
+      ad.adb.mock_properties['ro.debuggable'] = '0'
+    self.assertEqual(ad.build_info['build_type'], 'user')
+    self.assertEqual(ad.build_info['debuggable'], '0')
+    self.assertFalse(ad.is_rootable)
+    self.assertEqual(ad.adb.getprops_call_count, 2)
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch('mobly.utils.start_standing_subprocess',
+        return_value='process')
+  @mock.patch('mobly.utils.stop_standing_subprocess')
+  @mock.patch.object(logcat.Logcat, '_open_logcat_file')
+  def test_AndroidDevice_handle_reboot_changes_build_info_with_caching(
+      self, open_logcat_mock, stop_proc_mock, start_proc_mock,
+      FastbootProxy, MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')  # Call getprops 1.
+    rootable_states = [ad.is_rootable]
+    with ad.handle_reboot():
+      rootable_states.append(ad.is_rootable)  # Call getprops 2.
+      ad.adb.mock_properties['ro.debuggable'] = '0'
+      rootable_states.append(ad.is_rootable)  # Call getprops 3.
+    # Call getprops 4, on context manager end.
+    rootable_states.append(ad.is_rootable)  # Cached call.
+    rootable_states.append(ad.is_rootable)  # Cached call.
+    self.assertEqual(ad.adb.getprops_call_count, 4)
+    self.assertEqual(rootable_states, [True, True, False, False, False])
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch(
+    'mobly.controllers.android_device.AndroidDevice.is_boot_completed',
+    side_effect=[
+      False, False,
+      adb.AdbTimeoutError(['adb', 'shell', 'getprop sys.boot_completed'],
+                timeout=5,
+                serial=1), True
+    ])
+  @mock.patch('time.sleep', return_value=None)
+  @mock.patch('time.time', side_effect=[0, 5, 10, 15, 20, 25, 30])
+  def test_AndroidDevice_wait_for_completion_completed(
+      self, MockTime, MockSleep, MockIsBootCompleted, FastbootProxy,
+      MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    raised = False
+    try:
+      ad.wait_for_boot_completion()
+    except (adb.AdbError, adb.AdbTimeoutError):
+      raised = True
+    self.assertFalse(
+      raised,
+      'adb.AdbError or adb.AdbTimeoutError exception raised but not handled.'
+    )
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy('1'))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy('1'))
+  @mock.patch(
+    'mobly.controllers.android_device.AndroidDevice.is_boot_completed',
+    side_effect=[
+      False, False,
+      adb.AdbTimeoutError(['adb', 'shell', 'getprop sys.boot_completed'],
+                timeout=5,
+                serial=1), False, False, False, False
+    ])
+  @mock.patch('time.sleep', return_value=None)
+  @mock.patch('time.time', side_effect=[0, 5, 10, 15, 20, 25, 30])
+  def test_AndroidDevice_wait_for_completion_never_boot(
+      self, MockTime, MockSleep, MockIsBootCompleted, FastbootProxy,
+      MockAdbProxy):
+    ad = android_device.AndroidDevice(serial='1')
+    raised = False
+    try:
+      with self.assertRaises(android_device.DeviceError):
+        ad.wait_for_boot_completion(timeout=20)
+    except (adb.AdbError, adb.AdbTimeoutError):
+      raised = True
+    self.assertFalse(
+      raised,
+      'adb.AdbError or adb.AdbTimeoutError exception raised but not handled.'
+    )
+
+  def test_AndroidDevice_parse_device_list_when_decode_error(self):
+    gbk_str = b'\xc4\xe3\xba\xc3'
+    raised = False
+    try:
+      android_device.parse_device_list(gbk_str, 'some_key')
+    except UnicodeDecodeError:
+      raised = True
+    self.assertTrue(
+      raised,
+      'did not raise an exception when parsing gbk bytes'
+    )
 
 
 if __name__ == '__main__':
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/controllers/monsoon_test.py b/tests/mobly/controllers/monsoon_test.py
index c8b6eeb..dd7c249 100755
--- a/tests/mobly/controllers/monsoon_test.py
+++ b/tests/mobly/controllers/monsoon_test.py
@@ -18,12 +18,12 @@
 
 
 class MonsoonTest(unittest.TestCase):
-    @unittest.skipIf(platform.system() == 'Windows',
-                     'fcntl does not exist on Windows')
-    def test_monsoon_import(self):
-        # TODO: Replace 'fnctl' with a Windows equivalent when on Windows
-        from mobly.controllers import monsoon
+  @unittest.skipIf(platform.system() == 'Windows',
+           'fcntl does not exist on Windows')
+  def test_monsoon_import(self):
+    # TODO: Replace 'fnctl' with a Windows equivalent when on Windows
+    from mobly.controllers import monsoon
 
 
 if __name__ == '__main__':
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/logger_test.py b/tests/mobly/logger_test.py
index 2112656..9bedc0b 100755
--- a/tests/mobly/logger_test.py
+++ b/tests/mobly/logger_test.py
@@ -23,204 +23,204 @@
 
 
 class LoggerTest(unittest.TestCase):
-    """Verifies code in mobly.logger module.
-    """
-    def setUp(self):
-        self.log_dir = tempfile.mkdtemp()
+  """Verifies code in mobly.logger module.
+  """
+  def setUp(self):
+    self.log_dir = tempfile.mkdtemp()
 
-    def tearDown(self):
-        shutil.rmtree(self.log_dir)
+  def tearDown(self):
+    shutil.rmtree(self.log_dir)
 
-    def test_epoch_to_log_line_timestamp(self):
-        actual_stamp = logger.epoch_to_log_line_timestamp(1469134262116,
-                                                          time_zone=pytz.utc)
-        self.assertEqual("07-21 20:51:02.116", actual_stamp)
+  def test_epoch_to_log_line_timestamp(self):
+    actual_stamp = logger.epoch_to_log_line_timestamp(1469134262116,
+                              time_zone=pytz.utc)
+    self.assertEqual("07-21 20:51:02.116", actual_stamp)
 
-    def test_is_valid_logline_timestamp(self):
-        self.assertTrue(
-            logger.is_valid_logline_timestamp("06-21 17:44:42.336"))
+  def test_is_valid_logline_timestamp(self):
+    self.assertTrue(
+      logger.is_valid_logline_timestamp("06-21 17:44:42.336"))
 
-    def test_is_valid_logline_timestamp_when_wrong_length(self):
-        self.assertFalse(
-            logger.is_valid_logline_timestamp("  06-21 17:44:42.336"))
+  def test_is_valid_logline_timestamp_when_wrong_length(self):
+    self.assertFalse(
+      logger.is_valid_logline_timestamp("  06-21 17:44:42.336"))
 
-    def test_is_valid_logline_timestamp_when_invalid_content(self):
-        self.assertFalse(
-            logger.is_valid_logline_timestamp("------------------"))
+  def test_is_valid_logline_timestamp_when_invalid_content(self):
+    self.assertFalse(
+      logger.is_valid_logline_timestamp("------------------"))
 
-    @mock.patch('mobly.utils.create_alias')
-    def test_create_latest_log_alias(self, mock_create_alias):
-        logger.create_latest_log_alias('fake_path', alias='latest')
-        mock_create_alias.assert_called_once_with('fake_path', 'latest')
+  @mock.patch('mobly.utils.create_alias')
+  def test_create_latest_log_alias(self, mock_create_alias):
+    logger.create_latest_log_alias('fake_path', alias='latest')
+    mock_create_alias.assert_called_once_with('fake_path', 'latest')
 
-    @mock.patch('mobly.logger._setup_test_logger')
-    @mock.patch('mobly.logger.create_latest_log_alias')
-    def test_setup_test_logger_creates_log_alias(self,
-                                                 mock_create_latest_log_alias,
-                                                 mock__setup_test_logger):
-        logger.setup_test_logger(self.log_dir)
-        mock__setup_test_logger.assert_called_once_with(self.log_dir, None)
-        mock_create_latest_log_alias.assert_called_once_with(self.log_dir,
-                                                             alias='latest')
+  @mock.patch('mobly.logger._setup_test_logger')
+  @mock.patch('mobly.logger.create_latest_log_alias')
+  def test_setup_test_logger_creates_log_alias(self,
+                         mock_create_latest_log_alias,
+                         mock__setup_test_logger):
+    logger.setup_test_logger(self.log_dir)
+    mock__setup_test_logger.assert_called_once_with(self.log_dir, None)
+    mock_create_latest_log_alias.assert_called_once_with(self.log_dir,
+                               alias='latest')
 
-    @mock.patch('mobly.logger._setup_test_logger')
-    @mock.patch('mobly.logger.create_latest_log_alias')
-    def test_setup_test_logger_creates_log_alias_with_custom_value(
-            self, mock_create_latest_log_alias, mock__setup_test_logger):
-        mock_alias = mock.MagicMock()
-        logger.setup_test_logger(self.log_dir, alias=mock_alias)
+  @mock.patch('mobly.logger._setup_test_logger')
+  @mock.patch('mobly.logger.create_latest_log_alias')
+  def test_setup_test_logger_creates_log_alias_with_custom_value(
+      self, mock_create_latest_log_alias, mock__setup_test_logger):
+    mock_alias = mock.MagicMock()
+    logger.setup_test_logger(self.log_dir, alias=mock_alias)
 
-        mock_create_latest_log_alias.assert_called_once_with(self.log_dir,
-                                                             alias=mock_alias)
+    mock_create_latest_log_alias.assert_called_once_with(self.log_dir,
+                               alias=mock_alias)
 
-    def test_sanitize_filename_when_valid(self):
-        fake_filename = 'logcat.txt'
-        expected_filename = 'logcat.txt'
-        self.assertEqual(logger.sanitize_filename(fake_filename),
-                         expected_filename)
+  def test_sanitize_filename_when_valid(self):
+    fake_filename = 'logcat.txt'
+    expected_filename = 'logcat.txt'
+    self.assertEqual(logger.sanitize_filename(fake_filename),
+             expected_filename)
 
-    def test_sanitize_filename_when_valid_with_path(self):
-        fake_filename = os.path.join('dir', 'logs', 'logcat.txt')
-        expected_filename = os.path.join('dir', 'logs', 'logcat.txt')
-        self.assertEqual(logger.sanitize_filename(fake_filename),
-                         expected_filename)
+  def test_sanitize_filename_when_valid_with_path(self):
+    fake_filename = os.path.join('dir', 'logs', 'logcat.txt')
+    expected_filename = os.path.join('dir', 'logs', 'logcat.txt')
+    self.assertEqual(logger.sanitize_filename(fake_filename),
+             expected_filename)
 
-    def test_sanitize_filename_when_random_spaces(self):
-        fake_filename = 'log cat file.txt'
-        expected_filename = 'log_cat_file.txt'
-        self.assertEqual(logger.sanitize_filename(fake_filename),
-                         expected_filename)
+  def test_sanitize_filename_when_random_spaces(self):
+    fake_filename = 'log cat file.txt'
+    expected_filename = 'log_cat_file.txt'
+    self.assertEqual(logger.sanitize_filename(fake_filename),
+             expected_filename)
 
-    def test_sanitize_filename_when_over_max_characters(self):
-        fake_filename = 'l' * 300
-        expected_filename = 'l' * 237
-        self.assertEqual(len(logger.sanitize_filename(fake_filename)), 237)
-        self.assertEqual(logger.sanitize_filename(fake_filename),
-                         expected_filename)
+  def test_sanitize_filename_when_over_max_characters(self):
+    fake_filename = 'l' * 300
+    expected_filename = 'l' * 237
+    self.assertEqual(len(logger.sanitize_filename(fake_filename)), 237)
+    self.assertEqual(logger.sanitize_filename(fake_filename),
+             expected_filename)
 
-    def test_sanitize_filename_when_over_max_characters_with_extension(self):
-        fake_filename = 'l' * 300 + '.txt'
-        expected_filename = 'l' * 233 + '.txt'
-        self.assertEqual(len(logger.sanitize_filename(fake_filename)), 237)
-        self.assertEqual(logger.sanitize_filename(fake_filename),
-                         expected_filename)
+  def test_sanitize_filename_when_over_max_characters_with_extension(self):
+    fake_filename = 'l' * 300 + '.txt'
+    expected_filename = 'l' * 233 + '.txt'
+    self.assertEqual(len(logger.sanitize_filename(fake_filename)), 237)
+    self.assertEqual(logger.sanitize_filename(fake_filename),
+             expected_filename)
 
-    def test_sanitize_filename_when_extension_at_max_characters(self):
-        fake_filename = 'l' * 300 + '.' + 't' * 236
-        expected_filename = '.' + 't' * 236
-        self.assertEqual(len(logger.sanitize_filename(fake_filename)), 237)
-        self.assertEqual(logger.sanitize_filename(fake_filename),
-                         expected_filename)
+  def test_sanitize_filename_when_extension_at_max_characters(self):
+    fake_filename = 'l' * 300 + '.' + 't' * 236
+    expected_filename = '.' + 't' * 236
+    self.assertEqual(len(logger.sanitize_filename(fake_filename)), 237)
+    self.assertEqual(logger.sanitize_filename(fake_filename),
+             expected_filename)
 
-    def test_sanitize_filename_when_extension_over_max_characters(self):
-        fake_filename = 'l' * 300 + '.' + 't' * 300
-        expected_filename = 'l' * 237
-        self.assertEqual(len(logger.sanitize_filename(fake_filename)), 237)
-        self.assertEqual(logger.sanitize_filename(fake_filename),
-                         expected_filename)
+  def test_sanitize_filename_when_extension_over_max_characters(self):
+    fake_filename = 'l' * 300 + '.' + 't' * 300
+    expected_filename = 'l' * 237
+    self.assertEqual(len(logger.sanitize_filename(fake_filename)), 237)
+    self.assertEqual(logger.sanitize_filename(fake_filename),
+             expected_filename)
 
-    def test__sanitize_windows_filename_when_path_characters(self):
-        fake_filename = '/\\'
-        expected_filename = '__'
-        self.assertEqual(logger._sanitize_windows_filename(fake_filename),
-                         expected_filename)
+  def test__sanitize_windows_filename_when_path_characters(self):
+    fake_filename = '/\\'
+    expected_filename = '__'
+    self.assertEqual(logger._sanitize_windows_filename(fake_filename),
+             expected_filename)
 
-    def test_sanitize_filename_when_specical_characters(self):
-        fake_filename = '<>:"|?*\x00'
-        expected_filename = '---_,,,0'
-        self.assertEqual(logger.sanitize_filename(fake_filename),
-                         expected_filename)
+  def test_sanitize_filename_when_specical_characters(self):
+    fake_filename = '<>:"|?*\x00'
+    expected_filename = '---_,,,0'
+    self.assertEqual(logger.sanitize_filename(fake_filename),
+             expected_filename)
 
-    def test_sanitize_filename_when_con(self):
-        for fake_filename, expected_filename in [
-            ('con', 'mobly_con'),
-            ('CON', 'mobly_CON'),
-            ('con.txt', 'mobly_con.txt'),
-            ('connections.log', 'connections.log'),
-        ]:
-            self.assertEqual(logger.sanitize_filename(fake_filename),
-                             expected_filename)
+  def test_sanitize_filename_when_con(self):
+    for fake_filename, expected_filename in [
+      ('con', 'mobly_con'),
+      ('CON', 'mobly_CON'),
+      ('con.txt', 'mobly_con.txt'),
+      ('connections.log', 'connections.log'),
+    ]:
+      self.assertEqual(logger.sanitize_filename(fake_filename),
+               expected_filename)
 
-    def test_sanitize_filename_when_prn(self):
-        for fake_filename, expected_filename in [
-            ('prn', 'mobly_prn'),
-            ('PRN', 'mobly_PRN'),
-            ('prn.txt', 'mobly_prn.txt'),
-            ('prnters.log', 'prnters.log'),
-        ]:
-            self.assertEqual(logger.sanitize_filename(fake_filename),
-                             expected_filename)
+  def test_sanitize_filename_when_prn(self):
+    for fake_filename, expected_filename in [
+      ('prn', 'mobly_prn'),
+      ('PRN', 'mobly_PRN'),
+      ('prn.txt', 'mobly_prn.txt'),
+      ('prnters.log', 'prnters.log'),
+    ]:
+      self.assertEqual(logger.sanitize_filename(fake_filename),
+               expected_filename)
 
-    def test_sanitize_filename_when_aux(self):
-        for fake_filename, expected_filename in [
-            ('aux', 'mobly_aux'),
-            ('AUX', 'mobly_AUX'),
-            ('aux.txt', 'mobly_aux.txt'),
-            ('auxiliaries.log', 'auxiliaries.log'),
-        ]:
-            self.assertEqual(logger.sanitize_filename(fake_filename),
-                             expected_filename)
+  def test_sanitize_filename_when_aux(self):
+    for fake_filename, expected_filename in [
+      ('aux', 'mobly_aux'),
+      ('AUX', 'mobly_AUX'),
+      ('aux.txt', 'mobly_aux.txt'),
+      ('auxiliaries.log', 'auxiliaries.log'),
+    ]:
+      self.assertEqual(logger.sanitize_filename(fake_filename),
+               expected_filename)
 
-    def test_sanitize_filename_when_nul(self):
-        for fake_filename, expected_filename in [
-            ('nul', 'mobly_nul'),
-            ('NUL', 'mobly_NUL'),
-            ('nul.txt', 'mobly_nul.txt'),
-            ('nullptrs.log', 'nullptrs.log'),
-        ]:
-            self.assertEqual(logger.sanitize_filename(fake_filename),
-                             expected_filename)
+  def test_sanitize_filename_when_nul(self):
+    for fake_filename, expected_filename in [
+      ('nul', 'mobly_nul'),
+      ('NUL', 'mobly_NUL'),
+      ('nul.txt', 'mobly_nul.txt'),
+      ('nullptrs.log', 'nullptrs.log'),
+    ]:
+      self.assertEqual(logger.sanitize_filename(fake_filename),
+               expected_filename)
 
-    def test_sanitize_filename_when_com(self):
-        for fake_filename, expected_filename in [
-            ('com', 'com'),
-            ('COM0', 'mobly_COM0'),
-            ('com1', 'mobly_com1'),
-            ('COM2', 'mobly_COM2'),
-            ('com3', 'mobly_com3'),
-            ('COM4', 'mobly_COM4'),
-            ('com5', 'mobly_com5'),
-            ('COM6', 'mobly_COM6'),
-            ('com7', 'mobly_com7'),
-            ('COM8', 'mobly_COM8'),
-            ('com9', 'mobly_com9'),
-            ('com0.log', 'mobly_com0.log'),
-            ('com0files.log', 'com0files.log'),
-        ]:
-            self.assertEqual(logger.sanitize_filename(fake_filename),
-                             expected_filename)
+  def test_sanitize_filename_when_com(self):
+    for fake_filename, expected_filename in [
+      ('com', 'com'),
+      ('COM0', 'mobly_COM0'),
+      ('com1', 'mobly_com1'),
+      ('COM2', 'mobly_COM2'),
+      ('com3', 'mobly_com3'),
+      ('COM4', 'mobly_COM4'),
+      ('com5', 'mobly_com5'),
+      ('COM6', 'mobly_COM6'),
+      ('com7', 'mobly_com7'),
+      ('COM8', 'mobly_COM8'),
+      ('com9', 'mobly_com9'),
+      ('com0.log', 'mobly_com0.log'),
+      ('com0files.log', 'com0files.log'),
+    ]:
+      self.assertEqual(logger.sanitize_filename(fake_filename),
+               expected_filename)
 
-    def test_sanitize_filename_when_lpt(self):
-        for fake_filename, expected_filename in [
-            ('lpt', 'lpt'),
-            ('LPT0', 'mobly_LPT0'),
-            ('lpt1', 'mobly_lpt1'),
-            ('LPT2', 'mobly_LPT2'),
-            ('lpt3', 'mobly_lpt3'),
-            ('LPT4', 'mobly_LPT4'),
-            ('lpt5', 'mobly_lpt5'),
-            ('LPT6', 'mobly_LPT6'),
-            ('lpt7', 'mobly_lpt7'),
-            ('LPT8', 'mobly_LPT8'),
-            ('lpt9', 'mobly_lpt9'),
-            ('lpt3.txt', 'mobly_lpt3.txt'),
-            ('lpt3_file.txt', 'lpt3_file.txt'),
-        ]:
-            self.assertEqual(logger.sanitize_filename(fake_filename),
-                             expected_filename)
+  def test_sanitize_filename_when_lpt(self):
+    for fake_filename, expected_filename in [
+      ('lpt', 'lpt'),
+      ('LPT0', 'mobly_LPT0'),
+      ('lpt1', 'mobly_lpt1'),
+      ('LPT2', 'mobly_LPT2'),
+      ('lpt3', 'mobly_lpt3'),
+      ('LPT4', 'mobly_LPT4'),
+      ('lpt5', 'mobly_lpt5'),
+      ('LPT6', 'mobly_LPT6'),
+      ('lpt7', 'mobly_lpt7'),
+      ('LPT8', 'mobly_LPT8'),
+      ('lpt9', 'mobly_lpt9'),
+      ('lpt3.txt', 'mobly_lpt3.txt'),
+      ('lpt3_file.txt', 'lpt3_file.txt'),
+    ]:
+      self.assertEqual(logger.sanitize_filename(fake_filename),
+               expected_filename)
 
-    def test_sanitize_filename_when_ends_with_space(self):
-        fake_filename = 'logcat.txt '
-        expected_filename = 'logcat.txt_'
-        self.assertEqual(logger.sanitize_filename(fake_filename),
-                         expected_filename)
+  def test_sanitize_filename_when_ends_with_space(self):
+    fake_filename = 'logcat.txt '
+    expected_filename = 'logcat.txt_'
+    self.assertEqual(logger.sanitize_filename(fake_filename),
+             expected_filename)
 
-    def test_sanitize_filename_when_ends_with_period(self):
-        fake_filename = 'logcat.txt.'
-        expected_filename = 'logcat.txt_'
-        self.assertEqual(logger.sanitize_filename(fake_filename),
-                         expected_filename)
+  def test_sanitize_filename_when_ends_with_period(self):
+    fake_filename = 'logcat.txt.'
+    expected_filename = 'logcat.txt_'
+    self.assertEqual(logger.sanitize_filename(fake_filename),
+             expected_filename)
 
 
 if __name__ == "__main__":
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/output_test.py b/tests/mobly/output_test.py
index 6a8facb..676d7fc 100755
--- a/tests/mobly/output_test.py
+++ b/tests/mobly/output_test.py
@@ -32,300 +32,300 @@
 from tests.lib import teardown_class_failure_test
 
 if platform.system() == 'Windows':
-    import win32file
-    from win32com import client
+  import win32file
+  from win32com import client
 
 
 class OutputTest(unittest.TestCase):
-    """This test class has unit tests for the implementation of Mobly's output
-    files.
+  """This test class has unit tests for the implementation of Mobly's output
+  files.
+  """
+
+  def setUp(self):
+    self.tmp_dir = tempfile.mkdtemp()
+    self.base_mock_test_config = config_parser.TestRunConfig()
+    self.base_mock_test_config.testbed_name = 'SampleTestBed'
+    self.base_mock_test_config.controller_configs = {}
+    self.base_mock_test_config.user_params = {
+      'icecream': 42,
+      'extra_param': 'haha'
+    }
+    self.base_mock_test_config.log_path = self.tmp_dir
+    self.log_dir = self.base_mock_test_config.log_path
+    self.testbed_name = self.base_mock_test_config.testbed_name
+
+  def tearDown(self):
+    shutil.rmtree(self.tmp_dir)
+
+  def create_mock_test_config(self, base_mock_test_config):
+    mock_test_config = base_mock_test_config.copy()
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    my_config = [{
+      'serial': 'xxxx',
+      'magic': 'Magic1'
+    }, {
+      'serial': 'xxxx',
+      'magic': 'Magic2'
+    }]
+    mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
+    return mock_test_config
+
+  def get_output_logs(self, output_dir):
+    summary_file_path = os.path.join(output_dir,
+                     records.OUTPUT_FILE_SUMMARY)
+    debug_log_path = os.path.join(output_dir,
+                    records.OUTPUT_FILE_DEBUG_LOG)
+    info_log_path = os.path.join(output_dir, records.OUTPUT_FILE_INFO_LOG)
+    return (summary_file_path, debug_log_path, info_log_path)
+
+  def assert_output_logs_exist(self, output_dir):
+    (summary_file_path, debug_log_path,
+     info_log_path) = self.get_output_logs(output_dir)
+    self.assertTrue(os.path.isfile(summary_file_path))
+    self.assertTrue(os.path.isfile(debug_log_path))
+    self.assertTrue(os.path.isfile(info_log_path))
+    return (summary_file_path, debug_log_path, info_log_path)
+
+  def assert_log_contents(self, log_path, whitelist=[], blacklist=[]):
+    with io.open(log_path, 'r', encoding='utf-8') as f:
+      content = f.read()
+      for item in whitelist:
+        self.assertIn(item, content)
+      for item in blacklist:
+        self.assertNotIn(item, content)
+
+  def test_yields_logging_path(self):
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger() as log_path:
+      self.assertEqual(log_path, logging.log_path)
+
+  @unittest.skipIf(platform.system() == 'Windows',
+           'Symlinks are usually specific to Unix operating systems')
+  def test_symlink(self):
+    """Verifies the symlink is created and links properly."""
+    mock_test_config = self.create_mock_test_config(
+      self.base_mock_test_config)
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger():
+      pass
+    symlink = os.path.join(self.log_dir, self.testbed_name, 'latest')
+    self.assertEqual(os.readlink(symlink), logging.log_path)
+
+  @unittest.skipIf(platform.system() != 'Windows',
+           'Shortcuts are specific to Windows operating systems')
+  def test_shortcut(self):
+    """Verifies the shortcut is created and links properly."""
+    shortcut_path = os.path.join(self.log_dir, self.testbed_name,
+                   'latest.lnk')
+    shell = client.Dispatch("WScript.Shell")
+    shortcut = shell.CreateShortCut(shortcut_path)
+    self.assertFalse(shortcut.Targetpath)
+    mock_test_config = self.create_mock_test_config(
+      self.base_mock_test_config)
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger():
+      pass
+    shortcut = shell.CreateShortCut(shortcut_path)
+    # Normalize paths for case and truncation
+    normalized_shortcut_path = os.path.normcase(
+      win32file.GetLongPathName(shortcut.Targetpath))
+    normalized_logger_path = os.path.normcase(
+      win32file.GetLongPathName(logging.log_path))
+    self.assertEqual(normalized_shortcut_path, normalized_logger_path)
+
+  @mock.patch('mobly.utils.create_alias')
+  def test_mobly_logger_with_default_latest_log_alias(
+      self, mock_create_alias):
+    mock_test_config = self.create_mock_test_config(
+      self.base_mock_test_config)
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger():
+      pass
+    expected_alias_dir = os.path.join(self.log_dir, self.testbed_name,
+                      'latest')
+    mock_create_alias.assert_called_once_with(logging.log_path,
+                          expected_alias_dir)
+
+  @mock.patch('mobly.utils.create_alias')
+  def test_mobly_logger_with_custom_latest_log_alias(self,
+                             mock_create_alias):
+    mock_test_config = self.create_mock_test_config(
+      self.base_mock_test_config)
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger(alias='history'):
+      pass
+    expected_alias_dir = os.path.join(self.log_dir, self.testbed_name,
+                      'history')
+    mock_create_alias.assert_called_once_with(logging.log_path,
+                          expected_alias_dir)
+
+  @mock.patch('mobly.utils.create_alias')
+  def test_mobly_logger_skips_latest_log_alias_when_none(
+      self, mock_create_alias):
+    mock_test_config = self.create_mock_test_config(
+      self.base_mock_test_config)
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger(alias=None):
+      pass
+    mock_create_alias.asset_not_called()
+
+  @mock.patch('mobly.utils.create_alias')
+  def test_mobly_logger_skips_latest_log_alias_when_empty(
+      self, mock_create_alias):
+    mock_test_config = self.create_mock_test_config(
+      self.base_mock_test_config)
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger(alias=''):
+      pass
+    mock_create_alias.asset_not_called()
+
+  def test_logging_before_run(self):
+    """Verifies the expected output files from a test run.
+
+    * Files are correctly created.
+    * Basic sanity checks of each output file.
     """
+    mock_test_config = self.create_mock_test_config(
+      self.base_mock_test_config)
+    info_uuid = 'e098d4ff-4e90-4e08-b369-aa84a7ef90ec'
+    debug_uuid = 'c6f1474e-960a-4df8-8305-1c5b8b905eca'
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger():
+      logging.info(info_uuid)
+      logging.debug(debug_uuid)
+      tr.add_test_class(mock_test_config,
+                integration_test.IntegrationTest)
+      tr.run()
+    output_dir = logging.root_output_path
+    (summary_file_path, debug_log_path,
+     info_log_path) = self.assert_output_logs_exist(output_dir)
+    self.assert_log_contents(debug_log_path,
+                 whitelist=[debug_uuid, info_uuid])
+    self.assert_log_contents(info_log_path,
+                 whitelist=[info_uuid],
+                 blacklist=[debug_uuid])
 
-    def setUp(self):
-        self.tmp_dir = tempfile.mkdtemp()
-        self.base_mock_test_config = config_parser.TestRunConfig()
-        self.base_mock_test_config.testbed_name = 'SampleTestBed'
-        self.base_mock_test_config.controller_configs = {}
-        self.base_mock_test_config.user_params = {
-            'icecream': 42,
-            'extra_param': 'haha'
-        }
-        self.base_mock_test_config.log_path = self.tmp_dir
-        self.log_dir = self.base_mock_test_config.log_path
-        self.testbed_name = self.base_mock_test_config.testbed_name
+  @mock.patch('mobly.logger.get_log_file_timestamp',
+        side_effect=str(time.time()))
+  def test_run_twice_for_two_sets_of_logs(self, mock_timestamp):
+    """Verifies the expected output files from a test run.
 
-    def tearDown(self):
-        shutil.rmtree(self.tmp_dir)
+    * Files are correctly created.
+    * Basic sanity checks of each output file.
+    """
+    mock_test_config = self.create_mock_test_config(
+      self.base_mock_test_config)
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    tr.add_test_class(mock_test_config, integration_test.IntegrationTest)
+    with tr.mobly_logger():
+      tr.run()
+    output_dir1 = logging.root_output_path
+    with tr.mobly_logger():
+      tr.run()
+    output_dir2 = logging.root_output_path
+    self.assertNotEqual(output_dir1, output_dir2)
+    self.assert_output_logs_exist(output_dir1)
+    self.assert_output_logs_exist(output_dir2)
 
-    def create_mock_test_config(self, base_mock_test_config):
-        mock_test_config = base_mock_test_config.copy()
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        my_config = [{
-            'serial': 'xxxx',
-            'magic': 'Magic1'
-        }, {
-            'serial': 'xxxx',
-            'magic': 'Magic2'
-        }]
-        mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
-        return mock_test_config
+  @mock.patch('mobly.logger.get_log_file_timestamp',
+        side_effect=str(time.time()))
+  def test_teardown_erases_logs(self, mock_timestamp):
+    """Verifies the expected output files from a test run.
 
-    def get_output_logs(self, output_dir):
-        summary_file_path = os.path.join(output_dir,
-                                         records.OUTPUT_FILE_SUMMARY)
-        debug_log_path = os.path.join(output_dir,
-                                      records.OUTPUT_FILE_DEBUG_LOG)
-        info_log_path = os.path.join(output_dir, records.OUTPUT_FILE_INFO_LOG)
-        return (summary_file_path, debug_log_path, info_log_path)
+    * Files are correctly created.
+    * Basic sanity checks of each output file.
+    """
+    mock_test_config = self.create_mock_test_config(
+      self.base_mock_test_config)
+    info_uuid1 = '0c3ebb06-700d-496e-b015-62652da9e451'
+    debug_uuid1 = '0c3ebb06-700d-496e-b015-62652da9e451'
+    info_uuid2 = '484ef7db-f2dd-4b76-a126-c2f263e3808c'
+    debug_uuid2 = 'd564da87-c42f-49c3-b0bf-18fa97cf0218'
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
 
-    def assert_output_logs_exist(self, output_dir):
-        (summary_file_path, debug_log_path,
-         info_log_path) = self.get_output_logs(output_dir)
-        self.assertTrue(os.path.isfile(summary_file_path))
-        self.assertTrue(os.path.isfile(debug_log_path))
-        self.assertTrue(os.path.isfile(info_log_path))
-        return (summary_file_path, debug_log_path, info_log_path)
+    with tr.mobly_logger():
+      logging.info(info_uuid1)
+      logging.debug(debug_uuid1)
+    output_dir1 = logging.log_path
 
-    def assert_log_contents(self, log_path, whitelist=[], blacklist=[]):
-        with io.open(log_path, 'r', encoding='utf-8') as f:
-            content = f.read()
-            for item in whitelist:
-                self.assertIn(item, content)
-            for item in blacklist:
-                self.assertNotIn(item, content)
+    with tr.mobly_logger():
+      logging.info(info_uuid2)
+      logging.debug(debug_uuid2)
+    output_dir2 = logging.log_path
 
-    def test_yields_logging_path(self):
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger() as log_path:
-            self.assertEqual(log_path, logging.log_path)
+    self.assertNotEqual(output_dir1, output_dir2)
 
-    @unittest.skipIf(platform.system() == 'Windows',
-                     'Symlinks are usually specific to Unix operating systems')
-    def test_symlink(self):
-        """Verifies the symlink is created and links properly."""
-        mock_test_config = self.create_mock_test_config(
-            self.base_mock_test_config)
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger():
-            pass
-        symlink = os.path.join(self.log_dir, self.testbed_name, 'latest')
-        self.assertEqual(os.readlink(symlink), logging.log_path)
+    (summary_file_path1, debug_log_path1,
+     info_log_path1) = self.get_output_logs(output_dir1)
+    (summary_file_path2, debug_log_path2,
+     info_log_path2) = self.get_output_logs(output_dir2)
 
-    @unittest.skipIf(platform.system() != 'Windows',
-                     'Shortcuts are specific to Windows operating systems')
-    def test_shortcut(self):
-        """Verifies the shortcut is created and links properly."""
-        shortcut_path = os.path.join(self.log_dir, self.testbed_name,
-                                     'latest.lnk')
-        shell = client.Dispatch("WScript.Shell")
-        shortcut = shell.CreateShortCut(shortcut_path)
-        self.assertFalse(shortcut.Targetpath)
-        mock_test_config = self.create_mock_test_config(
-            self.base_mock_test_config)
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger():
-            pass
-        shortcut = shell.CreateShortCut(shortcut_path)
-        # Normalize paths for case and truncation
-        normalized_shortcut_path = os.path.normcase(
-            win32file.GetLongPathName(shortcut.Targetpath))
-        normalized_logger_path = os.path.normcase(
-            win32file.GetLongPathName(logging.log_path))
-        self.assertEqual(normalized_shortcut_path, normalized_logger_path)
+    self.assert_log_contents(debug_log_path1,
+                 whitelist=[debug_uuid1, info_uuid1],
+                 blacklist=[info_uuid2, debug_uuid2])
+    self.assert_log_contents(debug_log_path2,
+                 whitelist=[debug_uuid2, info_uuid2],
+                 blacklist=[info_uuid1, debug_uuid1])
 
-    @mock.patch('mobly.utils.create_alias')
-    def test_mobly_logger_with_default_latest_log_alias(
-            self, mock_create_alias):
-        mock_test_config = self.create_mock_test_config(
-            self.base_mock_test_config)
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger():
-            pass
-        expected_alias_dir = os.path.join(self.log_dir, self.testbed_name,
-                                          'latest')
-        mock_create_alias.assert_called_once_with(logging.log_path,
-                                                  expected_alias_dir)
+  def test_basic_output(self):
+    """Verifies the expected output files from a test run.
 
-    @mock.patch('mobly.utils.create_alias')
-    def test_mobly_logger_with_custom_latest_log_alias(self,
-                                                       mock_create_alias):
-        mock_test_config = self.create_mock_test_config(
-            self.base_mock_test_config)
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger(alias='history'):
-            pass
-        expected_alias_dir = os.path.join(self.log_dir, self.testbed_name,
-                                          'history')
-        mock_create_alias.assert_called_once_with(logging.log_path,
-                                                  expected_alias_dir)
+    * Files are correctly created.
+    * Basic sanity checks of each output file.
+    """
+    mock_test_config = self.create_mock_test_config(
+      self.base_mock_test_config)
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger():
+      tr.add_test_class(mock_test_config,
+                integration_test.IntegrationTest)
+      tr.run()
+    expected_class_path = os.path.join(logging.root_output_path,
+                       'IntegrationTest')
+    self.assertEqual(expected_class_path, logging.log_path)
+    os.path.exists(logging.log_path)
+    output_dir = logging.root_output_path
+    (summary_file_path, debug_log_path,
+     info_log_path) = self.assert_output_logs_exist(output_dir)
+    summary_entries = []
+    with io.open(summary_file_path, 'r', encoding='utf-8') as f:
+      for entry in yaml.safe_load_all(f):
+        self.assertTrue(entry['Type'])
+        summary_entries.append(entry)
+    self.assert_log_contents(debug_log_path, whitelist=['DEBUG', 'INFO'])
+    self.assert_log_contents(info_log_path,
+                 whitelist=['INFO'],
+                 blacklist=['DEBUG'])
 
-    @mock.patch('mobly.utils.create_alias')
-    def test_mobly_logger_skips_latest_log_alias_when_none(
-            self, mock_create_alias):
-        mock_test_config = self.create_mock_test_config(
-            self.base_mock_test_config)
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger(alias=None):
-            pass
-        mock_create_alias.asset_not_called()
-
-    @mock.patch('mobly.utils.create_alias')
-    def test_mobly_logger_skips_latest_log_alias_when_empty(
-            self, mock_create_alias):
-        mock_test_config = self.create_mock_test_config(
-            self.base_mock_test_config)
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger(alias=''):
-            pass
-        mock_create_alias.asset_not_called()
-
-    def test_logging_before_run(self):
-        """Verifies the expected output files from a test run.
-
-        * Files are correctly created.
-        * Basic sanity checks of each output file.
-        """
-        mock_test_config = self.create_mock_test_config(
-            self.base_mock_test_config)
-        info_uuid = 'e098d4ff-4e90-4e08-b369-aa84a7ef90ec'
-        debug_uuid = 'c6f1474e-960a-4df8-8305-1c5b8b905eca'
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger():
-            logging.info(info_uuid)
-            logging.debug(debug_uuid)
-            tr.add_test_class(mock_test_config,
-                              integration_test.IntegrationTest)
-            tr.run()
-        output_dir = logging.root_output_path
-        (summary_file_path, debug_log_path,
-         info_log_path) = self.assert_output_logs_exist(output_dir)
-        self.assert_log_contents(debug_log_path,
-                                 whitelist=[debug_uuid, info_uuid])
-        self.assert_log_contents(info_log_path,
-                                 whitelist=[info_uuid],
-                                 blacklist=[debug_uuid])
-
-    @mock.patch('mobly.logger.get_log_file_timestamp',
-                side_effect=str(time.time()))
-    def test_run_twice_for_two_sets_of_logs(self, mock_timestamp):
-        """Verifies the expected output files from a test run.
-
-        * Files are correctly created.
-        * Basic sanity checks of each output file.
-        """
-        mock_test_config = self.create_mock_test_config(
-            self.base_mock_test_config)
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        tr.add_test_class(mock_test_config, integration_test.IntegrationTest)
-        with tr.mobly_logger():
-            tr.run()
-        output_dir1 = logging.root_output_path
-        with tr.mobly_logger():
-            tr.run()
-        output_dir2 = logging.root_output_path
-        self.assertNotEqual(output_dir1, output_dir2)
-        self.assert_output_logs_exist(output_dir1)
-        self.assert_output_logs_exist(output_dir2)
-
-    @mock.patch('mobly.logger.get_log_file_timestamp',
-                side_effect=str(time.time()))
-    def test_teardown_erases_logs(self, mock_timestamp):
-        """Verifies the expected output files from a test run.
-
-        * Files are correctly created.
-        * Basic sanity checks of each output file.
-        """
-        mock_test_config = self.create_mock_test_config(
-            self.base_mock_test_config)
-        info_uuid1 = '0c3ebb06-700d-496e-b015-62652da9e451'
-        debug_uuid1 = '0c3ebb06-700d-496e-b015-62652da9e451'
-        info_uuid2 = '484ef7db-f2dd-4b76-a126-c2f263e3808c'
-        debug_uuid2 = 'd564da87-c42f-49c3-b0bf-18fa97cf0218'
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-
-        with tr.mobly_logger():
-            logging.info(info_uuid1)
-            logging.debug(debug_uuid1)
-        output_dir1 = logging.log_path
-
-        with tr.mobly_logger():
-            logging.info(info_uuid2)
-            logging.debug(debug_uuid2)
-        output_dir2 = logging.log_path
-
-        self.assertNotEqual(output_dir1, output_dir2)
-
-        (summary_file_path1, debug_log_path1,
-         info_log_path1) = self.get_output_logs(output_dir1)
-        (summary_file_path2, debug_log_path2,
-         info_log_path2) = self.get_output_logs(output_dir2)
-
-        self.assert_log_contents(debug_log_path1,
-                                 whitelist=[debug_uuid1, info_uuid1],
-                                 blacklist=[info_uuid2, debug_uuid2])
-        self.assert_log_contents(debug_log_path2,
-                                 whitelist=[debug_uuid2, info_uuid2],
-                                 blacklist=[info_uuid1, debug_uuid1])
-
-    def test_basic_output(self):
-        """Verifies the expected output files from a test run.
-
-        * Files are correctly created.
-        * Basic sanity checks of each output file.
-        """
-        mock_test_config = self.create_mock_test_config(
-            self.base_mock_test_config)
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger():
-            tr.add_test_class(mock_test_config,
-                              integration_test.IntegrationTest)
-            tr.run()
-        expected_class_path = os.path.join(logging.root_output_path,
-                                           'IntegrationTest')
-        self.assertEqual(expected_class_path, logging.log_path)
-        os.path.exists(logging.log_path)
-        output_dir = logging.root_output_path
-        (summary_file_path, debug_log_path,
-         info_log_path) = self.assert_output_logs_exist(output_dir)
-        summary_entries = []
-        with io.open(summary_file_path, 'r', encoding='utf-8') as f:
-            for entry in yaml.safe_load_all(f):
-                self.assertTrue(entry['Type'])
-                summary_entries.append(entry)
-        self.assert_log_contents(debug_log_path, whitelist=['DEBUG', 'INFO'])
-        self.assert_log_contents(info_log_path,
-                                 whitelist=['INFO'],
-                                 blacklist=['DEBUG'])
-
-    def test_teardown_class_output(self):
-        """Verifies the summary file includes the failure record for
-        teardown_class.
-        """
-        mock_test_config = self.base_mock_test_config.copy()
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger():
-            tr.add_test_class(
-                mock_test_config,
-                teardown_class_failure_test.TearDownClassFailureTest)
-            tr.run()
-        output_dir = logging.root_output_path
-        summary_file_path = os.path.join(output_dir,
-                                         records.OUTPUT_FILE_SUMMARY)
-        found = False
-        with io.open(summary_file_path, 'r', encoding='utf-8') as f:
-            raw_content = f.read()
-            f.seek(0)
-            for entry in yaml.safe_load_all(f):
-                if (entry['Type'] == 'Record'
-                        and entry[records.TestResultEnums.RECORD_NAME] ==
-                        'teardown_class'):
-                    found = True
-                    break
-            self.assertTrue(
-                found,
-                'No record for teardown_class found in the output file:\n %s' %
-                raw_content)
+  def test_teardown_class_output(self):
+    """Verifies the summary file includes the failure record for
+    teardown_class.
+    """
+    mock_test_config = self.base_mock_test_config.copy()
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger():
+      tr.add_test_class(
+        mock_test_config,
+        teardown_class_failure_test.TearDownClassFailureTest)
+      tr.run()
+    output_dir = logging.root_output_path
+    summary_file_path = os.path.join(output_dir,
+                     records.OUTPUT_FILE_SUMMARY)
+    found = False
+    with io.open(summary_file_path, 'r', encoding='utf-8') as f:
+      raw_content = f.read()
+      f.seek(0)
+      for entry in yaml.safe_load_all(f):
+        if (entry['Type'] == 'Record'
+            and entry[records.TestResultEnums.RECORD_NAME] ==
+            'teardown_class'):
+          found = True
+          break
+      self.assertTrue(
+        found,
+        'No record for teardown_class found in the output file:\n %s' %
+        raw_content)
 
 
 if __name__ == "__main__":
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/records_test.py b/tests/mobly/records_test.py
index a374347..d850675 100755
--- a/tests/mobly/records_test.py
+++ b/tests/mobly/records_test.py
@@ -32,408 +32,408 @@
 
 
 class RecordTestError(Exception):
-    """Error class with constructors that take extra args.
+  """Error class with constructors that take extra args.
 
-    Used for ExceptionRecord tests.
-    """
+  Used for ExceptionRecord tests.
+  """
 
-    def __init__(self, something):
-        self._something = something
+  def __init__(self, something):
+    self._something = something
 
 
 class RecordsTest(unittest.TestCase):
-    """This test class tests the implementation of classes in mobly.records.
+  """This test class tests the implementation of classes in mobly.records.
+  """
+
+  def setUp(self):
+    self.tn = 'test_name'
+    self.details = 'Some details about the test execution.'
+    self.float_extra = 12345.56789
+    self.json_extra = {'ha': 'whatever'}
+    self.tmp_path = tempfile.mkdtemp()
+
+  def tearDown(self):
+    shutil.rmtree(self.tmp_path)
+
+  def verify_record(self, record, result, details, extras, stacktrace=None):
+    record.update_record()
+    # Verify each field.
+    self.assertEqual(record.test_name, self.tn)
+    self.assertEqual(record.result, result)
+    self.assertEqual(record.details, details)
+    self.assertEqual(record.extras, extras)
+    self.assertTrue(record.begin_time, 'begin time should not be empty.')
+    self.assertTrue(record.end_time, 'end time should not be empty.')
+    # UID is not used at the moment, should always be None.
+    self.assertIsNone(record.uid)
+    # Verify to_dict.
+    d = {}
+    d[records.TestResultEnums.RECORD_NAME] = self.tn
+    d[records.TestResultEnums.RECORD_RESULT] = result
+    d[records.TestResultEnums.RECORD_DETAILS] = details
+    d[records.TestResultEnums.RECORD_EXTRAS] = extras
+    d[records.TestResultEnums.RECORD_BEGIN_TIME] = record.begin_time
+    d[records.TestResultEnums.RECORD_END_TIME] = record.end_time
+    d[records.TestResultEnums.RECORD_UID] = None
+    d[records.TestResultEnums.RECORD_CLASS] = None
+    d[records.TestResultEnums.RECORD_EXTRA_ERRORS] = {}
+    d[records.TestResultEnums.RECORD_STACKTRACE] = stacktrace
+    actual_d = record.to_dict()
+    # Verify stacktrace partially match as stacktraces often have file path
+    # in them.
+    if stacktrace:
+      stacktrace_key = records.TestResultEnums.RECORD_STACKTRACE
+      self.assertTrue(
+        d.pop(stacktrace_key) in actual_d.pop(stacktrace_key))
+    self.assertDictEqual(actual_d, d)
+    # Verify that these code paths do not cause crashes and yield non-empty
+    # results.
+    self.assertTrue(str(record), 'str of the record should not be empty.')
+    self.assertTrue(repr(record), "the record's repr shouldn't be empty.")
+
+  """ Begin of Tests """
+
+  def test_result_record_pass_none(self):
+    record = records.TestResultRecord(self.tn)
+    record.test_begin()
+    record.test_pass()
+    self.verify_record(
+      record=record,
+      result=records.TestResultEnums.TEST_RESULT_PASS,
+      details=None,
+      extras=None)
+
+  def test_result_record_pass_with_float_extra(self):
+    record = records.TestResultRecord(self.tn)
+    record.test_begin()
+    s = signals.TestPass(self.details, self.float_extra)
+    record.test_pass(s)
+    self.verify_record(
+      record=record,
+      result=records.TestResultEnums.TEST_RESULT_PASS,
+      details=self.details,
+      extras=self.float_extra)
+
+  def test_result_record_pass_with_json_extra(self):
+    record = records.TestResultRecord(self.tn)
+    record.test_begin()
+    s = signals.TestPass(self.details, self.json_extra)
+    record.test_pass(s)
+    self.verify_record(
+      record=record,
+      result=records.TestResultEnums.TEST_RESULT_PASS,
+      details=self.details,
+      extras=self.json_extra)
+
+  def test_result_record_fail_none(self):
+    record = records.TestResultRecord(self.tn)
+    record.test_begin()
+    record.test_fail()
+    self.verify_record(
+      record=record,
+      result=records.TestResultEnums.TEST_RESULT_FAIL,
+      details=None,
+      extras=None)
+
+  def test_result_record_fail_stacktrace(self):
+    record = records.TestResultRecord(self.tn)
+    record.test_begin()
+    try:
+      raise Exception('Something failed.')
+    except Exception as e:
+      record.test_fail(e)
+    # Verify stacktrace separately if we expect a non-None value.
+    # Because stacktrace includes file names and line numbers, we can't do
+    # a simple equality check.
+    self.verify_record(
+      record=record,
+      result=records.TestResultEnums.TEST_RESULT_FAIL,
+      details='Something failed.',
+      extras=None,
+      stacktrace='in test_result_record_fail_stacktrace\n    '
+      'raise Exception(\'Something failed.\')\nException: '
+      'Something failed.\n')
+
+  def test_result_record_fail_with_float_extra(self):
+    record = records.TestResultRecord(self.tn)
+    record.test_begin()
+    s = signals.TestFailure(self.details, self.float_extra)
+    record.test_fail(s)
+    self.verify_record(
+      record=record,
+      result=records.TestResultEnums.TEST_RESULT_FAIL,
+      details=self.details,
+      extras=self.float_extra)
+
+  def test_result_record_fail_with_unicode_test_signal(self):
+    record = records.TestResultRecord(self.tn)
+    record.test_begin()
+    details = u'\u2022'
+    s = signals.TestFailure(details, self.float_extra)
+    record.test_fail(s)
+    self.verify_record(
+      record=record,
+      result=records.TestResultEnums.TEST_RESULT_FAIL,
+      details=details,
+      extras=self.float_extra)
+
+  def test_result_record_fail_with_unicode_exception(self):
+    record = records.TestResultRecord(self.tn)
+    record.test_begin()
+    details = u'\u2022'
+    s = Exception(details)
+    record.test_fail(s)
+    self.verify_record(
+      record=record,
+      result=records.TestResultEnums.TEST_RESULT_FAIL,
+      details=details,
+      extras=None)
+
+  def test_result_record_fail_with_json_extra(self):
+    record = records.TestResultRecord(self.tn)
+    record.test_begin()
+    s = signals.TestFailure(self.details, self.json_extra)
+    record.test_fail(s)
+    self.verify_record(
+      record=record,
+      result=records.TestResultEnums.TEST_RESULT_FAIL,
+      details=self.details,
+      extras=self.json_extra)
+
+  def test_result_record_skip_none(self):
+    record = records.TestResultRecord(self.tn)
+    record.test_begin()
+    record.test_skip()
+    self.verify_record(
+      record=record,
+      result=records.TestResultEnums.TEST_RESULT_SKIP,
+      details=None,
+      extras=None)
+
+  def test_result_record_skip_with_float_extra(self):
+    record = records.TestResultRecord(self.tn)
+    record.test_begin()
+    s = signals.TestSkip(self.details, self.float_extra)
+    record.test_skip(s)
+    self.verify_record(
+      record=record,
+      result=records.TestResultEnums.TEST_RESULT_SKIP,
+      details=self.details,
+      extras=self.float_extra)
+
+  def test_result_record_skip_with_json_extra(self):
+    record = records.TestResultRecord(self.tn)
+    record.test_begin()
+    s = signals.TestSkip(self.details, self.json_extra)
+    record.test_skip(s)
+    self.verify_record(
+      record=record,
+      result=records.TestResultEnums.TEST_RESULT_SKIP,
+      details=self.details,
+      extras=self.json_extra)
+
+  def test_result_add_operator_success(self):
+    record1 = records.TestResultRecord(self.tn)
+    record1.test_begin()
+    s = signals.TestPass(self.details, self.float_extra)
+    record1.test_pass(s)
+    tr1 = records.TestResult()
+    tr1.add_record(record1)
+    controller_info = records.ControllerInfoRecord(
+      'SomeClass', 'MockDevice', ['magicA', 'magicB'])
+    tr1.add_controller_info_record(controller_info)
+    record2 = records.TestResultRecord(self.tn)
+    record2.test_begin()
+    s = signals.TestPass(self.details, self.json_extra)
+    record2.test_pass(s)
+    tr2 = records.TestResult()
+    tr2.add_record(record2)
+    controller_info = records.ControllerInfoRecord(
+      'SomeClass', 'MockDevice', ['magicC'])
+    tr2.add_controller_info_record(controller_info)
+    tr2 += tr1
+    self.assertTrue(tr2.passed, [tr1, tr2])
+    self.assertTrue(tr2.controller_info, {'MockDevice': ['magicC']})
+
+  def test_result_add_operator_type_mismatch(self):
+    record1 = records.TestResultRecord(self.tn)
+    record1.test_begin()
+    s = signals.TestPass(self.details, self.float_extra)
+    record1.test_pass(s)
+    tr1 = records.TestResult()
+    tr1.add_record(record1)
+    expected_msg = 'Operand .* of type .* is not a TestResult.'
+    with self.assertRaisesRegex(TypeError, expected_msg):
+      tr1 += 'haha'
+
+  def test_result_add_class_error_with_test_signal(self):
+    record1 = records.TestResultRecord(self.tn)
+    record1.test_begin()
+    s = signals.TestPass(self.details, self.float_extra)
+    record1.test_pass(s)
+    tr = records.TestResult()
+    tr.add_record(record1)
+    s = signals.TestFailure(self.details, self.float_extra)
+    record2 = records.TestResultRecord('SomeTest', s)
+    tr.add_class_error(record2)
+    self.assertEqual(len(tr.passed), 1)
+    self.assertEqual(len(tr.error), 1)
+    self.assertEqual(len(tr.executed), 1)
+
+  def test_result_add_class_error_with_special_error(self):
+    """Call TestResult.add_class_error with an error class that requires more
+    than one arg to instantiate.
     """
+    record1 = records.TestResultRecord(self.tn)
+    record1.test_begin()
+    s = signals.TestPass(self.details, self.float_extra)
+    record1.test_pass(s)
+    tr = records.TestResult()
+    tr.add_record(record1)
 
-    def setUp(self):
-        self.tn = 'test_name'
-        self.details = 'Some details about the test execution.'
-        self.float_extra = 12345.56789
-        self.json_extra = {'ha': 'whatever'}
-        self.tmp_path = tempfile.mkdtemp()
+    class SpecialError(Exception):
+      def __init__(self, arg1, arg2):
+        self.msg = '%s %s' % (arg1, arg2)
 
-    def tearDown(self):
-        shutil.rmtree(self.tmp_path)
+    se = SpecialError('haha', 42)
+    record2 = records.TestResultRecord('SomeTest', se)
+    tr.add_class_error(record2)
+    self.assertEqual(len(tr.passed), 1)
+    self.assertEqual(len(tr.error), 1)
+    self.assertEqual(len(tr.executed), 1)
 
-    def verify_record(self, record, result, details, extras, stacktrace=None):
-        record.update_record()
-        # Verify each field.
-        self.assertEqual(record.test_name, self.tn)
-        self.assertEqual(record.result, result)
-        self.assertEqual(record.details, details)
-        self.assertEqual(record.extras, extras)
-        self.assertTrue(record.begin_time, 'begin time should not be empty.')
-        self.assertTrue(record.end_time, 'end time should not be empty.')
-        # UID is not used at the moment, should always be None.
-        self.assertIsNone(record.uid)
-        # Verify to_dict.
-        d = {}
-        d[records.TestResultEnums.RECORD_NAME] = self.tn
-        d[records.TestResultEnums.RECORD_RESULT] = result
-        d[records.TestResultEnums.RECORD_DETAILS] = details
-        d[records.TestResultEnums.RECORD_EXTRAS] = extras
-        d[records.TestResultEnums.RECORD_BEGIN_TIME] = record.begin_time
-        d[records.TestResultEnums.RECORD_END_TIME] = record.end_time
-        d[records.TestResultEnums.RECORD_UID] = None
-        d[records.TestResultEnums.RECORD_CLASS] = None
-        d[records.TestResultEnums.RECORD_EXTRA_ERRORS] = {}
-        d[records.TestResultEnums.RECORD_STACKTRACE] = stacktrace
-        actual_d = record.to_dict()
-        # Verify stacktrace partially match as stacktraces often have file path
-        # in them.
-        if stacktrace:
-            stacktrace_key = records.TestResultEnums.RECORD_STACKTRACE
-            self.assertTrue(
-                d.pop(stacktrace_key) in actual_d.pop(stacktrace_key))
-        self.assertDictEqual(actual_d, d)
-        # Verify that these code paths do not cause crashes and yield non-empty
-        # results.
-        self.assertTrue(str(record), 'str of the record should not be empty.')
-        self.assertTrue(repr(record), "the record's repr shouldn't be empty.")
+  def test_is_all_pass(self):
+    s = signals.TestPass(self.details, self.float_extra)
+    record1 = records.TestResultRecord(self.tn)
+    record1.test_begin()
+    record1.test_pass(s)
+    s = signals.TestSkip(self.details, self.float_extra)
+    record2 = records.TestResultRecord(self.tn)
+    record2.test_begin()
+    record2.test_skip(s)
+    tr = records.TestResult()
+    tr.add_record(record1)
+    tr.add_record(record2)
+    tr.add_record(record1)
+    self.assertEqual(len(tr.passed), 2)
+    self.assertTrue(tr.is_all_pass)
 
-    """ Begin of Tests """
+  def test_is_all_pass_negative(self):
+    s = signals.TestFailure(self.details, self.float_extra)
+    record1 = records.TestResultRecord(self.tn)
+    record1.test_begin()
+    record1.test_fail(s)
+    record2 = records.TestResultRecord(self.tn)
+    record2.test_begin()
+    record2.test_error(s)
+    tr = records.TestResult()
+    tr.add_record(record1)
+    tr.add_record(record2)
+    utils.validate_test_result(tr)
+    self.assertFalse(tr.is_all_pass)
 
-    def test_result_record_pass_none(self):
-        record = records.TestResultRecord(self.tn)
-        record.test_begin()
-        record.test_pass()
-        self.verify_record(
-            record=record,
-            result=records.TestResultEnums.TEST_RESULT_PASS,
-            details=None,
-            extras=None)
+  def test_is_all_pass_with_add_class_error(self):
+    """Verifies that is_all_pass yields correct value when add_class_error is
+    used.
+    """
+    record1 = records.TestResultRecord(self.tn)
+    record1.test_begin()
+    record1.test_fail(Exception('haha'))
+    tr = records.TestResult()
+    tr.add_class_error(record1)
+    self.assertFalse(tr.is_all_pass)
 
-    def test_result_record_pass_with_float_extra(self):
-        record = records.TestResultRecord(self.tn)
-        record.test_begin()
-        s = signals.TestPass(self.details, self.float_extra)
-        record.test_pass(s)
-        self.verify_record(
-            record=record,
-            result=records.TestResultEnums.TEST_RESULT_PASS,
-            details=self.details,
-            extras=self.float_extra)
+  def test_is_test_executed(self):
+    record1 = records.TestResultRecord(self.tn)
+    record1.test_begin()
+    record1.test_fail(Exception('haha'))
+    tr = records.TestResult()
+    tr.add_record(record1)
+    self.assertTrue(tr.is_test_executed(record1.test_name))
+    self.assertFalse(tr.is_test_executed(self.tn + 'ha'))
 
-    def test_result_record_pass_with_json_extra(self):
-        record = records.TestResultRecord(self.tn)
-        record.test_begin()
-        s = signals.TestPass(self.details, self.json_extra)
-        record.test_pass(s)
-        self.verify_record(
-            record=record,
-            result=records.TestResultEnums.TEST_RESULT_PASS,
-            details=self.details,
-            extras=self.json_extra)
+  def test_summary_write_dump(self):
+    s = signals.TestFailure(self.details, self.float_extra)
+    record1 = records.TestResultRecord(self.tn)
+    record1.test_begin()
+    record1.test_fail(s)
+    dump_path = os.path.join(self.tmp_path, 'ha.yaml')
+    writer = records.TestSummaryWriter(dump_path)
+    writer.dump(record1.to_dict(), records.TestSummaryEntryType.RECORD)
+    with io.open(dump_path, 'r', encoding='utf-8') as f:
+      content = yaml.safe_load(f)
+      self.assertEqual(content['Type'],
+               records.TestSummaryEntryType.RECORD.value)
+      self.assertEqual(content[records.TestResultEnums.RECORD_DETAILS],
+               self.details)
+      self.assertEqual(content[records.TestResultEnums.RECORD_EXTRAS],
+               self.float_extra)
 
-    def test_result_record_fail_none(self):
-        record = records.TestResultRecord(self.tn)
-        record.test_begin()
-        record.test_fail()
-        self.verify_record(
-            record=record,
-            result=records.TestResultEnums.TEST_RESULT_FAIL,
-            details=None,
-            extras=None)
+  def test_summary_write_dump_with_unicode(self):
+    unicode_details = u'\u901a'  # utf-8 -> b'\xe9\x80\x9a'
+    unicode_extras = u'\u8fc7'  # utf-8 -> b'\xe8\xbf\x87'
+    s = signals.TestFailure(unicode_details, unicode_extras)
+    record1 = records.TestResultRecord(self.tn)
+    record1.test_begin()
+    record1.test_fail(s)
+    dump_path = os.path.join(self.tmp_path, 'ha.yaml')
+    writer = records.TestSummaryWriter(dump_path)
+    writer.dump(record1.to_dict(), records.TestSummaryEntryType.RECORD)
+    with io.open(dump_path, 'r', encoding='utf-8') as f:
+      content = yaml.safe_load(f)
+      self.assertEqual(content['Type'],
+               records.TestSummaryEntryType.RECORD.value)
+      self.assertEqual(content[records.TestResultEnums.RECORD_DETAILS],
+               unicode_details)
+      self.assertEqual(content[records.TestResultEnums.RECORD_EXTRAS],
+               unicode_extras)
 
-    def test_result_record_fail_stacktrace(self):
-        record = records.TestResultRecord(self.tn)
-        record.test_begin()
-        try:
-            raise Exception('Something failed.')
-        except Exception as e:
-            record.test_fail(e)
-        # Verify stacktrace separately if we expect a non-None value.
-        # Because stacktrace includes file names and line numbers, we can't do
-        # a simple equality check.
-        self.verify_record(
-            record=record,
-            result=records.TestResultEnums.TEST_RESULT_FAIL,
-            details='Something failed.',
-            extras=None,
-            stacktrace='in test_result_record_fail_stacktrace\n    '
-            'raise Exception(\'Something failed.\')\nException: '
-            'Something failed.\n')
+  def test_summary_user_data(self):
+    user_data1 = {'a': 1}
+    user_data2 = {'b': 1}
+    user_data = [user_data1, user_data2]
+    dump_path = os.path.join(self.tmp_path, 'ha.yaml')
+    writer = records.TestSummaryWriter(dump_path)
+    for data in user_data:
+      writer.dump(data, records.TestSummaryEntryType.USER_DATA)
+    with io.open(dump_path, 'r', encoding='utf-8') as f:
+      contents = []
+      for c in yaml.safe_load_all(f):
+        contents.append(c)
+    for content in contents:
+      self.assertEqual(content['Type'],
+               records.TestSummaryEntryType.USER_DATA.value)
+    self.assertEqual(contents[0]['a'], user_data1['a'])
+    self.assertEqual(contents[1]['b'], user_data2['b'])
 
-    def test_result_record_fail_with_float_extra(self):
-        record = records.TestResultRecord(self.tn)
-        record.test_begin()
-        s = signals.TestFailure(self.details, self.float_extra)
-        record.test_fail(s)
-        self.verify_record(
-            record=record,
-            result=records.TestResultEnums.TEST_RESULT_FAIL,
-            details=self.details,
-            extras=self.float_extra)
+  def test_exception_record_deepcopy(self):
+    """Makes sure ExceptionRecord wrapper handles deep copy properly."""
+    try:
+      raise RecordTestError('Oh ha!')
+    except RecordTestError as e:
+      er = records.ExceptionRecord(e)
+    new_er = copy.deepcopy(er)
+    self.assertIsNot(er, new_er)
+    self.assertDictEqual(er.to_dict(), new_er.to_dict())
 
-    def test_result_record_fail_with_unicode_test_signal(self):
-        record = records.TestResultRecord(self.tn)
-        record.test_begin()
-        details = u'\u2022'
-        s = signals.TestFailure(details, self.float_extra)
-        record.test_fail(s)
-        self.verify_record(
-            record=record,
-            result=records.TestResultEnums.TEST_RESULT_FAIL,
-            details=details,
-            extras=self.float_extra)
+  def test_add_controller_info_record(self):
+    tr = records.TestResult()
+    self.assertFalse(tr.controller_info)
+    controller_info = records.ControllerInfoRecord(
+      'SomeClass', 'MockDevice', ['magicA', 'magicB'])
+    tr.add_controller_info_record(controller_info)
+    self.assertTrue(tr.controller_info[0])
+    self.assertEqual(tr.controller_info[0].controller_name, 'MockDevice')
+    self.assertEqual(tr.controller_info[0].controller_info,
+             ['magicA', 'magicB'])
 
-    def test_result_record_fail_with_unicode_exception(self):
-        record = records.TestResultRecord(self.tn)
-        record.test_begin()
-        details = u'\u2022'
-        s = Exception(details)
-        record.test_fail(s)
-        self.verify_record(
-            record=record,
-            result=records.TestResultEnums.TEST_RESULT_FAIL,
-            details=details,
-            extras=None)
+  def test_uid(self):
+    @records.uid('some-uuid')
+    def test_uid_helper():
+      """Dummy test used by `test_uid` for testing the uid decorator."""
 
-    def test_result_record_fail_with_json_extra(self):
-        record = records.TestResultRecord(self.tn)
-        record.test_begin()
-        s = signals.TestFailure(self.details, self.json_extra)
-        record.test_fail(s)
-        self.verify_record(
-            record=record,
-            result=records.TestResultEnums.TEST_RESULT_FAIL,
-            details=self.details,
-            extras=self.json_extra)
-
-    def test_result_record_skip_none(self):
-        record = records.TestResultRecord(self.tn)
-        record.test_begin()
-        record.test_skip()
-        self.verify_record(
-            record=record,
-            result=records.TestResultEnums.TEST_RESULT_SKIP,
-            details=None,
-            extras=None)
-
-    def test_result_record_skip_with_float_extra(self):
-        record = records.TestResultRecord(self.tn)
-        record.test_begin()
-        s = signals.TestSkip(self.details, self.float_extra)
-        record.test_skip(s)
-        self.verify_record(
-            record=record,
-            result=records.TestResultEnums.TEST_RESULT_SKIP,
-            details=self.details,
-            extras=self.float_extra)
-
-    def test_result_record_skip_with_json_extra(self):
-        record = records.TestResultRecord(self.tn)
-        record.test_begin()
-        s = signals.TestSkip(self.details, self.json_extra)
-        record.test_skip(s)
-        self.verify_record(
-            record=record,
-            result=records.TestResultEnums.TEST_RESULT_SKIP,
-            details=self.details,
-            extras=self.json_extra)
-
-    def test_result_add_operator_success(self):
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        s = signals.TestPass(self.details, self.float_extra)
-        record1.test_pass(s)
-        tr1 = records.TestResult()
-        tr1.add_record(record1)
-        controller_info = records.ControllerInfoRecord(
-            'SomeClass', 'MockDevice', ['magicA', 'magicB'])
-        tr1.add_controller_info_record(controller_info)
-        record2 = records.TestResultRecord(self.tn)
-        record2.test_begin()
-        s = signals.TestPass(self.details, self.json_extra)
-        record2.test_pass(s)
-        tr2 = records.TestResult()
-        tr2.add_record(record2)
-        controller_info = records.ControllerInfoRecord(
-            'SomeClass', 'MockDevice', ['magicC'])
-        tr2.add_controller_info_record(controller_info)
-        tr2 += tr1
-        self.assertTrue(tr2.passed, [tr1, tr2])
-        self.assertTrue(tr2.controller_info, {'MockDevice': ['magicC']})
-
-    def test_result_add_operator_type_mismatch(self):
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        s = signals.TestPass(self.details, self.float_extra)
-        record1.test_pass(s)
-        tr1 = records.TestResult()
-        tr1.add_record(record1)
-        expected_msg = 'Operand .* of type .* is not a TestResult.'
-        with self.assertRaisesRegex(TypeError, expected_msg):
-            tr1 += 'haha'
-
-    def test_result_add_class_error_with_test_signal(self):
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        s = signals.TestPass(self.details, self.float_extra)
-        record1.test_pass(s)
-        tr = records.TestResult()
-        tr.add_record(record1)
-        s = signals.TestFailure(self.details, self.float_extra)
-        record2 = records.TestResultRecord('SomeTest', s)
-        tr.add_class_error(record2)
-        self.assertEqual(len(tr.passed), 1)
-        self.assertEqual(len(tr.error), 1)
-        self.assertEqual(len(tr.executed), 1)
-
-    def test_result_add_class_error_with_special_error(self):
-        """Call TestResult.add_class_error with an error class that requires more
-        than one arg to instantiate.
-        """
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        s = signals.TestPass(self.details, self.float_extra)
-        record1.test_pass(s)
-        tr = records.TestResult()
-        tr.add_record(record1)
-
-        class SpecialError(Exception):
-            def __init__(self, arg1, arg2):
-                self.msg = '%s %s' % (arg1, arg2)
-
-        se = SpecialError('haha', 42)
-        record2 = records.TestResultRecord('SomeTest', se)
-        tr.add_class_error(record2)
-        self.assertEqual(len(tr.passed), 1)
-        self.assertEqual(len(tr.error), 1)
-        self.assertEqual(len(tr.executed), 1)
-
-    def test_is_all_pass(self):
-        s = signals.TestPass(self.details, self.float_extra)
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        record1.test_pass(s)
-        s = signals.TestSkip(self.details, self.float_extra)
-        record2 = records.TestResultRecord(self.tn)
-        record2.test_begin()
-        record2.test_skip(s)
-        tr = records.TestResult()
-        tr.add_record(record1)
-        tr.add_record(record2)
-        tr.add_record(record1)
-        self.assertEqual(len(tr.passed), 2)
-        self.assertTrue(tr.is_all_pass)
-
-    def test_is_all_pass_negative(self):
-        s = signals.TestFailure(self.details, self.float_extra)
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        record1.test_fail(s)
-        record2 = records.TestResultRecord(self.tn)
-        record2.test_begin()
-        record2.test_error(s)
-        tr = records.TestResult()
-        tr.add_record(record1)
-        tr.add_record(record2)
-        utils.validate_test_result(tr)
-        self.assertFalse(tr.is_all_pass)
-
-    def test_is_all_pass_with_add_class_error(self):
-        """Verifies that is_all_pass yields correct value when add_class_error is
-        used.
-        """
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        record1.test_fail(Exception('haha'))
-        tr = records.TestResult()
-        tr.add_class_error(record1)
-        self.assertFalse(tr.is_all_pass)
-
-    def test_is_test_executed(self):
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        record1.test_fail(Exception('haha'))
-        tr = records.TestResult()
-        tr.add_record(record1)
-        self.assertTrue(tr.is_test_executed(record1.test_name))
-        self.assertFalse(tr.is_test_executed(self.tn + 'ha'))
-
-    def test_summary_write_dump(self):
-        s = signals.TestFailure(self.details, self.float_extra)
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        record1.test_fail(s)
-        dump_path = os.path.join(self.tmp_path, 'ha.yaml')
-        writer = records.TestSummaryWriter(dump_path)
-        writer.dump(record1.to_dict(), records.TestSummaryEntryType.RECORD)
-        with io.open(dump_path, 'r', encoding='utf-8') as f:
-            content = yaml.safe_load(f)
-            self.assertEqual(content['Type'],
-                             records.TestSummaryEntryType.RECORD.value)
-            self.assertEqual(content[records.TestResultEnums.RECORD_DETAILS],
-                             self.details)
-            self.assertEqual(content[records.TestResultEnums.RECORD_EXTRAS],
-                             self.float_extra)
-
-    def test_summary_write_dump_with_unicode(self):
-        unicode_details = u'\u901a'  # utf-8 -> b'\xe9\x80\x9a'
-        unicode_extras = u'\u8fc7'  # utf-8 -> b'\xe8\xbf\x87'
-        s = signals.TestFailure(unicode_details, unicode_extras)
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        record1.test_fail(s)
-        dump_path = os.path.join(self.tmp_path, 'ha.yaml')
-        writer = records.TestSummaryWriter(dump_path)
-        writer.dump(record1.to_dict(), records.TestSummaryEntryType.RECORD)
-        with io.open(dump_path, 'r', encoding='utf-8') as f:
-            content = yaml.safe_load(f)
-            self.assertEqual(content['Type'],
-                             records.TestSummaryEntryType.RECORD.value)
-            self.assertEqual(content[records.TestResultEnums.RECORD_DETAILS],
-                             unicode_details)
-            self.assertEqual(content[records.TestResultEnums.RECORD_EXTRAS],
-                             unicode_extras)
-
-    def test_summary_user_data(self):
-        user_data1 = {'a': 1}
-        user_data2 = {'b': 1}
-        user_data = [user_data1, user_data2]
-        dump_path = os.path.join(self.tmp_path, 'ha.yaml')
-        writer = records.TestSummaryWriter(dump_path)
-        for data in user_data:
-            writer.dump(data, records.TestSummaryEntryType.USER_DATA)
-        with io.open(dump_path, 'r', encoding='utf-8') as f:
-            contents = []
-            for c in yaml.safe_load_all(f):
-                contents.append(c)
-        for content in contents:
-            self.assertEqual(content['Type'],
-                             records.TestSummaryEntryType.USER_DATA.value)
-        self.assertEqual(contents[0]['a'], user_data1['a'])
-        self.assertEqual(contents[1]['b'], user_data2['b'])
-
-    def test_exception_record_deepcopy(self):
-        """Makes sure ExceptionRecord wrapper handles deep copy properly."""
-        try:
-            raise RecordTestError('Oh ha!')
-        except RecordTestError as e:
-            er = records.ExceptionRecord(e)
-        new_er = copy.deepcopy(er)
-        self.assertIsNot(er, new_er)
-        self.assertDictEqual(er.to_dict(), new_er.to_dict())
-
-    def test_add_controller_info_record(self):
-        tr = records.TestResult()
-        self.assertFalse(tr.controller_info)
-        controller_info = records.ControllerInfoRecord(
-            'SomeClass', 'MockDevice', ['magicA', 'magicB'])
-        tr.add_controller_info_record(controller_info)
-        self.assertTrue(tr.controller_info[0])
-        self.assertEqual(tr.controller_info[0].controller_name, 'MockDevice')
-        self.assertEqual(tr.controller_info[0].controller_info,
-                         ['magicA', 'magicB'])
-
-    def test_uid(self):
-        @records.uid('some-uuid')
-        def test_uid_helper():
-            """Dummy test used by `test_uid` for testing the uid decorator."""
-
-        self.assertEqual(test_uid_helper.uid, 'some-uuid')
+    self.assertEqual(test_uid_helper.uid, 'some-uuid')
 
 
 if __name__ == '__main__':
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/suite_runner_test.py b/tests/mobly/suite_runner_test.py
index 57d6489..f9665fb 100755
--- a/tests/mobly/suite_runner_test.py
+++ b/tests/mobly/suite_runner_test.py
@@ -26,96 +26,96 @@
 
 
 class SuiteRunnerTest(unittest.TestCase):
-    def setUp(self):
-        self.tmp_dir = tempfile.mkdtemp()
+  def setUp(self):
+    self.tmp_dir = tempfile.mkdtemp()
 
-    def tearDown(self):
-        shutil.rmtree(self.tmp_dir)
+  def tearDown(self):
+    shutil.rmtree(self.tmp_dir)
 
-    def test_select_no_args(self):
-        identifiers = suite_runner.compute_selected_tests(test_classes=[
-            integration_test.IntegrationTest,
-            integration2_test.Integration2Test
-        ],
-                                                          selected_tests=None)
-        self.assertEqual(
-            {
-                integration_test.IntegrationTest: None,
-                integration2_test.Integration2Test: None,
-            }, identifiers)
+  def test_select_no_args(self):
+    identifiers = suite_runner.compute_selected_tests(test_classes=[
+      integration_test.IntegrationTest,
+      integration2_test.Integration2Test
+    ],
+                              selected_tests=None)
+    self.assertEqual(
+      {
+        integration_test.IntegrationTest: None,
+        integration2_test.Integration2Test: None,
+      }, identifiers)
 
-    def test_select_by_class(self):
-        identifiers = suite_runner.compute_selected_tests(
-            test_classes=[
-                integration_test.IntegrationTest,
-                integration2_test.Integration2Test
-            ],
-            selected_tests=['IntegrationTest'])
-        self.assertEqual({integration_test.IntegrationTest: None}, identifiers)
+  def test_select_by_class(self):
+    identifiers = suite_runner.compute_selected_tests(
+      test_classes=[
+        integration_test.IntegrationTest,
+        integration2_test.Integration2Test
+      ],
+      selected_tests=['IntegrationTest'])
+    self.assertEqual({integration_test.IntegrationTest: None}, identifiers)
 
-    def test_select_by_method(self):
-        identifiers = suite_runner.compute_selected_tests(
-            test_classes=[
-                integration_test.IntegrationTest,
-                integration2_test.Integration2Test
-            ],
-            selected_tests=[
-                'IntegrationTest.test_a', 'IntegrationTest.test_b'
-            ])
-        self.assertEqual(
-            {integration_test.IntegrationTest: ['test_a', 'test_b']},
-            identifiers)
+  def test_select_by_method(self):
+    identifiers = suite_runner.compute_selected_tests(
+      test_classes=[
+        integration_test.IntegrationTest,
+        integration2_test.Integration2Test
+      ],
+      selected_tests=[
+        'IntegrationTest.test_a', 'IntegrationTest.test_b'
+      ])
+    self.assertEqual(
+      {integration_test.IntegrationTest: ['test_a', 'test_b']},
+      identifiers)
 
-    def test_select_all_clobbers_method(self):
-        identifiers = suite_runner.compute_selected_tests(
-            test_classes=[
-                integration_test.IntegrationTest,
-                integration2_test.Integration2Test
-            ],
-            selected_tests=['IntegrationTest.test_a', 'IntegrationTest'])
-        self.assertEqual({integration_test.IntegrationTest: None}, identifiers)
+  def test_select_all_clobbers_method(self):
+    identifiers = suite_runner.compute_selected_tests(
+      test_classes=[
+        integration_test.IntegrationTest,
+        integration2_test.Integration2Test
+      ],
+      selected_tests=['IntegrationTest.test_a', 'IntegrationTest'])
+    self.assertEqual({integration_test.IntegrationTest: None}, identifiers)
 
-        identifiers = suite_runner.compute_selected_tests(
-            test_classes=[
-                integration_test.IntegrationTest,
-                integration2_test.Integration2Test
-            ],
-            selected_tests=['IntegrationTest', 'IntegrationTest.test_a'])
-        self.assertEqual({integration_test.IntegrationTest: None}, identifiers)
+    identifiers = suite_runner.compute_selected_tests(
+      test_classes=[
+        integration_test.IntegrationTest,
+        integration2_test.Integration2Test
+      ],
+      selected_tests=['IntegrationTest', 'IntegrationTest.test_a'])
+    self.assertEqual({integration_test.IntegrationTest: None}, identifiers)
 
-    @mock.patch('sys.exit')
-    def test_run_suite(self, mock_exit):
-        tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
-        with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
-            f.write(u"""
-                TestBeds:
-                    # A test bed where adb will find Android devices.
-                    - Name: SampleTestBed
-                      Controllers:
-                          MagicDevice: '*'
-                      TestParams:
-                          icecream: 42
-                          extra_param: 'haha'
-            """)
-        suite_runner.run_suite([integration_test.IntegrationTest],
-                               argv=['-c', tmp_file_path])
-        mock_exit.assert_not_called()
+  @mock.patch('sys.exit')
+  def test_run_suite(self, mock_exit):
+    tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
+    with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
+      f.write(u"""
+        TestBeds:
+          # A test bed where adb will find Android devices.
+          - Name: SampleTestBed
+            Controllers:
+              MagicDevice: '*'
+            TestParams:
+              icecream: 42
+              extra_param: 'haha'
+      """)
+    suite_runner.run_suite([integration_test.IntegrationTest],
+                 argv=['-c', tmp_file_path])
+    mock_exit.assert_not_called()
 
-    @mock.patch('sys.exit')
-    def test_run_suite_with_failures(self, mock_exit):
-        tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
-        with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
-            f.write(u"""
-                TestBeds:
-                    # A test bed where adb will find Android devices.
-                    - Name: SampleTestBed
-                      Controllers:
-                          MagicDevice: '*'
-            """)
-        suite_runner.run_suite([integration_test.IntegrationTest],
-                               argv=['-c', tmp_file_path])
-        mock_exit.assert_called_once_with(1)
+  @mock.patch('sys.exit')
+  def test_run_suite_with_failures(self, mock_exit):
+    tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
+    with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
+      f.write(u"""
+        TestBeds:
+          # A test bed where adb will find Android devices.
+          - Name: SampleTestBed
+            Controllers:
+              MagicDevice: '*'
+      """)
+    suite_runner.run_suite([integration_test.IntegrationTest],
+                 argv=['-c', tmp_file_path])
+    mock_exit.assert_called_once_with(1)
 
 
 if __name__ == "__main__":
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/test_runner_test.py b/tests/mobly/test_runner_test.py
index 65b9e72..6077675 100755
--- a/tests/mobly/test_runner_test.py
+++ b/tests/mobly/test_runner_test.py
@@ -36,350 +36,350 @@
 
 
 class TestRunnerTest(unittest.TestCase):
-    """This test class has unit tests for the implementation of everything
-    under mobly.test_runner.
+  """This test class has unit tests for the implementation of everything
+  under mobly.test_runner.
+  """
+
+  def setUp(self):
+    self.tmp_dir = tempfile.mkdtemp()
+    self.base_mock_test_config = config_parser.TestRunConfig()
+    self.base_mock_test_config.testbed_name = 'SampleTestBed'
+    self.base_mock_test_config.controller_configs = {}
+    self.base_mock_test_config.user_params = {
+      'icecream': 42,
+      'extra_param': 'haha'
+    }
+    self.base_mock_test_config.log_path = self.tmp_dir
+    self.log_dir = self.base_mock_test_config.log_path
+    self.testbed_name = self.base_mock_test_config.testbed_name
+
+  def tearDown(self):
+    shutil.rmtree(self.tmp_dir)
+
+  def _assertControllerInfoEqual(self, info, expected_info_dict):
+    self.assertEqual(expected_info_dict['Controller Name'],
+             info.controller_name)
+    self.assertEqual(expected_info_dict['Test Class'], info.test_class)
+    self.assertEqual(expected_info_dict['Controller Info'],
+             info.controller_info)
+
+  def test_run_twice(self):
+    """Verifies that:
+    1. Repeated run works properly.
+    2. The original configuration is not altered if a test controller
+       module modifies configuration.
     """
-
-    def setUp(self):
-        self.tmp_dir = tempfile.mkdtemp()
-        self.base_mock_test_config = config_parser.TestRunConfig()
-        self.base_mock_test_config.testbed_name = 'SampleTestBed'
-        self.base_mock_test_config.controller_configs = {}
-        self.base_mock_test_config.user_params = {
-            'icecream': 42,
-            'extra_param': 'haha'
+    mock_test_config = self.base_mock_test_config.copy()
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    my_config = [{
+      'serial': 'xxxx',
+      'magic': 'Magic1'
+    }, {
+      'serial': 'xxxx',
+      'magic': 'Magic2'
+    }]
+    mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger():
+      tr.add_test_class(mock_test_config,
+                integration_test.IntegrationTest)
+      tr.run()
+    self.assertTrue(
+      mock_test_config.controller_configs[mock_ctrlr_config_name][0])
+    with tr.mobly_logger():
+      tr.run()
+    results = tr.results.summary_dict()
+    self.assertEqual(results['Requested'], 2)
+    self.assertEqual(results['Executed'], 2)
+    self.assertEqual(results['Passed'], 2)
+    expected_info_dict = {
+      'Controller Info': [{
+        'MyMagic': {
+          'magic': 'Magic1'
         }
-        self.base_mock_test_config.log_path = self.tmp_dir
-        self.log_dir = self.base_mock_test_config.log_path
-        self.testbed_name = self.base_mock_test_config.testbed_name
-
-    def tearDown(self):
-        shutil.rmtree(self.tmp_dir)
-
-    def _assertControllerInfoEqual(self, info, expected_info_dict):
-        self.assertEqual(expected_info_dict['Controller Name'],
-                         info.controller_name)
-        self.assertEqual(expected_info_dict['Test Class'], info.test_class)
-        self.assertEqual(expected_info_dict['Controller Info'],
-                         info.controller_info)
-
-    def test_run_twice(self):
-        """Verifies that:
-        1. Repeated run works properly.
-        2. The original configuration is not altered if a test controller
-           module modifies configuration.
-        """
-        mock_test_config = self.base_mock_test_config.copy()
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        my_config = [{
-            'serial': 'xxxx',
-            'magic': 'Magic1'
-        }, {
-            'serial': 'xxxx',
-            'magic': 'Magic2'
-        }]
-        mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger():
-            tr.add_test_class(mock_test_config,
-                              integration_test.IntegrationTest)
-            tr.run()
-        self.assertTrue(
-            mock_test_config.controller_configs[mock_ctrlr_config_name][0])
-        with tr.mobly_logger():
-            tr.run()
-        results = tr.results.summary_dict()
-        self.assertEqual(results['Requested'], 2)
-        self.assertEqual(results['Executed'], 2)
-        self.assertEqual(results['Passed'], 2)
-        expected_info_dict = {
-            'Controller Info': [{
-                'MyMagic': {
-                    'magic': 'Magic1'
-                }
-            }, {
-                'MyMagic': {
-                    'magic': 'Magic2'
-                }
-            }],
-            'Controller Name':
-            'MagicDevice',
-            'Test Class':
-            'IntegrationTest',
+      }, {
+        'MyMagic': {
+          'magic': 'Magic2'
         }
-        self._assertControllerInfoEqual(tr.results.controller_info[0],
-                                        expected_info_dict)
-        self._assertControllerInfoEqual(tr.results.controller_info[1],
-                                        expected_info_dict)
-        self.assertNotEqual(tr.results.controller_info[0],
-                            tr.results.controller_info[1])
+      }],
+      'Controller Name':
+      'MagicDevice',
+      'Test Class':
+      'IntegrationTest',
+    }
+    self._assertControllerInfoEqual(tr.results.controller_info[0],
+                    expected_info_dict)
+    self._assertControllerInfoEqual(tr.results.controller_info[1],
+                    expected_info_dict)
+    self.assertNotEqual(tr.results.controller_info[0],
+              tr.results.controller_info[1])
 
-    def test_summary_file_entries(self):
-        """Verifies the output summary's file format.
+  def test_summary_file_entries(self):
+    """Verifies the output summary's file format.
 
-        This focuses on the format of the file instead of the content of
-        entries, which is covered in base_test_test.
-        """
-        mock_test_config = self.base_mock_test_config.copy()
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        my_config = [{
-            'serial': 'xxxx',
-            'magic': 'Magic1'
-        }, {
-            'serial': 'xxxx',
-            'magic': 'Magic2'
-        }]
-        mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger():
-            tr.add_test_class(mock_test_config,
-                              integration_test.IntegrationTest)
-            tr.run()
-        summary_path = os.path.join(logging.root_output_path,
-                                    records.OUTPUT_FILE_SUMMARY)
-        with io.open(summary_path, 'r', encoding='utf-8') as f:
-            summary_entries = list(yaml.safe_load_all(f))
-        self.assertEqual(len(summary_entries), 4)
-        # Verify the first entry is the list of test names.
-        self.assertEqual(summary_entries[0]['Type'],
-                         records.TestSummaryEntryType.TEST_NAME_LIST.value)
-        self.assertEqual(summary_entries[1]['Type'],
-                         records.TestSummaryEntryType.RECORD.value)
-        self.assertEqual(summary_entries[2]['Type'],
-                         records.TestSummaryEntryType.CONTROLLER_INFO.value)
-        self.assertEqual(summary_entries[3]['Type'],
-                         records.TestSummaryEntryType.SUMMARY.value)
+    This focuses on the format of the file instead of the content of
+    entries, which is covered in base_test_test.
+    """
+    mock_test_config = self.base_mock_test_config.copy()
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    my_config = [{
+      'serial': 'xxxx',
+      'magic': 'Magic1'
+    }, {
+      'serial': 'xxxx',
+      'magic': 'Magic2'
+    }]
+    mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger():
+      tr.add_test_class(mock_test_config,
+                integration_test.IntegrationTest)
+      tr.run()
+    summary_path = os.path.join(logging.root_output_path,
+                  records.OUTPUT_FILE_SUMMARY)
+    with io.open(summary_path, 'r', encoding='utf-8') as f:
+      summary_entries = list(yaml.safe_load_all(f))
+    self.assertEqual(len(summary_entries), 4)
+    # Verify the first entry is the list of test names.
+    self.assertEqual(summary_entries[0]['Type'],
+             records.TestSummaryEntryType.TEST_NAME_LIST.value)
+    self.assertEqual(summary_entries[1]['Type'],
+             records.TestSummaryEntryType.RECORD.value)
+    self.assertEqual(summary_entries[2]['Type'],
+             records.TestSummaryEntryType.CONTROLLER_INFO.value)
+    self.assertEqual(summary_entries[3]['Type'],
+             records.TestSummaryEntryType.SUMMARY.value)
 
-    def test_run(self):
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        self.base_mock_test_config.controller_configs[
-            mock_controller.MOBLY_CONTROLLER_CONFIG_NAME] = '*'
-        with tr.mobly_logger():
-            tr.add_test_class(self.base_mock_test_config,
-                              integration_test.IntegrationTest)
-            tr.run()
-        results = tr.results.summary_dict()
-        self.assertEqual(results['Requested'], 1)
-        self.assertEqual(results['Executed'], 1)
-        self.assertEqual(results['Passed'], 1)
-        self.assertEqual(len(tr.results.executed), 1)
-        record = tr.results.executed[0]
-        self.assertEqual(record.test_class, 'IntegrationTest')
+  def test_run(self):
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    self.base_mock_test_config.controller_configs[
+      mock_controller.MOBLY_CONTROLLER_CONFIG_NAME] = '*'
+    with tr.mobly_logger():
+      tr.add_test_class(self.base_mock_test_config,
+                integration_test.IntegrationTest)
+      tr.run()
+    results = tr.results.summary_dict()
+    self.assertEqual(results['Requested'], 1)
+    self.assertEqual(results['Executed'], 1)
+    self.assertEqual(results['Passed'], 1)
+    self.assertEqual(len(tr.results.executed), 1)
+    record = tr.results.executed[0]
+    self.assertEqual(record.test_class, 'IntegrationTest')
 
-    def test_run_without_mobly_logger_context(self):
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        self.base_mock_test_config.controller_configs[
-            mock_controller.MOBLY_CONTROLLER_CONFIG_NAME] = '*'
-        tr.add_test_class(self.base_mock_test_config,
-                          integration_test.IntegrationTest)
+  def test_run_without_mobly_logger_context(self):
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    self.base_mock_test_config.controller_configs[
+      mock_controller.MOBLY_CONTROLLER_CONFIG_NAME] = '*'
+    tr.add_test_class(self.base_mock_test_config,
+              integration_test.IntegrationTest)
+    tr.run()
+    results = tr.results.summary_dict()
+    self.assertEqual(results['Requested'], 1)
+    self.assertEqual(results['Executed'], 1)
+    self.assertEqual(results['Passed'], 1)
+    self.assertEqual(len(tr.results.executed), 1)
+    record = tr.results.executed[0]
+    self.assertEqual(record.test_class, 'IntegrationTest')
+
+  @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
+        return_value=mock_android_device.MockAdbProxy(1))
+  @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+        return_value=mock_android_device.MockFastbootProxy(1))
+  @mock.patch('mobly.controllers.android_device.list_adb_devices',
+        return_value=['1'])
+  @mock.patch('mobly.controllers.android_device.get_all_instances',
+        return_value=mock_android_device.get_mock_ads(1))
+  def test_run_two_test_classes(self, mock_get_all, mock_list_adb,
+                  mock_fastboot, mock_adb):
+    """Verifies that running more than one test class in one test run works
+    properly.
+
+    This requires using a built-in controller module. Using AndroidDevice
+    module since it has all the mocks needed already.
+    """
+    mock_test_config = self.base_mock_test_config.copy()
+    mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+    my_config = [{
+      'serial': 'xxxx',
+      'magic': 'Magic1'
+    }, {
+      'serial': 'xxxx',
+      'magic': 'Magic2'
+    }]
+    mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
+    mock_test_config.controller_configs['AndroidDevice'] = [{
+      'serial': '1'
+    }]
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger():
+      tr.add_test_class(mock_test_config,
+                integration2_test.Integration2Test)
+      tr.add_test_class(mock_test_config,
+                integration_test.IntegrationTest)
+      tr.run()
+    results = tr.results.summary_dict()
+    self.assertEqual(results['Requested'], 2)
+    self.assertEqual(results['Executed'], 2)
+    self.assertEqual(results['Passed'], 2)
+    self.assertEqual(len(tr.results.executed), 2)
+    # Tag of the test class defaults to the class name.
+    record1 = tr.results.executed[0]
+    record2 = tr.results.executed[1]
+    self.assertEqual(record1.test_class, 'Integration2Test')
+    self.assertEqual(record2.test_class, 'IntegrationTest')
+
+  def test_run_two_test_classes_different_configs_and_aliases(self):
+    """Verifies that running more than one test class in one test run with
+    different configs works properly.
+    """
+    config1 = self.base_mock_test_config.copy()
+    config1.controller_configs[
+      mock_controller.MOBLY_CONTROLLER_CONFIG_NAME] = [{
+        'serial': 'xxxx'
+      }]
+    config2 = config1.copy()
+    config2.user_params['icecream'] = 10
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger():
+      tr.add_test_class(config1,
+                integration_test.IntegrationTest,
+                name_suffix='FirstConfig')
+      tr.add_test_class(config2,
+                integration_test.IntegrationTest,
+                name_suffix='SecondConfig')
+      tr.run()
+    results = tr.results.summary_dict()
+    self.assertEqual(results['Requested'], 2)
+    self.assertEqual(results['Executed'], 2)
+    self.assertEqual(results['Passed'], 1)
+    self.assertEqual(results['Failed'], 1)
+    self.assertEqual(tr.results.failed[0].details, '10 != 42')
+    self.assertEqual(len(tr.results.executed), 2)
+    record1 = tr.results.executed[0]
+    record2 = tr.results.executed[1]
+    self.assertEqual(record1.test_class, 'IntegrationTest_FirstConfig')
+    self.assertEqual(record2.test_class, 'IntegrationTest_SecondConfig')
+
+  def test_run_with_abort_all(self):
+    mock_test_config = self.base_mock_test_config.copy()
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with tr.mobly_logger():
+      tr.add_test_class(mock_test_config,
+                integration3_test.Integration3Test)
+      with self.assertRaises(signals.TestAbortAll):
         tr.run()
-        results = tr.results.summary_dict()
-        self.assertEqual(results['Requested'], 1)
-        self.assertEqual(results['Executed'], 1)
-        self.assertEqual(results['Passed'], 1)
-        self.assertEqual(len(tr.results.executed), 1)
-        record = tr.results.executed[0]
-        self.assertEqual(record.test_class, 'IntegrationTest')
+    results = tr.results.summary_dict()
+    self.assertEqual(results['Requested'], 1)
+    self.assertEqual(results['Executed'], 0)
+    self.assertEqual(results['Passed'], 0)
+    self.assertEqual(results['Failed'], 0)
 
-    @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
-                return_value=mock_android_device.MockAdbProxy(1))
-    @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
-                return_value=mock_android_device.MockFastbootProxy(1))
-    @mock.patch('mobly.controllers.android_device.list_adb_devices',
-                return_value=['1'])
-    @mock.patch('mobly.controllers.android_device.get_all_instances',
-                return_value=mock_android_device.get_mock_ads(1))
-    def test_run_two_test_classes(self, mock_get_all, mock_list_adb,
-                                  mock_fastboot, mock_adb):
-        """Verifies that running more than one test class in one test run works
-        properly.
+  def test_add_test_class_mismatched_log_path(self):
+    tr = test_runner.TestRunner('/different/log/dir', self.testbed_name)
+    with self.assertRaisesRegex(
+        test_runner.Error,
+        'TestRunner\'s log folder is "/different/log/dir", but a test '
+        r'config with a different log folder \("%s"\) was added.' %
+        re.escape(self.log_dir)):
+      tr.add_test_class(self.base_mock_test_config,
+                integration_test.IntegrationTest)
 
-        This requires using a built-in controller module. Using AndroidDevice
-        module since it has all the mocks needed already.
-        """
-        mock_test_config = self.base_mock_test_config.copy()
-        mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
-        my_config = [{
-            'serial': 'xxxx',
-            'magic': 'Magic1'
-        }, {
-            'serial': 'xxxx',
-            'magic': 'Magic2'
-        }]
-        mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
-        mock_test_config.controller_configs['AndroidDevice'] = [{
-            'serial': '1'
-        }]
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger():
-            tr.add_test_class(mock_test_config,
-                              integration2_test.Integration2Test)
-            tr.add_test_class(mock_test_config,
-                              integration_test.IntegrationTest)
-            tr.run()
-        results = tr.results.summary_dict()
-        self.assertEqual(results['Requested'], 2)
-        self.assertEqual(results['Executed'], 2)
-        self.assertEqual(results['Passed'], 2)
-        self.assertEqual(len(tr.results.executed), 2)
-        # Tag of the test class defaults to the class name.
-        record1 = tr.results.executed[0]
-        record2 = tr.results.executed[1]
-        self.assertEqual(record1.test_class, 'Integration2Test')
-        self.assertEqual(record2.test_class, 'IntegrationTest')
+  def test_add_test_class_mismatched_testbed_name(self):
+    tr = test_runner.TestRunner(self.log_dir, 'different_test_bed')
+    with self.assertRaisesRegex(
+        test_runner.Error,
+        'TestRunner\'s test bed is "different_test_bed", but a test '
+        r'config with a different test bed \("%s"\) was added.' %
+        self.testbed_name):
+      tr.add_test_class(self.base_mock_test_config,
+                integration_test.IntegrationTest)
 
-    def test_run_two_test_classes_different_configs_and_aliases(self):
-        """Verifies that running more than one test class in one test run with
-        different configs works properly.
-        """
-        config1 = self.base_mock_test_config.copy()
-        config1.controller_configs[
-            mock_controller.MOBLY_CONTROLLER_CONFIG_NAME] = [{
-                'serial': 'xxxx'
-            }]
-        config2 = config1.copy()
-        config2.user_params['icecream'] = 10
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger():
-            tr.add_test_class(config1,
-                              integration_test.IntegrationTest,
-                              name_suffix='FirstConfig')
-            tr.add_test_class(config2,
-                              integration_test.IntegrationTest,
-                              name_suffix='SecondConfig')
-            tr.run()
-        results = tr.results.summary_dict()
-        self.assertEqual(results['Requested'], 2)
-        self.assertEqual(results['Executed'], 2)
-        self.assertEqual(results['Passed'], 1)
-        self.assertEqual(results['Failed'], 1)
-        self.assertEqual(tr.results.failed[0].details, '10 != 42')
-        self.assertEqual(len(tr.results.executed), 2)
-        record1 = tr.results.executed[0]
-        record2 = tr.results.executed[1]
-        self.assertEqual(record1.test_class, 'IntegrationTest_FirstConfig')
-        self.assertEqual(record2.test_class, 'IntegrationTest_SecondConfig')
+  def test_run_no_tests(self):
+    tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
+    with self.assertRaisesRegex(test_runner.Error, 'No tests to execute.'):
+      tr.run()
 
-    def test_run_with_abort_all(self):
-        mock_test_config = self.base_mock_test_config.copy()
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with tr.mobly_logger():
-            tr.add_test_class(mock_test_config,
-                              integration3_test.Integration3Test)
-            with self.assertRaises(signals.TestAbortAll):
-                tr.run()
-        results = tr.results.summary_dict()
-        self.assertEqual(results['Requested'], 1)
-        self.assertEqual(results['Executed'], 0)
-        self.assertEqual(results['Passed'], 0)
-        self.assertEqual(results['Failed'], 0)
+  @mock.patch('mobly.test_runner._find_test_class',
+        return_value=type('SampleTest', (), {}))
+  @mock.patch('mobly.test_runner.config_parser.load_test_config_file',
+        return_value=[config_parser.TestRunConfig()])
+  @mock.patch('mobly.test_runner.TestRunner', return_value=mock.MagicMock())
+  def test_main_parse_args(self, mock_test_runner, mock_config,
+               mock_find_test):
+    test_runner.main(['-c', 'some/path/foo.yaml', '-b', 'hello'])
+    mock_config.assert_called_with('some/path/foo.yaml', None)
 
-    def test_add_test_class_mismatched_log_path(self):
-        tr = test_runner.TestRunner('/different/log/dir', self.testbed_name)
-        with self.assertRaisesRegex(
-                test_runner.Error,
-                'TestRunner\'s log folder is "/different/log/dir", but a test '
-                r'config with a different log folder \("%s"\) was added.' %
-                re.escape(self.log_dir)):
-            tr.add_test_class(self.base_mock_test_config,
-                              integration_test.IntegrationTest)
+  @mock.patch('mobly.test_runner._find_test_class',
+        return_value=integration_test.IntegrationTest)
+  @mock.patch('sys.exit')
+  def test_main(self, mock_exit, mock_find_test):
+    tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
+    with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
+      f.write(u"""
+        TestBeds:
+          # A test bed where adb will find Android devices.
+          - Name: SampleTestBed
+            Controllers:
+              MagicDevice: '*'
+            TestParams:
+              icecream: 42
+              extra_param: 'haha'
+      """)
+    test_runner.main(['-c', tmp_file_path])
+    mock_exit.assert_not_called()
 
-    def test_add_test_class_mismatched_testbed_name(self):
-        tr = test_runner.TestRunner(self.log_dir, 'different_test_bed')
-        with self.assertRaisesRegex(
-                test_runner.Error,
-                'TestRunner\'s test bed is "different_test_bed", but a test '
-                r'config with a different test bed \("%s"\) was added.' %
-                self.testbed_name):
-            tr.add_test_class(self.base_mock_test_config,
-                              integration_test.IntegrationTest)
+  @mock.patch('mobly.test_runner._find_test_class',
+        return_value=integration_test.IntegrationTest)
+  @mock.patch('sys.exit')
+  def test_main_with_failures(self, mock_exit, mock_find_test):
+    tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
+    with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
+      f.write(u"""
+        TestBeds:
+          # A test bed where adb will find Android devices.
+          - Name: SampleTestBed
+            Controllers:
+              MagicDevice: '*'
+      """)
+    test_runner.main(['-c', tmp_file_path])
+    mock_exit.assert_called_once_with(1)
 
-    def test_run_no_tests(self):
-        tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
-        with self.assertRaisesRegex(test_runner.Error, 'No tests to execute.'):
-            tr.run()
+  def test__find_test_class_when_one_test_class(self):
+    with mock.patch.dict('sys.modules', __main__=integration_test):
+      test_class = test_runner._find_test_class()
+      self.assertEqual(test_class, integration_test.IntegrationTest)
 
-    @mock.patch('mobly.test_runner._find_test_class',
-                return_value=type('SampleTest', (), {}))
-    @mock.patch('mobly.test_runner.config_parser.load_test_config_file',
-                return_value=[config_parser.TestRunConfig()])
-    @mock.patch('mobly.test_runner.TestRunner', return_value=mock.MagicMock())
-    def test_main_parse_args(self, mock_test_runner, mock_config,
-                             mock_find_test):
-        test_runner.main(['-c', 'some/path/foo.yaml', '-b', 'hello'])
-        mock_config.assert_called_with('some/path/foo.yaml', None)
+  def test__find_test_class_when_no_test_class(self):
+    with self.assertRaises(SystemExit):
+      with mock.patch.dict('sys.modules', __main__=mock_controller):
+        test_class = test_runner._find_test_class()
 
-    @mock.patch('mobly.test_runner._find_test_class',
-                return_value=integration_test.IntegrationTest)
-    @mock.patch('sys.exit')
-    def test_main(self, mock_exit, mock_find_test):
-        tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
-        with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
-            f.write(u"""
-                TestBeds:
-                    # A test bed where adb will find Android devices.
-                    - Name: SampleTestBed
-                      Controllers:
-                          MagicDevice: '*'
-                      TestParams:
-                          icecream: 42
-                          extra_param: 'haha'
-            """)
-        test_runner.main(['-c', tmp_file_path])
-        mock_exit.assert_not_called()
+  def test__find_test_class_when_multiple_test_classes(self):
+    with self.assertRaises(SystemExit):
+      with mock.patch.dict('sys.modules',
+                 __main__=multiple_subclasses_module):
+        test_class = test_runner._find_test_class()
 
-    @mock.patch('mobly.test_runner._find_test_class',
-                return_value=integration_test.IntegrationTest)
-    @mock.patch('sys.exit')
-    def test_main_with_failures(self, mock_exit, mock_find_test):
-        tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
-        with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
-            f.write(u"""
-                TestBeds:
-                    # A test bed where adb will find Android devices.
-                    - Name: SampleTestBed
-                      Controllers:
-                          MagicDevice: '*'
-            """)
-        test_runner.main(['-c', tmp_file_path])
-        mock_exit.assert_called_once_with(1)
+  def test_print_test_names(self):
+    mock_test_class = mock.MagicMock()
+    mock_cls_instance = mock.MagicMock()
+    mock_test_class.return_value = mock_cls_instance
+    test_runner._print_test_names(mock_test_class)
+    mock_cls_instance.setup_generated_tests.assert_called_once()
+    mock_cls_instance.get_existing_test_names.assert_called_once()
+    mock_cls_instance._controller_manager.unregister_controllers.assert_called_once(
+    )
 
-    def test__find_test_class_when_one_test_class(self):
-        with mock.patch.dict('sys.modules', __main__=integration_test):
-            test_class = test_runner._find_test_class()
-            self.assertEqual(test_class, integration_test.IntegrationTest)
-
-    def test__find_test_class_when_no_test_class(self):
-        with self.assertRaises(SystemExit):
-            with mock.patch.dict('sys.modules', __main__=mock_controller):
-                test_class = test_runner._find_test_class()
-
-    def test__find_test_class_when_multiple_test_classes(self):
-        with self.assertRaises(SystemExit):
-            with mock.patch.dict('sys.modules',
-                                 __main__=multiple_subclasses_module):
-                test_class = test_runner._find_test_class()
-
-    def test_print_test_names(self):
-        mock_test_class = mock.MagicMock()
-        mock_cls_instance = mock.MagicMock()
-        mock_test_class.return_value = mock_cls_instance
-        test_runner._print_test_names(mock_test_class)
-        mock_cls_instance.setup_generated_tests.assert_called_once()
-        mock_cls_instance.get_existing_test_names.assert_called_once()
-        mock_cls_instance._controller_manager.unregister_controllers.assert_called_once(
-        )
-
-    def test_print_test_names_with_exception(self):
-        mock_test_class = mock.MagicMock()
-        mock_cls_instance = mock.MagicMock()
-        mock_test_class.return_value = mock_cls_instance
-        test_runner._print_test_names(mock_test_class)
-        mock_cls_instance.setup_generated_tests.side_effect = Exception(
-            'Something went wrong.')
-        mock_cls_instance._controller_manager.unregister_controllers.assert_called_once(
-        )
+  def test_print_test_names_with_exception(self):
+    mock_test_class = mock.MagicMock()
+    mock_cls_instance = mock.MagicMock()
+    mock_test_class.return_value = mock_cls_instance
+    test_runner._print_test_names(mock_test_class)
+    mock_cls_instance.setup_generated_tests.side_effect = Exception(
+      'Something went wrong.')
+    mock_cls_instance._controller_manager.unregister_controllers.assert_called_once(
+    )
 
 
 if __name__ == "__main__":
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/test_suite_test.py b/tests/mobly/test_suite_test.py
index 752cb03..6e52461 100755
--- a/tests/mobly/test_suite_test.py
+++ b/tests/mobly/test_suite_test.py
@@ -29,51 +29,51 @@
 
 
 class TestSuiteTest(unittest.TestCase):
-    """Tests for use cases of creating Mobly test suites.
+  """Tests for use cases of creating Mobly test suites.
 
-    Tests here target a combination of test_runner and base_test code.
-    """
-    def setUp(self):
-        self.tmp_dir = tempfile.mkdtemp()
-        self.mock_test_cls_configs = config_parser.TestRunConfig()
-        self.summary_file = os.path.join(self.tmp_dir, 'summary.yaml')
-        self.mock_test_cls_configs.summary_writer = records.TestSummaryWriter(
-            self.summary_file)
-        self.mock_test_cls_configs.log_path = self.tmp_dir
-        self.mock_test_cls_configs.user_params = {"some_param": "hahaha"}
-        self.mock_test_cls_configs.reporter = mock.MagicMock()
-        self.base_mock_test_config = config_parser.TestRunConfig()
-        self.base_mock_test_config.testbed_name = 'SampleTestBed'
-        self.base_mock_test_config.controller_configs = {}
-        self.base_mock_test_config.user_params = {
-            'icecream': 42,
-            'extra_param': 'haha'
-        }
-        self.base_mock_test_config.log_path = self.tmp_dir
+  Tests here target a combination of test_runner and base_test code.
+  """
+  def setUp(self):
+    self.tmp_dir = tempfile.mkdtemp()
+    self.mock_test_cls_configs = config_parser.TestRunConfig()
+    self.summary_file = os.path.join(self.tmp_dir, 'summary.yaml')
+    self.mock_test_cls_configs.summary_writer = records.TestSummaryWriter(
+      self.summary_file)
+    self.mock_test_cls_configs.log_path = self.tmp_dir
+    self.mock_test_cls_configs.user_params = {"some_param": "hahaha"}
+    self.mock_test_cls_configs.reporter = mock.MagicMock()
+    self.base_mock_test_config = config_parser.TestRunConfig()
+    self.base_mock_test_config.testbed_name = 'SampleTestBed'
+    self.base_mock_test_config.controller_configs = {}
+    self.base_mock_test_config.user_params = {
+      'icecream': 42,
+      'extra_param': 'haha'
+    }
+    self.base_mock_test_config.log_path = self.tmp_dir
 
-    def tearDown(self):
-        shutil.rmtree(self.tmp_dir)
+  def tearDown(self):
+    shutil.rmtree(self.tmp_dir)
 
-    def test_controller_object_not_persistent_across_classes(self):
-        test_run_config = self.base_mock_test_config.copy()
-        test_run_config.controller_configs = {'MagicDevice': [{'serial': 1}]}
+  def test_controller_object_not_persistent_across_classes(self):
+    test_run_config = self.base_mock_test_config.copy()
+    test_run_config.controller_configs = {'MagicDevice': [{'serial': 1}]}
 
-        class FooTest(base_test.BaseTestClass):
-            def setup_class(cls1):
-                self.controller1 = cls1.register_controller(mock_controller)[0]
+    class FooTest(base_test.BaseTestClass):
+      def setup_class(cls1):
+        self.controller1 = cls1.register_controller(mock_controller)[0]
 
-        class BarTest(base_test.BaseTestClass):
-            def setup_class(cls2):
-                self.controller2 = cls2.register_controller(mock_controller)[0]
+    class BarTest(base_test.BaseTestClass):
+      def setup_class(cls2):
+        self.controller2 = cls2.register_controller(mock_controller)[0]
 
-        tr = test_runner.TestRunner(self.tmp_dir,
-                                    test_run_config.testbed_name)
-        with tr.mobly_logger():
-            tr.add_test_class(test_run_config, FooTest)
-            tr.add_test_class(test_run_config, BarTest)
-            tr.run()
-        self.assertIsNot(self.controller1, self.controller2)
+    tr = test_runner.TestRunner(self.tmp_dir,
+                  test_run_config.testbed_name)
+    with tr.mobly_logger():
+      tr.add_test_class(test_run_config, FooTest)
+      tr.add_test_class(test_run_config, BarTest)
+      tr.run()
+    self.assertIsNot(self.controller1, self.controller2)
 
 
 if __name__ == "__main__":
-    unittest.main()
+  unittest.main()
diff --git a/tests/mobly/utils_test.py b/tests/mobly/utils_test.py
index 0b033e3..7f1bf80 100755
--- a/tests/mobly/utils_test.py
+++ b/tests/mobly/utils_test.py
@@ -43,550 +43,550 @@
 
 
 class UtilsTest(unittest.TestCase):
-    """This test class has unit tests for the implementation of everything
-    under mobly.utils.
+  """This test class has unit tests for the implementation of everything
+  under mobly.utils.
+  """
+  def setUp(self):
+    system = platform.system()
+    self.tmp_dir = tempfile.mkdtemp()
+
+  def tearDown(self):
+    shutil.rmtree(self.tmp_dir)
+
+  def sleep_cmd(self, wait_secs):
+    if platform.system() == 'Windows':
+      python_code = ['import time', 'time.sleep(%s)' % wait_secs]
+      return ['python', '-c', 'exec("%s")' % r'\r\n'.join(python_code)]
+    else:
+      return ['sleep', str(wait_secs)]
+
+  def test_run_command(self):
+    (ret, out, err) = utils.run_command(self.sleep_cmd(0.01))
+    self.assertEqual(ret, 0)
+
+  def test_run_command_with_timeout(self):
+    (ret, out, err) = utils.run_command(self.sleep_cmd(0.01), timeout=4)
+    self.assertEqual(ret, 0)
+
+  def test_run_command_with_timeout_expired(self):
+    with self.assertRaises(psutil.TimeoutExpired):
+      _ = utils.run_command(self.sleep_cmd(4), timeout=0.01)
+
+  @mock.patch('threading.Timer')
+  @mock.patch('psutil.Popen')
+  def test_run_command_with_default_params(self, mock_Popen, mock_Timer):
+    mock_command = mock.MagicMock(spec=dict)
+    mock_proc = mock_Popen.return_value
+    mock_proc.communicate.return_value = ('fake_out', 'fake_err')
+    mock_proc.returncode = 0
+    out = utils.run_command(mock_command)
+    self.assertEqual(out, (0, 'fake_out', 'fake_err'))
+    mock_Popen.assert_called_with(
+      mock_command,
+      stdout=subprocess.PIPE,
+      stderr=subprocess.PIPE,
+      shell=False,
+      cwd=None,
+      env=None,
+    )
+    mock_Timer.assert_not_called()
+
+  @mock.patch('threading.Timer')
+  @mock.patch('psutil.Popen')
+  def test_run_command_with_custom_params(self, mock_Popen, mock_Timer):
+    mock_command = mock.MagicMock(spec=dict)
+    mock_stdout = mock.MagicMock(spec=int)
+    mock_stderr = mock.MagicMock(spec=int)
+    mock_shell = mock.MagicMock(spec=bool)
+    mock_timeout = 1234
+    mock_env = mock.MagicMock(spec=dict)
+    mock_proc = mock_Popen.return_value
+    mock_proc.communicate.return_value = ('fake_out', 'fake_err')
+    mock_proc.returncode = 127
+    out = utils.run_command(mock_command,
+                stdout=mock_stdout,
+                stderr=mock_stderr,
+                shell=mock_shell,
+                timeout=mock_timeout,
+                env=mock_env)
+    self.assertEqual(out, (127, 'fake_out', 'fake_err'))
+    mock_Popen.assert_called_with(
+      mock_command,
+      stdout=mock_stdout,
+      stderr=mock_stderr,
+      shell=mock_shell,
+      cwd=None,
+      env=mock_env,
+    )
+    mock_Timer.assert_called_with(1234, mock.ANY)
+
+  def test_start_standing_subproc(self):
+    try:
+      p = utils.start_standing_subprocess(self.sleep_cmd(0.01))
+      p1 = psutil.Process(p.pid)
+      self.assertTrue(p1.is_running())
+    finally:
+      p.stdout.close()
+      p.stderr.close()
+      p.wait()
+
+  @mock.patch('subprocess.Popen')
+  def test_start_standing_subproc_without_env(self, mock_Popen):
+    p = utils.start_standing_subprocess(self.sleep_cmd(0.01))
+    mock_Popen.assert_called_with(
+      self.sleep_cmd(0.01),
+      stdin=subprocess.PIPE,
+      stdout=subprocess.PIPE,
+      stderr=subprocess.PIPE,
+      shell=False,
+      env=None,
+    )
+
+  @mock.patch('subprocess.Popen')
+  def test_start_standing_subproc_with_custom_env(self, mock_Popen):
+    mock_env = mock.MagicMock(spec=dict)
+    p = utils.start_standing_subprocess(self.sleep_cmd(0.01), env=mock_env)
+    mock_Popen.assert_called_with(
+      self.sleep_cmd(0.01),
+      stdin=subprocess.PIPE,
+      stdout=subprocess.PIPE,
+      stderr=subprocess.PIPE,
+      shell=False,
+      env=mock_env,
+    )
+
+  def test_stop_standing_subproc(self):
+    p = utils.start_standing_subprocess(self.sleep_cmd(4))
+    p1 = psutil.Process(p.pid)
+    utils.stop_standing_subprocess(p)
+    self.assertFalse(p1.is_running())
+
+  def test_stop_standing_subproc_wihtout_pipe(self):
+    p = subprocess.Popen(self.sleep_cmd(4))
+    self.assertIsNone(p.stdout)
+    p1 = psutil.Process(p.pid)
+    utils.stop_standing_subprocess(p)
+    self.assertFalse(p1.is_running())
+
+  @unittest.skipIf(sys.version_info >= (3, 4) and sys.version_info < (3, 5),
+           'Python 3.4 does not support `None` max_workers.')
+  def test_concurrent_exec_when_none_workers(self):
+    def adder(a, b):
+      return a + b
+
+    with mock.patch.object(
+        futures, 'ThreadPoolExecutor',
+        wraps=futures.ThreadPoolExecutor) as thread_pool_spy:
+      results = utils.concurrent_exec(adder, [(1, 1), (2, 2)],
+                      max_workers=None)
+
+    thread_pool_spy.assert_called_once_with(max_workers=None)
+
+    self.assertEqual(len(results), 2)
+    self.assertIn(2, results)
+    self.assertIn(4, results)
+
+  def test_concurrent_exec_when_default_max_workers(self):
+    def adder(a, b):
+      return a + b
+
+    with mock.patch.object(
+        futures, 'ThreadPoolExecutor',
+        wraps=futures.ThreadPoolExecutor) as thread_pool_spy:
+      results = utils.concurrent_exec(adder, [(1, 1), (2, 2)])
+
+    thread_pool_spy.assert_called_once_with(max_workers=30)
+
+    self.assertEqual(len(results), 2)
+    self.assertIn(2, results)
+    self.assertIn(4, results)
+
+  def test_concurrent_exec_when_custom_max_workers(self):
+    def adder(a, b):
+      return a + b
+
+    with mock.patch.object(
+        futures, 'ThreadPoolExecutor',
+        wraps=futures.ThreadPoolExecutor) as thread_pool_spy:
+      results = utils.concurrent_exec(adder, [(1, 1), (2, 2)],
+                      max_workers=1)
+
+    thread_pool_spy.assert_called_once_with(max_workers=1)
+    self.assertEqual(len(results), 2)
+    self.assertIn(2, results)
+    self.assertIn(4, results)
+
+  def test_concurrent_exec_makes_all_calls(self):
+    mock_function = mock.MagicMock()
+    _ = utils.concurrent_exec(mock_function, [
+      (1, 1),
+      (2, 2),
+      (3, 3),
+    ])
+    self.assertEqual(mock_function.call_count, 3)
+    mock_function.assert_has_calls(
+      [mock.call(1, 1),
+       mock.call(2, 2),
+       mock.call(3, 3)],
+      any_order=True)
+
+  def test_concurrent_exec_generates_results(self):
+    def adder(a, b):
+      return a + b
+
+    results = utils.concurrent_exec(adder, [(1, 1), (2, 2)])
+    self.assertEqual(len(results), 2)
+    self.assertIn(2, results)
+    self.assertIn(4, results)
+
+  def test_concurrent_exec_when_exception_makes_all_calls(self):
+    mock_call_recorder = mock.MagicMock()
+    lock_call_count = threading.Lock()
+
+    def fake_int(a, ):
+      with lock_call_count:
+        mock_call_recorder(a)
+      return int(a)
+
+    results = utils.concurrent_exec(fake_int, [
+      (1, ),
+      ('123', ),
+      ('not_int', ),
+      (5435, ),
+    ])
+
+    self.assertEqual(mock_call_recorder.call_count, 4)
+    mock_call_recorder.assert_has_calls([
+      mock.call(1),
+      mock.call('123'),
+      mock.call('not_int'),
+      mock.call(5435),
+    ],
+                      any_order=True)
+
+  def test_concurrent_exec_when_exception_generates_results(self):
+    mock_call_recorder = mock.MagicMock()
+    lock_call_count = threading.Lock()
+
+    def fake_int(a, ):
+      with lock_call_count:
+        mock_call_recorder(a)
+      return int(a)
+
+    results = utils.concurrent_exec(fake_int, [
+      (1, ),
+      ('123', ),
+      ('not_int', ),
+      (5435, ),
+    ])
+
+    self.assertEqual(len(results), 4)
+    self.assertIn(1, results)
+    self.assertIn(123, results)
+    self.assertIn(5435, results)
+    exceptions = [
+      result for result in results if isinstance(result, Exception)
+    ]
+    self.assertEqual(len(exceptions), 1)
+    self.assertIsInstance(exceptions[0], ValueError)
+
+  def test_concurrent_exec_when_multiple_exceptions_makes_all_calls(self):
+    mock_call_recorder = mock.MagicMock()
+    lock_call_count = threading.Lock()
+
+    def fake_int(a, ):
+      with lock_call_count:
+        mock_call_recorder(a)
+      return int(a)
+
+    results = utils.concurrent_exec(fake_int, [
+      (1, ),
+      ('not_int1', ),
+      ('not_int2', ),
+      (5435, ),
+    ])
+
+    self.assertEqual(mock_call_recorder.call_count, 4)
+    mock_call_recorder.assert_has_calls([
+      mock.call(1),
+      mock.call('not_int1'),
+      mock.call('not_int2'),
+      mock.call(5435),
+    ],
+                      any_order=True)
+
+  def test_concurrent_exec_when_multiple_exceptions_generates_results(self):
+    mock_call_recorder = mock.MagicMock()
+    lock_call_count = threading.Lock()
+
+    def fake_int(a, ):
+      with lock_call_count:
+        mock_call_recorder(a)
+      return int(a)
+
+    results = utils.concurrent_exec(fake_int, [
+      (1, ),
+      ('not_int1', ),
+      ('not_int2', ),
+      (5435, ),
+    ])
+
+    self.assertEqual(len(results), 4)
+    self.assertIn(1, results)
+    self.assertIn(5435, results)
+    exceptions = [
+      result for result in results if isinstance(result, Exception)
+    ]
+    self.assertEqual(len(exceptions), 2)
+    self.assertIsInstance(exceptions[0], ValueError)
+    self.assertIsInstance(exceptions[1], ValueError)
+    self.assertNotEqual(exceptions[0], exceptions[1])
+
+  def test_concurrent_exec_when_raising_exception_generates_results(self):
+    def adder(a, b):
+      return a + b
+
+    results = utils.concurrent_exec(adder, [(1, 1), (2, 2)],
+                    raise_on_exception=True)
+    self.assertEqual(len(results), 2)
+    self.assertIn(2, results)
+    self.assertIn(4, results)
+
+  def test_concurrent_exec_when_raising_exception_makes_all_calls(self):
+    mock_call_recorder = mock.MagicMock()
+    lock_call_count = threading.Lock()
+
+    def fake_int(a, ):
+      with lock_call_count:
+        mock_call_recorder(a)
+      return int(a)
+
+    with self.assertRaisesRegex(RuntimeError, '.*not_int.*'):
+      _ = utils.concurrent_exec(fake_int, [
+        (1, ),
+        ('123', ),
+        ('not_int', ),
+        (5435, ),
+      ],
+                    raise_on_exception=True)
+
+    self.assertEqual(mock_call_recorder.call_count, 4)
+    mock_call_recorder.assert_has_calls([
+      mock.call(1),
+      mock.call('123'),
+      mock.call('not_int'),
+      mock.call(5435),
+    ],
+                      any_order=True)
+
+  def test_concurrent_exec_when_raising_multiple_exceptions_makes_all_calls(
+      self):
+    mock_call_recorder = mock.MagicMock()
+    lock_call_count = threading.Lock()
+
+    def fake_int(a, ):
+      with lock_call_count:
+        mock_call_recorder(a)
+      return int(a)
+
+    with self.assertRaisesRegex(
+        RuntimeError,
+        r'(?m).*(not_int1(.|\s)+not_int2|not_int2(.|\s)+not_int1).*'):
+      _ = utils.concurrent_exec(fake_int, [
+        (1, ),
+        ('not_int1', ),
+        ('not_int2', ),
+        (5435, ),
+      ],
+                    raise_on_exception=True)
+
+    self.assertEqual(mock_call_recorder.call_count, 4)
+    mock_call_recorder.assert_has_calls([
+      mock.call(1),
+      mock.call('not_int1'),
+      mock.call('not_int2'),
+      mock.call(5435),
+    ],
+                      any_order=True)
+
+  def test_create_dir(self):
+    new_path = os.path.join(self.tmp_dir, 'haha')
+    self.assertFalse(os.path.exists(new_path))
+    utils.create_dir(new_path)
+    self.assertTrue(os.path.exists(new_path))
+
+  def test_create_dir_already_exists(self):
+    self.assertTrue(os.path.exists(self.tmp_dir))
+    utils.create_dir(self.tmp_dir)
+    self.assertTrue(os.path.exists(self.tmp_dir))
+
+  @mock.patch(
+    'mobly.controllers.android_device_lib.adb.list_occupied_adb_ports')
+  @mock.patch('portpicker.PickUnusedPort', return_value=MOCK_AVAILABLE_PORT)
+  def test_get_available_port_positive(self, mock_list_occupied_adb_ports,
+                     mock_pick_unused_port):
+    self.assertEqual(utils.get_available_host_port(), MOCK_AVAILABLE_PORT)
+
+  @mock.patch(
+    'mobly.controllers.android_device_lib.adb.list_occupied_adb_ports',
+    return_value=[MOCK_AVAILABLE_PORT])
+  @mock.patch('portpicker.PickUnusedPort', return_value=MOCK_AVAILABLE_PORT)
+  def test_get_available_port_negative(self, mock_list_occupied_adb_ports,
+                     mock_pick_unused_port):
+    with self.assertRaisesRegex(utils.Error, 'Failed to find.* retries'):
+      utils.get_available_host_port()
+
+  @mock.patch(
+    'mobly.controllers.android_device_lib.adb.list_occupied_adb_ports')
+  def test_get_available_port_returns_free_port(
+      self, mock_list_occupied_adb_ports):
+    """Verifies logic to pick a free port on the host.
+
+    Test checks we can bind to either an ipv4 or ipv6 socket on the port
+    returned by get_available_host_port.
     """
-    def setUp(self):
-        system = platform.system()
-        self.tmp_dir = tempfile.mkdtemp()
+    port = utils.get_available_host_port()
+    got_socket = False
+    for family in (socket.AF_INET, socket.AF_INET6):
+      try:
+        s = socket.socket(family, socket.SOCK_STREAM)
+        got_socket = True
+        break
+      except socket.error:
+        continue
+    self.assertTrue(got_socket)
+    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+    try:
+      s.bind(('localhost', port))
+    finally:
+      s.close()
 
-    def tearDown(self):
-        shutil.rmtree(self.tmp_dir)
+  def test_load_file_to_base64_str_reads_bytes_file_as_base64_string(self):
+    tmp_file_path = os.path.join(self.tmp_dir, 'b64.bin')
+    expected_base64_encoding = u'SGVsbG93IHdvcmxkIQ=='
+    with io.open(tmp_file_path, 'wb') as f:
+      f.write(b'Hellow world!')
+    self.assertEqual(utils.load_file_to_base64_str(tmp_file_path),
+             expected_base64_encoding)
 
-    def sleep_cmd(self, wait_secs):
-        if platform.system() == 'Windows':
-            python_code = ['import time', 'time.sleep(%s)' % wait_secs]
-            return ['python', '-c', 'exec("%s")' % r'\r\n'.join(python_code)]
-        else:
-            return ['sleep', str(wait_secs)]
+  def test_load_file_to_base64_str_reads_text_file_as_base64_string(self):
+    tmp_file_path = os.path.join(self.tmp_dir, 'b64.bin')
+    expected_base64_encoding = u'SGVsbG93IHdvcmxkIQ=='
+    with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
+      f.write(u'Hellow world!')
+    self.assertEqual(utils.load_file_to_base64_str(tmp_file_path),
+             expected_base64_encoding)
 
-    def test_run_command(self):
-        (ret, out, err) = utils.run_command(self.sleep_cmd(0.01))
-        self.assertEqual(ret, 0)
+  def test_load_file_to_base64_str_reads_unicode_file_as_base64_string(self):
+    tmp_file_path = os.path.join(self.tmp_dir, 'b64.bin')
+    expected_base64_encoding = u'6YCa'
+    with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
+      f.write(u'\u901a')
+    self.assertEqual(utils.load_file_to_base64_str(tmp_file_path),
+             expected_base64_encoding)
 
-    def test_run_command_with_timeout(self):
-        (ret, out, err) = utils.run_command(self.sleep_cmd(0.01), timeout=4)
-        self.assertEqual(ret, 0)
+  def test_cli_cmd_to_string(self):
+    cmd = ['"adb"', 'a b', 'c//']
+    self.assertEqual(utils.cli_cmd_to_string(cmd), '\'"adb"\' \'a b\' c//')
+    cmd = 'adb -s meme do something ab_cd'
+    self.assertEqual(utils.cli_cmd_to_string(cmd), cmd)
 
-    def test_run_command_with_timeout_expired(self):
-        with self.assertRaises(psutil.TimeoutExpired):
-            _ = utils.run_command(self.sleep_cmd(4), timeout=0.01)
+  def test_get_settable_properties(self):
+    class SomeClass(object):
+      regular_attr = 'regular_attr'
+      _foo = 'foo'
+      _bar = 'bar'
 
-    @mock.patch('threading.Timer')
-    @mock.patch('psutil.Popen')
-    def test_run_command_with_default_params(self, mock_Popen, mock_Timer):
-        mock_command = mock.MagicMock(spec=dict)
-        mock_proc = mock_Popen.return_value
-        mock_proc.communicate.return_value = ('fake_out', 'fake_err')
-        mock_proc.returncode = 0
-        out = utils.run_command(mock_command)
-        self.assertEqual(out, (0, 'fake_out', 'fake_err'))
-        mock_Popen.assert_called_with(
-            mock_command,
-            stdout=subprocess.PIPE,
-            stderr=subprocess.PIPE,
-            shell=False,
-            cwd=None,
-            env=None,
-        )
-        mock_Timer.assert_not_called()
+      @property
+      def settable_prop(self):
+        return self._foo
 
-    @mock.patch('threading.Timer')
-    @mock.patch('psutil.Popen')
-    def test_run_command_with_custom_params(self, mock_Popen, mock_Timer):
-        mock_command = mock.MagicMock(spec=dict)
-        mock_stdout = mock.MagicMock(spec=int)
-        mock_stderr = mock.MagicMock(spec=int)
-        mock_shell = mock.MagicMock(spec=bool)
-        mock_timeout = 1234
-        mock_env = mock.MagicMock(spec=dict)
-        mock_proc = mock_Popen.return_value
-        mock_proc.communicate.return_value = ('fake_out', 'fake_err')
-        mock_proc.returncode = 127
-        out = utils.run_command(mock_command,
-                                stdout=mock_stdout,
-                                stderr=mock_stderr,
-                                shell=mock_shell,
-                                timeout=mock_timeout,
-                                env=mock_env)
-        self.assertEqual(out, (127, 'fake_out', 'fake_err'))
-        mock_Popen.assert_called_with(
-            mock_command,
-            stdout=mock_stdout,
-            stderr=mock_stderr,
-            shell=mock_shell,
-            cwd=None,
-            env=mock_env,
-        )
-        mock_Timer.assert_called_with(1234, mock.ANY)
+      @settable_prop.setter
+      def settable_prop(self, new_foo):
+        self._foo = new_foo
 
-    def test_start_standing_subproc(self):
-        try:
-            p = utils.start_standing_subprocess(self.sleep_cmd(0.01))
-            p1 = psutil.Process(p.pid)
-            self.assertTrue(p1.is_running())
-        finally:
-            p.stdout.close()
-            p.stderr.close()
-            p.wait()
+      @property
+      def readonly_prop(self):
+        return self._bar
 
-    @mock.patch('subprocess.Popen')
-    def test_start_standing_subproc_without_env(self, mock_Popen):
-        p = utils.start_standing_subprocess(self.sleep_cmd(0.01))
-        mock_Popen.assert_called_with(
-            self.sleep_cmd(0.01),
-            stdin=subprocess.PIPE,
-            stdout=subprocess.PIPE,
-            stderr=subprocess.PIPE,
-            shell=False,
-            env=None,
-        )
+      def func(self):
+        """Func should not be considered as a settable prop."""
 
-    @mock.patch('subprocess.Popen')
-    def test_start_standing_subproc_with_custom_env(self, mock_Popen):
-        mock_env = mock.MagicMock(spec=dict)
-        p = utils.start_standing_subprocess(self.sleep_cmd(0.01), env=mock_env)
-        mock_Popen.assert_called_with(
-            self.sleep_cmd(0.01),
-            stdin=subprocess.PIPE,
-            stdout=subprocess.PIPE,
-            stderr=subprocess.PIPE,
-            shell=False,
-            env=mock_env,
-        )
+    actual = utils.get_settable_properties(SomeClass)
+    self.assertEqual(actual, ['settable_prop'])
 
-    def test_stop_standing_subproc(self):
-        p = utils.start_standing_subprocess(self.sleep_cmd(4))
-        p1 = psutil.Process(p.pid)
-        utils.stop_standing_subprocess(p)
-        self.assertFalse(p1.is_running())
+  def test_find_subclasses_in_module_when_one_subclass(self):
+    subclasses = utils.find_subclasses_in_module([base_test.BaseTestClass],
+                           integration_test)
+    self.assertEqual(len(subclasses), 1)
+    self.assertEqual(subclasses[0], integration_test.IntegrationTest)
 
-    def test_stop_standing_subproc_wihtout_pipe(self):
-        p = subprocess.Popen(self.sleep_cmd(4))
-        self.assertIsNone(p.stdout)
-        p1 = psutil.Process(p.pid)
-        utils.stop_standing_subprocess(p)
-        self.assertFalse(p1.is_running())
+  def test_find_subclasses_in_module_when_indirect_subclass(self):
+    subclasses = utils.find_subclasses_in_module([base_test.BaseTestClass],
+                           mock_instrumentation_test)
+    self.assertEqual(len(subclasses), 1)
+    self.assertEqual(subclasses[0],
+             mock_instrumentation_test.MockInstrumentationTest)
 
-    @unittest.skipIf(sys.version_info >= (3, 4) and sys.version_info < (3, 5),
-                     'Python 3.4 does not support `None` max_workers.')
-    def test_concurrent_exec_when_none_workers(self):
-        def adder(a, b):
-            return a + b
+  def test_find_subclasses_in_module_when_no_subclasses(self):
+    subclasses = utils.find_subclasses_in_module([base_test.BaseTestClass],
+                           mock_controller)
+    self.assertEqual(len(subclasses), 0)
 
-        with mock.patch.object(
-                futures, 'ThreadPoolExecutor',
-                wraps=futures.ThreadPoolExecutor) as thread_pool_spy:
-            results = utils.concurrent_exec(adder, [(1, 1), (2, 2)],
-                                            max_workers=None)
+  def test_find_subclasses_in_module_when_multiple_subclasses(self):
+    subclasses = utils.find_subclasses_in_module(
+      [base_test.BaseTestClass], multiple_subclasses_module)
+    self.assertEqual(len(subclasses), 2)
+    self.assertIn(multiple_subclasses_module.Subclass1Test, subclasses)
+    self.assertIn(multiple_subclasses_module.Subclass2Test, subclasses)
 
-        thread_pool_spy.assert_called_once_with(max_workers=None)
+  def test_find_subclasses_in_module_when_multiple_base_classes(self):
+    subclasses = utils.find_subclasses_in_module(
+      [base_test.BaseTestClass, test_runner.TestRunner],
+      multiple_subclasses_module)
+    self.assertEqual(len(subclasses), 4)
+    self.assertIn(multiple_subclasses_module.Subclass1Test, subclasses)
+    self.assertIn(multiple_subclasses_module.Subclass2Test, subclasses)
+    self.assertIn(multiple_subclasses_module.Subclass1Runner, subclasses)
+    self.assertIn(multiple_subclasses_module.Subclass2Runner, subclasses)
 
-        self.assertEqual(len(results), 2)
-        self.assertIn(2, results)
-        self.assertIn(4, results)
+  def test_find_subclasses_in_module_when_only_some_base_classes_present(
+      self):
+    subclasses = utils.find_subclasses_in_module(
+      [signals.TestSignal, test_runner.TestRunner],
+      multiple_subclasses_module)
+    self.assertEqual(len(subclasses), 2)
+    self.assertIn(multiple_subclasses_module.Subclass1Runner, subclasses)
+    self.assertIn(multiple_subclasses_module.Subclass2Runner, subclasses)
 
-    def test_concurrent_exec_when_default_max_workers(self):
-        def adder(a, b):
-            return a + b
+  def test_find_subclass_in_module_when_one_subclass(self):
+    subclass = utils.find_subclass_in_module(base_test.BaseTestClass,
+                         integration_test)
+    self.assertEqual(subclass, integration_test.IntegrationTest)
 
-        with mock.patch.object(
-                futures, 'ThreadPoolExecutor',
-                wraps=futures.ThreadPoolExecutor) as thread_pool_spy:
-            results = utils.concurrent_exec(adder, [(1, 1), (2, 2)])
+  def test_find_subclass_in_module_when_indirect_subclass(self):
+    subclass = utils.find_subclass_in_module(base_test.BaseTestClass,
+                         mock_instrumentation_test)
+    self.assertEqual(subclass,
+             mock_instrumentation_test.MockInstrumentationTest)
 
-        thread_pool_spy.assert_called_once_with(max_workers=30)
+  def test_find_subclass_in_module_when_no_subclasses(self):
+    with self.assertRaisesRegex(
+        ValueError,
+        '.*Expected 1 subclass of BaseTestClass per module, found'
+        r' \[\].*'):
+      _ = utils.find_subclass_in_module(base_test.BaseTestClass,
+                        mock_controller)
 
-        self.assertEqual(len(results), 2)
-        self.assertIn(2, results)
-        self.assertIn(4, results)
-
-    def test_concurrent_exec_when_custom_max_workers(self):
-        def adder(a, b):
-            return a + b
-
-        with mock.patch.object(
-                futures, 'ThreadPoolExecutor',
-                wraps=futures.ThreadPoolExecutor) as thread_pool_spy:
-            results = utils.concurrent_exec(adder, [(1, 1), (2, 2)],
-                                            max_workers=1)
-
-        thread_pool_spy.assert_called_once_with(max_workers=1)
-        self.assertEqual(len(results), 2)
-        self.assertIn(2, results)
-        self.assertIn(4, results)
-
-    def test_concurrent_exec_makes_all_calls(self):
-        mock_function = mock.MagicMock()
-        _ = utils.concurrent_exec(mock_function, [
-            (1, 1),
-            (2, 2),
-            (3, 3),
-        ])
-        self.assertEqual(mock_function.call_count, 3)
-        mock_function.assert_has_calls(
-            [mock.call(1, 1),
-             mock.call(2, 2),
-             mock.call(3, 3)],
-            any_order=True)
-
-    def test_concurrent_exec_generates_results(self):
-        def adder(a, b):
-            return a + b
-
-        results = utils.concurrent_exec(adder, [(1, 1), (2, 2)])
-        self.assertEqual(len(results), 2)
-        self.assertIn(2, results)
-        self.assertIn(4, results)
-
-    def test_concurrent_exec_when_exception_makes_all_calls(self):
-        mock_call_recorder = mock.MagicMock()
-        lock_call_count = threading.Lock()
-
-        def fake_int(a, ):
-            with lock_call_count:
-                mock_call_recorder(a)
-            return int(a)
-
-        results = utils.concurrent_exec(fake_int, [
-            (1, ),
-            ('123', ),
-            ('not_int', ),
-            (5435, ),
-        ])
-
-        self.assertEqual(mock_call_recorder.call_count, 4)
-        mock_call_recorder.assert_has_calls([
-            mock.call(1),
-            mock.call('123'),
-            mock.call('not_int'),
-            mock.call(5435),
-        ],
-                                            any_order=True)
-
-    def test_concurrent_exec_when_exception_generates_results(self):
-        mock_call_recorder = mock.MagicMock()
-        lock_call_count = threading.Lock()
-
-        def fake_int(a, ):
-            with lock_call_count:
-                mock_call_recorder(a)
-            return int(a)
-
-        results = utils.concurrent_exec(fake_int, [
-            (1, ),
-            ('123', ),
-            ('not_int', ),
-            (5435, ),
-        ])
-
-        self.assertEqual(len(results), 4)
-        self.assertIn(1, results)
-        self.assertIn(123, results)
-        self.assertIn(5435, results)
-        exceptions = [
-            result for result in results if isinstance(result, Exception)
-        ]
-        self.assertEqual(len(exceptions), 1)
-        self.assertIsInstance(exceptions[0], ValueError)
-
-    def test_concurrent_exec_when_multiple_exceptions_makes_all_calls(self):
-        mock_call_recorder = mock.MagicMock()
-        lock_call_count = threading.Lock()
-
-        def fake_int(a, ):
-            with lock_call_count:
-                mock_call_recorder(a)
-            return int(a)
-
-        results = utils.concurrent_exec(fake_int, [
-            (1, ),
-            ('not_int1', ),
-            ('not_int2', ),
-            (5435, ),
-        ])
-
-        self.assertEqual(mock_call_recorder.call_count, 4)
-        mock_call_recorder.assert_has_calls([
-            mock.call(1),
-            mock.call('not_int1'),
-            mock.call('not_int2'),
-            mock.call(5435),
-        ],
-                                            any_order=True)
-
-    def test_concurrent_exec_when_multiple_exceptions_generates_results(self):
-        mock_call_recorder = mock.MagicMock()
-        lock_call_count = threading.Lock()
-
-        def fake_int(a, ):
-            with lock_call_count:
-                mock_call_recorder(a)
-            return int(a)
-
-        results = utils.concurrent_exec(fake_int, [
-            (1, ),
-            ('not_int1', ),
-            ('not_int2', ),
-            (5435, ),
-        ])
-
-        self.assertEqual(len(results), 4)
-        self.assertIn(1, results)
-        self.assertIn(5435, results)
-        exceptions = [
-            result for result in results if isinstance(result, Exception)
-        ]
-        self.assertEqual(len(exceptions), 2)
-        self.assertIsInstance(exceptions[0], ValueError)
-        self.assertIsInstance(exceptions[1], ValueError)
-        self.assertNotEqual(exceptions[0], exceptions[1])
-
-    def test_concurrent_exec_when_raising_exception_generates_results(self):
-        def adder(a, b):
-            return a + b
-
-        results = utils.concurrent_exec(adder, [(1, 1), (2, 2)],
-                                        raise_on_exception=True)
-        self.assertEqual(len(results), 2)
-        self.assertIn(2, results)
-        self.assertIn(4, results)
-
-    def test_concurrent_exec_when_raising_exception_makes_all_calls(self):
-        mock_call_recorder = mock.MagicMock()
-        lock_call_count = threading.Lock()
-
-        def fake_int(a, ):
-            with lock_call_count:
-                mock_call_recorder(a)
-            return int(a)
-
-        with self.assertRaisesRegex(RuntimeError, '.*not_int.*'):
-            _ = utils.concurrent_exec(fake_int, [
-                (1, ),
-                ('123', ),
-                ('not_int', ),
-                (5435, ),
-            ],
-                                      raise_on_exception=True)
-
-        self.assertEqual(mock_call_recorder.call_count, 4)
-        mock_call_recorder.assert_has_calls([
-            mock.call(1),
-            mock.call('123'),
-            mock.call('not_int'),
-            mock.call(5435),
-        ],
-                                            any_order=True)
-
-    def test_concurrent_exec_when_raising_multiple_exceptions_makes_all_calls(
-            self):
-        mock_call_recorder = mock.MagicMock()
-        lock_call_count = threading.Lock()
-
-        def fake_int(a, ):
-            with lock_call_count:
-                mock_call_recorder(a)
-            return int(a)
-
-        with self.assertRaisesRegex(
-                RuntimeError,
-                r'(?m).*(not_int1(.|\s)+not_int2|not_int2(.|\s)+not_int1).*'):
-            _ = utils.concurrent_exec(fake_int, [
-                (1, ),
-                ('not_int1', ),
-                ('not_int2', ),
-                (5435, ),
-            ],
-                                      raise_on_exception=True)
-
-        self.assertEqual(mock_call_recorder.call_count, 4)
-        mock_call_recorder.assert_has_calls([
-            mock.call(1),
-            mock.call('not_int1'),
-            mock.call('not_int2'),
-            mock.call(5435),
-        ],
-                                            any_order=True)
-
-    def test_create_dir(self):
-        new_path = os.path.join(self.tmp_dir, 'haha')
-        self.assertFalse(os.path.exists(new_path))
-        utils.create_dir(new_path)
-        self.assertTrue(os.path.exists(new_path))
-
-    def test_create_dir_already_exists(self):
-        self.assertTrue(os.path.exists(self.tmp_dir))
-        utils.create_dir(self.tmp_dir)
-        self.assertTrue(os.path.exists(self.tmp_dir))
-
-    @mock.patch(
-        'mobly.controllers.android_device_lib.adb.list_occupied_adb_ports')
-    @mock.patch('portpicker.PickUnusedPort', return_value=MOCK_AVAILABLE_PORT)
-    def test_get_available_port_positive(self, mock_list_occupied_adb_ports,
-                                         mock_pick_unused_port):
-        self.assertEqual(utils.get_available_host_port(), MOCK_AVAILABLE_PORT)
-
-    @mock.patch(
-        'mobly.controllers.android_device_lib.adb.list_occupied_adb_ports',
-        return_value=[MOCK_AVAILABLE_PORT])
-    @mock.patch('portpicker.PickUnusedPort', return_value=MOCK_AVAILABLE_PORT)
-    def test_get_available_port_negative(self, mock_list_occupied_adb_ports,
-                                         mock_pick_unused_port):
-        with self.assertRaisesRegex(utils.Error, 'Failed to find.* retries'):
-            utils.get_available_host_port()
-
-    @mock.patch(
-        'mobly.controllers.android_device_lib.adb.list_occupied_adb_ports')
-    def test_get_available_port_returns_free_port(
-            self, mock_list_occupied_adb_ports):
-        """Verifies logic to pick a free port on the host.
-
-        Test checks we can bind to either an ipv4 or ipv6 socket on the port
-        returned by get_available_host_port.
-        """
-        port = utils.get_available_host_port()
-        got_socket = False
-        for family in (socket.AF_INET, socket.AF_INET6):
-            try:
-                s = socket.socket(family, socket.SOCK_STREAM)
-                got_socket = True
-                break
-            except socket.error:
-                continue
-        self.assertTrue(got_socket)
-        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        try:
-            s.bind(('localhost', port))
-        finally:
-            s.close()
-
-    def test_load_file_to_base64_str_reads_bytes_file_as_base64_string(self):
-        tmp_file_path = os.path.join(self.tmp_dir, 'b64.bin')
-        expected_base64_encoding = u'SGVsbG93IHdvcmxkIQ=='
-        with io.open(tmp_file_path, 'wb') as f:
-            f.write(b'Hellow world!')
-        self.assertEqual(utils.load_file_to_base64_str(tmp_file_path),
-                         expected_base64_encoding)
-
-    def test_load_file_to_base64_str_reads_text_file_as_base64_string(self):
-        tmp_file_path = os.path.join(self.tmp_dir, 'b64.bin')
-        expected_base64_encoding = u'SGVsbG93IHdvcmxkIQ=='
-        with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
-            f.write(u'Hellow world!')
-        self.assertEqual(utils.load_file_to_base64_str(tmp_file_path),
-                         expected_base64_encoding)
-
-    def test_load_file_to_base64_str_reads_unicode_file_as_base64_string(self):
-        tmp_file_path = os.path.join(self.tmp_dir, 'b64.bin')
-        expected_base64_encoding = u'6YCa'
-        with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
-            f.write(u'\u901a')
-        self.assertEqual(utils.load_file_to_base64_str(tmp_file_path),
-                         expected_base64_encoding)
-
-    def test_cli_cmd_to_string(self):
-        cmd = ['"adb"', 'a b', 'c//']
-        self.assertEqual(utils.cli_cmd_to_string(cmd), '\'"adb"\' \'a b\' c//')
-        cmd = 'adb -s meme do something ab_cd'
-        self.assertEqual(utils.cli_cmd_to_string(cmd), cmd)
-
-    def test_get_settable_properties(self):
-        class SomeClass(object):
-            regular_attr = 'regular_attr'
-            _foo = 'foo'
-            _bar = 'bar'
-
-            @property
-            def settable_prop(self):
-                return self._foo
-
-            @settable_prop.setter
-            def settable_prop(self, new_foo):
-                self._foo = new_foo
-
-            @property
-            def readonly_prop(self):
-                return self._bar
-
-            def func(self):
-                """Func should not be considered as a settable prop."""
-
-        actual = utils.get_settable_properties(SomeClass)
-        self.assertEqual(actual, ['settable_prop'])
-
-    def test_find_subclasses_in_module_when_one_subclass(self):
-        subclasses = utils.find_subclasses_in_module([base_test.BaseTestClass],
-                                                     integration_test)
-        self.assertEqual(len(subclasses), 1)
-        self.assertEqual(subclasses[0], integration_test.IntegrationTest)
-
-    def test_find_subclasses_in_module_when_indirect_subclass(self):
-        subclasses = utils.find_subclasses_in_module([base_test.BaseTestClass],
-                                                     mock_instrumentation_test)
-        self.assertEqual(len(subclasses), 1)
-        self.assertEqual(subclasses[0],
-                         mock_instrumentation_test.MockInstrumentationTest)
-
-    def test_find_subclasses_in_module_when_no_subclasses(self):
-        subclasses = utils.find_subclasses_in_module([base_test.BaseTestClass],
-                                                     mock_controller)
-        self.assertEqual(len(subclasses), 0)
-
-    def test_find_subclasses_in_module_when_multiple_subclasses(self):
-        subclasses = utils.find_subclasses_in_module(
-            [base_test.BaseTestClass], multiple_subclasses_module)
-        self.assertEqual(len(subclasses), 2)
-        self.assertIn(multiple_subclasses_module.Subclass1Test, subclasses)
-        self.assertIn(multiple_subclasses_module.Subclass2Test, subclasses)
-
-    def test_find_subclasses_in_module_when_multiple_base_classes(self):
-        subclasses = utils.find_subclasses_in_module(
-            [base_test.BaseTestClass, test_runner.TestRunner],
-            multiple_subclasses_module)
-        self.assertEqual(len(subclasses), 4)
-        self.assertIn(multiple_subclasses_module.Subclass1Test, subclasses)
-        self.assertIn(multiple_subclasses_module.Subclass2Test, subclasses)
-        self.assertIn(multiple_subclasses_module.Subclass1Runner, subclasses)
-        self.assertIn(multiple_subclasses_module.Subclass2Runner, subclasses)
-
-    def test_find_subclasses_in_module_when_only_some_base_classes_present(
-            self):
-        subclasses = utils.find_subclasses_in_module(
-            [signals.TestSignal, test_runner.TestRunner],
-            multiple_subclasses_module)
-        self.assertEqual(len(subclasses), 2)
-        self.assertIn(multiple_subclasses_module.Subclass1Runner, subclasses)
-        self.assertIn(multiple_subclasses_module.Subclass2Runner, subclasses)
-
-    def test_find_subclass_in_module_when_one_subclass(self):
-        subclass = utils.find_subclass_in_module(base_test.BaseTestClass,
-                                                 integration_test)
-        self.assertEqual(subclass, integration_test.IntegrationTest)
-
-    def test_find_subclass_in_module_when_indirect_subclass(self):
-        subclass = utils.find_subclass_in_module(base_test.BaseTestClass,
-                                                 mock_instrumentation_test)
-        self.assertEqual(subclass,
-                         mock_instrumentation_test.MockInstrumentationTest)
-
-    def test_find_subclass_in_module_when_no_subclasses(self):
-        with self.assertRaisesRegex(
-                ValueError,
-                '.*Expected 1 subclass of BaseTestClass per module, found'
-                r' \[\].*'):
-            _ = utils.find_subclass_in_module(base_test.BaseTestClass,
-                                              mock_controller)
-
-    def test_find_subclass_in_module_when_multiple_subclasses(self):
-        with self.assertRaisesRegex(
-                ValueError,
-                '.*Expected 1 subclass of BaseTestClass per module, found'
-                r' \[(\'Subclass1Test\', \'Subclass2Test\''
-                r'|\'Subclass2Test\', \'Subclass1Test\')\].*'):
-            _ = utils.find_subclass_in_module(base_test.BaseTestClass,
-                                              multiple_subclasses_module)
+  def test_find_subclass_in_module_when_multiple_subclasses(self):
+    with self.assertRaisesRegex(
+        ValueError,
+        '.*Expected 1 subclass of BaseTestClass per module, found'
+        r' \[(\'Subclass1Test\', \'Subclass2Test\''
+        r'|\'Subclass2Test\', \'Subclass1Test\')\].*'):
+      _ = utils.find_subclass_in_module(base_test.BaseTestClass,
+                        multiple_subclasses_module)
 
 
 if __name__ == '__main__':
-    unittest.main()
+  unittest.main()