diff --git a/mobly/controllers/android_device_lib/adb.py b/mobly/controllers/android_device_lib/adb.py
index 41af20c..15e2a5c 100644
--- a/mobly/controllers/android_device_lib/adb.py
+++ b/mobly/controllers/android_device_lib/adb.py
@@ -44,13 +44,17 @@ class AdbError(Error):
         stdout: byte string, the raw stdout of the command.
         stderr: byte string, the raw stderr of the command.
         ret_code: int, the return code of the command.
+        serial: string, the serial of the device the command is executed on.
+            This is an empty string if the adb command is not specific to a
+            device.
     """
 
-    def __init__(self, cmd, stdout, stderr, ret_code):
+    def __init__(self, cmd, stdout, stderr, ret_code, serial=''):
         self.cmd = cmd
         self.stdout = stdout
         self.stderr = stderr
         self.ret_code = ret_code
+        self.serial = serial
 
     def __str__(self):
         return ('Error executing adb cmd "%s". ret: %d, stdout: %s, stderr: %s'
@@ -64,11 +68,15 @@ class AdbTimeoutError(Error):
     Args:
         cmd: list of strings, the adb command that timed out
         timeout: float, the number of seconds passed before timing out.
+        serial: string, the serial of the device the command is executed on.
+            This is an empty string if the adb command is not specific to a
+            device.
     """
 
-    def __init__(self, cmd, timeout):
+    def __init__(self, cmd, timeout, serial=''):
         self.cmd = cmd
         self.timeout = timeout
+        self.serial = serial
 
     def __str__(self):
         return 'Timed out executing command "%s" after %ss.' % (
@@ -155,6 +163,7 @@ class AdbProxy(object):
             The output of the adb command run if exit code is 0.
 
         Raises:
+            ValueError: timeout value is invalid.
             AdbError: The adb command exit code is not 0.
             AdbTimeoutError: The adb command timed out.
         """
@@ -162,13 +171,14 @@ class AdbProxy(object):
             args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=shell)
         process = psutil.Process(proc.pid)
         if timeout and timeout <= 0:
-            raise Error('Timeout is not a positive value: %s' % timeout)
+            raise ValueError('Timeout is not a positive value: %s' % timeout)
         if timeout and timeout > 0:
             try:
                 process.wait(timeout=timeout)
             except psutil.TimeoutExpired:
                 process.terminate()
-                raise AdbTimeoutError(cmd=args, timeout=timeout)
+                raise AdbTimeoutError(
+                    cmd=args, timeout=timeout, serial=self.serial)
 
         (out, err) = proc.communicate()
         if stderr:
@@ -179,7 +189,12 @@ class AdbProxy(object):
         if ret == 0:
             return out
         else:
-            raise AdbError(cmd=args, stdout=out, stderr=err, ret_code=ret)
+            raise AdbError(
+                cmd=args,
+                stdout=out,
+                stderr=err,
+                ret_code=ret,
+                serial=self.serial)
 
     def _execute_and_process_stdout(self, args, shell, handler):
         """Executes adb commands and processes the stdout with a handler.
diff --git a/mobly/utils.py b/mobly/utils.py
index a9f065c..bb2f316 100644
--- a/mobly/utils.py
+++ b/mobly/utils.py
@@ -283,7 +283,7 @@ def concurrent_exec(func, param_list):
         return return_vals
 
 
-def start_standing_subprocess(cmd, shell=False):
+def start_standing_subprocess(cmd, shell=False, env=None):
     """Starts a long-running subprocess.
 
     This is not a blocking call and the subprocess started by it should be
@@ -296,6 +296,9 @@ def start_standing_subprocess(cmd, shell=False):
         cmd: string, the command to start the subprocess with.
         shell: bool, True to run this command through the system shell,
             False to invoke it directly. See subprocess.Proc() docs.
+        env: dict, a custom environment to run the standing subprocess. If not
+            specified, inherits the current environment. See subprocess.Popen()
+            docs.
 
     Returns:
         The subprocess that was started.
@@ -306,7 +309,8 @@ def start_standing_subprocess(cmd, shell=False):
         stdin=subprocess.PIPE,
         stdout=subprocess.PIPE,
         stderr=subprocess.PIPE,
-        shell=shell)
+        shell=shell,
+        env=env)
     # Leaving stdin open causes problems for input, e.g. breaking the
     # code.inspect() shell (http://stackoverflow.com/a/25512460/1612937), so
     # explicitly close it assuming it is not needed for standing subprocesses.

`expects` APIs crash in execution stages before the test case
In `setup_class` and `setup_generated_tests`, calling `expects` APIs would cause crashes.
Also in `teardown_class`, `expects` APIs would probably attach errors to the wrong record.
diff --git a/mobly/base_test.py b/mobly/base_test.py
index 03db500..56d8d4e 100644
--- a/mobly/base_test.py
+++ b/mobly/base_test.py
@@ -292,9 +292,46 @@ class BaseTestClass(object):
     def _setup_class(self):
         """Proxy function to guarantee the base implementation of setup_class
         is called.
+
+        Returns:
+            If `self.results` is returned instead of None, this means something
+            has gone wrong, and the rest of the test class should not execute.
         """
-        with self._log_test_stage(STAGE_NAME_SETUP_CLASS):
-            self.setup_class()
+        # Setup for the class.
+        class_record = records.TestResultRecord(STAGE_NAME_SETUP_CLASS,
+                                                self.TAG)
+        class_record.test_begin()
+        self.current_test_info = runtime_test_info.RuntimeTestInfo(
+            STAGE_NAME_SETUP_CLASS, self.log_path, class_record)
+        expects.recorder.reset_internal_states(class_record)
+        try:
+            with self._log_test_stage(STAGE_NAME_SETUP_CLASS):
+                self.setup_class()
+        except signals.TestAbortSignal:
+            # Throw abort signals to outer try block for handling.
+            raise
+        except Exception as e:
+            # Setup class failed for unknown reasons.
+            # Fail the class and skip all tests.
+            logging.exception('Error in %s#setup_class.', self.TAG)
+            class_record.test_error(e)
+            self.results.add_class_error(class_record)
+            self._exec_procedure_func(self._on_fail, class_record)
+            class_record.update_record()
+            self.summary_writer.dump(class_record.to_dict(),
+                                     records.TestSummaryEntryType.RECORD)
+            self._skip_remaining_tests(e)
+            return self.results
+        if expects.recorder.has_error:
+            self._exec_procedure_func(self._on_fail, class_record)
+            class_record.test_error()
+            class_record.update_record()
+            self.summary_writer.dump(class_record.to_dict(),
+                                     records.TestSummaryEntryType.RECORD)
+            self.results.add_class_error(class_record)
+            self._skip_remaining_tests(
+                class_record.termination_signal.exception)
+            return self.results
 
     def setup_class(self):
         """Setup function that will be called before executing any test in the
@@ -302,6 +339,8 @@ class BaseTestClass(object):
 
         To signal setup failure, use asserts or raise your own exception.
 
+        Errors raised from `setup_class` will trigger `on_fail`.
+
         Implementation is optional.
         """
 
@@ -314,6 +353,7 @@ class BaseTestClass(object):
         record.test_begin()
         self.current_test_info = runtime_test_info.RuntimeTestInfo(
             stage_name, self.log_path, record)
+        expects.recorder.reset_internal_states(record)
         try:
             with self._log_test_stage(stage_name):
                 self.teardown_class()
@@ -327,6 +367,12 @@ class BaseTestClass(object):
             self.results.add_class_error(record)
             self.summary_writer.dump(record.to_dict(),
                                      records.TestSummaryEntryType.RECORD)
+        else:
+            if expects.recorder.has_error:
+                record.update_record()
+                self.results.add_class_error(record)
+                self.summary_writer.dump(record.to_dict(),
+                                         records.TestSummaryEntryType.RECORD)
         finally:
             # Write controller info and summary to summary file.
             self._record_controller_info()
@@ -336,6 +382,8 @@ class BaseTestClass(object):
         """Teardown function that will be called after all the selected tests in
         the test class have been executed.
 
+        Errors raised from `teardown_class` do not trigger `on_fail`.
+
         Implementation is optional.
         """
 
@@ -775,28 +823,9 @@ class BaseTestClass(object):
                                  records.TestSummaryEntryType.TEST_NAME_LIST)
         tests = self._get_test_methods(test_names)
         try:
-            # Setup for the class.
-            class_record = records.TestResultRecord(STAGE_NAME_SETUP_CLASS,
-                                                    self.TAG)
-            class_record.test_begin()
-            self.current_test_info = runtime_test_info.RuntimeTestInfo(
-                STAGE_NAME_SETUP_CLASS, self.log_path, class_record)
-            try:
-                self._setup_class()
-            except signals.TestAbortSignal:
-                # Throw abort signals to outer try block for handling.
-                raise
-            except Exception as e:
-                # Setup class failed for unknown reasons.
-                # Fail the class and skip all tests.
-                logging.exception('Error in %s#setup_class.', self.TAG)
-                class_record.test_error(e)
-                self.results.add_class_error(class_record)
-                self.summary_writer.dump(class_record.to_dict(),
-                                         records.TestSummaryEntryType.RECORD)
-                self._exec_procedure_func(self._on_fail, class_record)
-                self._skip_remaining_tests(e)
-                return self.results
+            setup_class_result = self._setup_class()
+            if setup_class_result:
+                return setup_class_result
             # Run tests in order.
             for test_name, test_method in tests:
                 self.exec_one_test(test_name, test_method)
diff --git a/tests/mobly/base_test_test.py b/tests/mobly/base_test_test.py
index 7fb2b1d..1183133 100755
--- a/tests/mobly/base_test_test.py
+++ b/tests/mobly/base_test_test.py
@@ -1485,6 +1485,122 @@ class BaseTestTest(unittest.TestCase):
         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()
+
+        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 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')
+
+    @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')
+
+            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')
+
+        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()
+
+        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')
+
+        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()
+
+        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 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)
+
     def test_expect_in_teardown_test(self):
         must_call = mock.Mock()
         must_call2 = mock.Mock()
diff --git a/tests/mobly/controllers/android_device_lib/adb_test.py b/tests/mobly/controllers/android_device_lib/adb_test.py
index 71fab9c..9430795 100755
--- a/tests/mobly/controllers/android_device_lib/adb_test.py
+++ b/tests/mobly/controllers/android_device_lib/adb_test.py
@@ -91,15 +91,29 @@ class AdbTest(unittest.TestCase):
 
     @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
     @mock.patch('mobly.controllers.android_device_lib.adb.psutil.Process')
-    def test_exec_cmd_error_no_timeout(self, mock_psutil_process, mock_popen):
+    def test_exec_cmd_error_with_serial(self, mock_psutil_process, mock_popen):
         self._mock_process(mock_psutil_process, mock_popen)
         # update return code to indicate command execution error
         mock_popen.return_value.returncode = 1
+        mock_serial = 'ABCD1234'
+        with self.assertRaisesRegex(adb.AdbError,
+                                    'Error executing adb cmd .*') as context:
+            adb.AdbProxy(mock_serial).fake_cmd()
+        self.assertEqual(context.exception.serial, mock_serial)
+        self.assertIn(mock_serial, context.exception.cmd)
 
+    @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
+    @mock.patch('mobly.controllers.android_device_lib.adb.psutil.Process')
+    def test_exec_cmd_error_without_serial(self, mock_psutil_process,
+                                           mock_popen):
+        self._mock_process(mock_psutil_process, mock_popen)
+        # update return code to indicate command execution error
+        mock_popen.return_value.returncode = 1
         with self.assertRaisesRegex(adb.AdbError,
-                                    'Error executing adb cmd .*'):
+                                    'Error executing adb cmd .*') as context:
             adb.AdbProxy()._exec_cmd(
                 ['fake_cmd'], shell=False, timeout=None, stderr=None)
+        self.assertFalse(context.exception.serial)
 
     @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
     @mock.patch('mobly.controllers.android_device_lib.adb.psutil.Process')
@@ -115,23 +129,34 @@ class AdbTest(unittest.TestCase):
     @mock.patch('mobly.controllers.android_device_lib.adb.psutil.Process')
     def test_exec_cmd_timed_out(self, mock_psutil_process, mock_popen):
         self._mock_process(mock_psutil_process, mock_popen)
-        # mock process.wait(timeout=timeout) to
-        # throw psutil.TimeoutExpired exception
         mock_psutil_process.return_value.wait.side_effect = (
             adb.psutil.TimeoutExpired('Timed out'))
+        mock_serial = '1234Abcd'
+        with self.assertRaisesRegex(
+                adb.AdbTimeoutError, 'Timed out executing command "adb -s '
+                '1234Abcd fake-cmd" after 0.01s.') as context:
+            adb.AdbProxy(mock_serial).fake_cmd(timeout=0.01)
+        self.assertEqual(context.exception.serial, mock_serial)
+        self.assertIn(mock_serial, context.exception.cmd)
 
+    @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
+    @mock.patch('mobly.controllers.android_device_lib.adb.psutil.Process')
+    def test_exec_cmd_timed_out_without_serial(self, mock_psutil_process,
+                                               mock_popen):
+        self._mock_process(mock_psutil_process, mock_popen)
+        mock_psutil_process.return_value.wait.side_effect = (
+            adb.psutil.TimeoutExpired('Timed out'))
         with self.assertRaisesRegex(adb.AdbTimeoutError,
-                                    'Timed out executing command "fake_cmd" '
-                                    'after 0.1s.'):
-            adb.AdbProxy()._exec_cmd(
-                ['fake_cmd'], shell=False, timeout=0.1, stderr=None)
+                                    'Timed out executing command "adb '
+                                    'fake-cmd" after 0.01s.') as context:
+            adb.AdbProxy().fake_cmd(timeout=0.01)
 
     @mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
     @mock.patch('mobly.controllers.android_device_lib.adb.psutil.Process')
     def test_exec_cmd_with_negative_timeout_value(self, mock_psutil_process,
                                                   mock_popen):
         self._mock_process(mock_psutil_process, mock_popen)
-        with self.assertRaisesRegex(adb.Error,
+        with self.assertRaisesRegex(ValueError,
                                     'Timeout is not a positive value: -1'):
             adb.AdbProxy()._exec_cmd(
                 ['fake_cmd'], shell=False, timeout=-1, stderr=None)
@@ -156,8 +181,8 @@ class AdbTest(unittest.TestCase):
         self._mock_execute_and_process_stdout_process(mock_popen)
         mock_handler = mock.MagicMock()
         mock_popen.return_value.communicate = mock.Mock(
-            return_value=(unexpected_stdout, MOCK_DEFAULT_STDERR.encode(
-                'utf-8')))
+            return_value=(unexpected_stdout,
+                          MOCK_DEFAULT_STDERR.encode('utf-8')))
 
         err = adb.AdbProxy()._execute_and_process_stdout(
             ['fake_cmd'], shell=False, handler=mock_handler)
diff --git a/tests/mobly/utils_test.py b/tests/mobly/utils_test.py
index 605dc8c..b9b0c22 100755
--- a/tests/mobly/utils_test.py
+++ b/tests/mobly/utils_test.py
@@ -53,6 +53,31 @@ class UtilsTest(unittest.TestCase):
             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)
+        mock_Popen.assert_called_with(
+            self.sleep_cmd,
+            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, env=mock_env)
+        mock_Popen.assert_called_with(
+            self.sleep_cmd,
+            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)

pip install -e .
parse_log_pytest
pytest
mock pytest pytz
apt-get update apt-get install -y adb python3-setuptools
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
future==1.0.0
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
-e git+https://github.com/google/mobly.git@e78255672c61f8f091e9eeb09f3b9f46481202d2#egg=mobly
mock==5.2.0
packaging @ file:///croot/packaging_1734472117206/work
pluggy @ file:///croot/pluggy_1733169602837/work
portpicker==1.6.0
psutil==7.0.0
pyserial==3.5
pytest @ file:///croot/pytest_1738938843180/work
pytz==2025.2
PyYAML==6.0.2
timeout-decorator==0.5.0
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work

name: mobly
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py39h06a4308_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - future==1.0.0
      - mock==5.2.0
      - portpicker==1.6.0
      - psutil==7.0.0
      - pyserial==3.5
      - pytz==2025.2
      - pyyaml==6.0.2
      - timeout-decorator==0.5.0
prefix: /opt/conda/envs/mobly

tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_error_with_serial tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_error_without_serial tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_timed_out tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_with_negative_timeout_value tests/mobly/utils_test.py::UtilsTest::test_start_standing_subproc_with_custom_env tests/mobly/utils_test.py::UtilsTest::test_start_standing_subproc_without_env
tests/mobly/base_test_test.py::BaseTestTest::test_write_user_data
tests/mobly/base_test_test.py::BaseTestTest::test_abort_all_in_on_fail tests/mobly/base_test_test.py::BaseTestTest::test_abort_all_in_on_fail_from_setup_class tests/mobly/base_test_test.py::BaseTestTest::test_abort_all_in_setup_class tests/mobly/base_test_test.py::BaseTestTest::test_abort_all_in_setup_test tests/mobly/base_test_test.py::BaseTestTest::test_abort_all_in_teardown_class tests/mobly/base_test_test.py::BaseTestTest::test_abort_all_in_test tests/mobly/base_test_test.py::BaseTestTest::test_abort_class_in_on_fail tests/mobly/base_test_test.py::BaseTestTest::test_abort_class_in_setup_test tests/mobly/base_test_test.py::BaseTestTest::test_abort_class_in_test tests/mobly/base_test_test.py::BaseTestTest::test_abort_class_setup_class tests/mobly/base_test_test.py::BaseTestTest::test_assert_equal_fail tests/mobly/base_test_test.py::BaseTestTest::test_assert_equal_fail_with_msg tests/mobly/base_test_test.py::BaseTestTest::test_assert_equal_pass tests/mobly/base_test_test.py::BaseTestTest::test_assert_raises_fail_with_noop tests/mobly/base_test_test.py::BaseTestTest::test_assert_raises_fail_with_wrong_error tests/mobly/base_test_test.py::BaseTestTest::test_assert_raises_fail_with_wrong_regex tests/mobly/base_test_test.py::BaseTestTest::test_assert_raises_pass tests/mobly/base_test_test.py::BaseTestTest::test_assert_raises_regex_fail_with_noop tests/mobly/base_test_test.py::BaseTestTest::test_assert_raises_regex_fail_with_wrong_error tests/mobly/base_test_test.py::BaseTestTest::test_assert_raises_regex_pass tests/mobly/base_test_test.py::BaseTestTest::test_assert_true tests/mobly/base_test_test.py::BaseTestTest::test_both_teardown_and_test_body_raise_exceptions tests/mobly/base_test_test.py::BaseTestTest::test_cli_test_selection_fail_by_convention tests/mobly/base_test_test.py::BaseTestTest::test_cli_test_selection_override_self_tests_list tests/mobly/base_test_test.py::BaseTestTest::test_current_test_info tests/mobly/base_test_test.py::BaseTestTest::test_current_test_info_in_setup_class tests/mobly/base_test_test.py::BaseTestTest::test_current_test_name tests/mobly/base_test_test.py::BaseTestTest::test_default_execution_of_all_tests tests/mobly/base_test_test.py::BaseTestTest::test_exception_objects_in_record tests/mobly/base_test_test.py::BaseTestTest::test_expect_equal tests/mobly/base_test_test.py::BaseTestTest::test_expect_false tests/mobly/base_test_test.py::BaseTestTest::test_expect_in_setup_class tests/mobly/base_test_test.py::BaseTestTest::test_expect_in_setup_class_and_on_fail tests/mobly/base_test_test.py::BaseTestTest::test_expect_in_setup_test tests/mobly/base_test_test.py::BaseTestTest::test_expect_in_teardown_class tests/mobly/base_test_test.py::BaseTestTest::test_expect_in_teardown_test tests/mobly/base_test_test.py::BaseTestTest::test_expect_multiple_fails tests/mobly/base_test_test.py::BaseTestTest::test_expect_no_op tests/mobly/base_test_test.py::BaseTestTest::test_expect_no_raises_custom_msg tests/mobly/base_test_test.py::BaseTestTest::test_expect_no_raises_default_msg tests/mobly/base_test_test.py::BaseTestTest::test_expect_true tests/mobly/base_test_test.py::BaseTestTest::test_expect_true_and_assert_true tests/mobly/base_test_test.py::BaseTestTest::test_expect_two_tests tests/mobly/base_test_test.py::BaseTestTest::test_explicit_pass tests/mobly/base_test_test.py::BaseTestTest::test_explicit_pass_but_teardown_test_raises_an_exception tests/mobly/base_test_test.py::BaseTestTest::test_fail tests/mobly/base_test_test.py::BaseTestTest::test_failure_in_procedure_functions_is_recorded tests/mobly/base_test_test.py::BaseTestTest::test_failure_to_call_procedure_function_is_recorded tests/mobly/base_test_test.py::BaseTestTest::test_generate_tests_call_outside_of_setup_generated_tests tests/mobly/base_test_test.py::BaseTestTest::test_generate_tests_dup_test_name tests/mobly/base_test_test.py::BaseTestTest::test_generate_tests_run tests/mobly/base_test_test.py::BaseTestTest::test_generate_tests_selected_run tests/mobly/base_test_test.py::BaseTestTest::test_implicit_pass tests/mobly/base_test_test.py::BaseTestTest::test_missing_requested_test_func tests/mobly/base_test_test.py::BaseTestTest::test_on_fail_cannot_modify_original_record tests/mobly/base_test_test.py::BaseTestTest::test_on_fail_executed_if_both_test_and_teardown_test_fails tests/mobly/base_test_test.py::BaseTestTest::test_on_fail_executed_if_setup_class_fails_by_exception tests/mobly/base_test_test.py::BaseTestTest::test_on_fail_executed_if_setup_test_fails_by_exception tests/mobly/base_test_test.py::BaseTestTest::test_on_fail_executed_if_teardown_test_fails tests/mobly/base_test_test.py::BaseTestTest::test_on_fail_executed_if_test_fails tests/mobly/base_test_test.py::BaseTestTest::test_on_fail_raise_exception tests/mobly/base_test_test.py::BaseTestTest::test_on_fail_triggered_by_setup_class_failure_then_fail_too tests/mobly/base_test_test.py::BaseTestTest::test_on_pass_cannot_modify_original_record tests/mobly/base_test_test.py::BaseTestTest::test_on_pass_raise_exception tests/mobly/base_test_test.py::BaseTestTest::test_procedure_function_gets_correct_record tests/mobly/base_test_test.py::BaseTestTest::test_promote_extra_errors_to_termination_signal tests/mobly/base_test_test.py::BaseTestTest::test_record_controller_info tests/mobly/base_test_test.py::BaseTestTest::test_self_tests_list tests/mobly/base_test_test.py::BaseTestTest::test_self_tests_list_fail_by_convention tests/mobly/base_test_test.py::BaseTestTest::test_setup_and_teardown_execution_count tests/mobly/base_test_test.py::BaseTestTest::test_setup_class_fail_by_exception tests/mobly/base_test_test.py::BaseTestTest::test_setup_generated_tests_failure tests/mobly/base_test_test.py::BaseTestTest::test_setup_test_fail_by_exception tests/mobly/base_test_test.py::BaseTestTest::test_setup_test_fail_by_test_signal tests/mobly/base_test_test.py::BaseTestTest::test_skip tests/mobly/base_test_test.py::BaseTestTest::test_skip_if tests/mobly/base_test_test.py::BaseTestTest::test_skip_in_setup_test tests/mobly/base_test_test.py::BaseTestTest::test_teardown_class_fail_by_exception tests/mobly/base_test_test.py::BaseTestTest::test_teardown_class_raise_abort_all tests/mobly/base_test_test.py::BaseTestTest::test_teardown_test_assert_fail tests/mobly/base_test_test.py::BaseTestTest::test_teardown_test_executed_if_setup_test_fails tests/mobly/base_test_test.py::BaseTestTest::test_teardown_test_executed_if_test_fails tests/mobly/base_test_test.py::BaseTestTest::test_teardown_test_executed_if_test_pass tests/mobly/base_test_test.py::BaseTestTest::test_teardown_test_raise_exception tests/mobly/base_test_test.py::BaseTestTest::test_uncaught_exception tests/mobly/base_test_test.py::BaseTestTest::test_unpack_userparams_basic tests/mobly/base_test_test.py::BaseTestTest::test_unpack_userparams_default_None tests/mobly/base_test_test.py::BaseTestTest::test_unpack_userparams_default_overwrite tests/mobly/base_test_test.py::BaseTestTest::test_unpack_userparams_default_overwrite_by_optional_param_list tests/mobly/base_test_test.py::BaseTestTest::test_unpack_userparams_default_overwrite_by_required_param_list tests/mobly/base_test_test.py::BaseTestTest::test_unpack_userparams_optional tests/mobly/base_test_test.py::BaseTestTest::test_unpack_userparams_optional_missing tests/mobly/base_test_test.py::BaseTestTest::test_unpack_userparams_optional_with_default tests/mobly/base_test_test.py::BaseTestTest::test_unpack_userparams_required tests/mobly/base_test_test.py::BaseTestTest::test_unpack_userparams_required_missing tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_cli_cmd_to_string tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_list tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_one_arg_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_one_arg_command_list tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_one_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_serial tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_serial_with_list tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_auto_quotes tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_list tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_one_arg_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_one_arg_command_list tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_one_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_serial tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_shell_true_with_serial_with_list tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_construct_adb_cmd_with_special_characters tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_adb_cmd tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_adb_cmd_formats_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_adb_cmd_formats_command_with_shell_true tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_adb_cmd_with_shell_true tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_adb_cmd_with_stderr_pipe tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_no_timeout_success tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_timed_out_without_serial tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_with_timeout_success tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_adb_and_process_stdout_formats_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_despite_cmd_exits tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_logs_cmd tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_logs_cmd_with_unexpected_stdout tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_raises_adb_error tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_reads_stdout tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_reads_unexpected_stdout tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_returns_stderr tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_when_cmd_eof tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_execute_and_process_stdout_when_handler_crash tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_forward tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_has_shell_command_called_correctly tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_has_shell_command_with_existing_command tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_has_shell_command_with_missing_command_on_newer_devices tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_has_shell_command_with_missing_command_on_older_devices tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_instrument_with_handler tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_instrument_with_handler_with_options tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_instrument_with_handler_with_runner tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_instrument_with_options tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_instrument_with_runner tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_instrument_without_parameters tests/mobly/utils_test.py::UtilsTest::test_create_dir tests/mobly/utils_test.py::UtilsTest::test_create_dir_already_exists tests/mobly/utils_test.py::UtilsTest::test_get_available_port_negative tests/mobly/utils_test.py::UtilsTest::test_get_available_port_positive tests/mobly/utils_test.py::UtilsTest::test_get_available_port_returns_free_port tests/mobly/utils_test.py::UtilsTest::test_load_file_to_base64_str_reads_bytes_file_as_base64_string tests/mobly/utils_test.py::UtilsTest::test_load_file_to_base64_str_reads_text_file_as_base64_string tests/mobly/utils_test.py::UtilsTest::test_load_file_to_base64_str_reads_unicode_file_as_base64_string tests/mobly/utils_test.py::UtilsTest::test_start_standing_subproc tests/mobly/utils_test.py::UtilsTest::test_stop_standing_subproc tests/mobly/utils_test.py::UtilsTest::test_stop_standing_subproc_wihtout_pipe
mobly/utils.py mobly/controllers/android_device_lib/adb.py
mobly/utils.py mobly/controllers/android_device_lib/adb.py