diff --git a/mobly/config_parser.py b/mobly/config_parser.py
index 2278ca6..d26f34b 100644
--- a/mobly/config_parser.py
+++ b/mobly/config_parser.py
@@ -152,7 +152,7 @@ def _load_config_file(path):
         A dict that represents info in the config file.
     """
     with io.open(utils.abs_path(path), 'r', encoding='utf-8') as f:
-        conf = yaml.load(f)
+        conf = yaml.safe_load(f)
         return conf
 
 
diff --git a/mobly/controllers/android_device.py b/mobly/controllers/android_device.py
index 331d2c1..20204be 100644
--- a/mobly/controllers/android_device.py
+++ b/mobly/controllers/android_device.py
@@ -711,8 +711,9 @@ class AndroidDevice(object):
                            'info.')
             return
         info = {}
-        info['build_id'] = self.adb.getprop('ro.build.id')
-        info['build_type'] = self.adb.getprop('ro.build.type')
+        build_info = self.adb.getprops(['ro.build.id', 'ro.build.type'])
+        info['build_id'] = build_info['ro.build.id']
+        info['build_type'] = build_info['ro.build.type']
         return info
 
     @property
diff --git a/mobly/controllers/android_device_lib/adb.py b/mobly/controllers/android_device_lib/adb.py
index 86b3112..885539a 100644
--- a/mobly/controllers/android_device_lib/adb.py
+++ b/mobly/controllers/android_device_lib/adb.py
@@ -62,8 +62,8 @@ class AdbError(Error):
 
     def __str__(self):
         return ('Error executing adb cmd "%s". ret: %d, stdout: %s, stderr: %s'
-                ) % (utils.cli_cmd_to_string(self.cmd), self.ret_code, self.stdout,
-                     self.stderr)
+                ) % (utils.cli_cmd_to_string(self.cmd), self.ret_code,
+                     self.stdout, self.stderr)
 
 
 class AdbTimeoutError(Error):
@@ -277,10 +277,28 @@ class AdbProxy(object):
             adb_cmd, shell=shell, handler=handler)
         return out
 
+    def _parse_getprop_output(self, output):
+        """Parses the raw output of `adb shell getprop` into a dictionary.
+
+        Args:
+            output: byte str, the raw output of the `adb shell getprop` call.
+
+        Returns:
+            dict, name-value pairs of the properties.
+        """
+        output = output.decode('utf-8').strip()
+        clean_output = output.replace('[', '').replace(']', '')
+        results = {}
+        for line in clean_output.split('\n'):
+            if line:
+                name, value = line.split(': ')
+                results[name] = value
+        return results
+
     def getprop(self, prop_name):
         """Get a property of the device.
 
-        This is a convenience wrapper for "adb shell getprop xxx".
+        This is a convenience wrapper for `adb shell getprop xxx`.
 
         Args:
             prop_name: A string that is the name of the property to get.
@@ -293,6 +311,28 @@ class AdbProxy(object):
             ['getprop', prop_name],
             timeout=DEFAULT_GETPROP_TIMEOUT_SEC).decode('utf-8').strip()
 
+    def getprops(self, prop_names):
+        """Get multiple properties of the device.
+
+        This is a convenience wrapper for `adb shell getprop`. Use this to
+        reduce the number of adb calls when getting multiple properties.
+
+        Args:
+            prop_names: list of strings, the names of the properties to get.
+
+        Returns:
+            A dict containing name-value pairs of the properties requested, if
+            they exist.
+        """
+        raw_output = self.shell(
+            ['getprop'], timeout=DEFAULT_GETPROP_TIMEOUT_SEC)
+        properties = self._parse_getprop_output(raw_output)
+        results = {}
+        for name in prop_names:
+            if name in properties:
+                results[name] = properties[name]
+        return results
+
     def has_shell_command(self, command):
         """Checks to see if a given check command exists on the device.
 

Reduce the number of adb calls made for `ad.getprop` 
Right now, each getprop requires a separate adb call.
In large scale labs, this could create a huge amount of adb calls.
We should provide a new API to get multiple props in one call.
diff --git a/tests/lib/mock_android_device.py b/tests/lib/mock_android_device.py
index 3745b1a..443f838 100755
--- a/tests/lib/mock_android_device.py
+++ b/tests/lib/mock_android_device.py
@@ -1,11 +1,11 @@
 # Copyright 2016 Google Inc.
-# 
+#
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
-# 
+#
 #     http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -68,6 +68,13 @@ class MockAdbProxy(object):
         self.serial = serial
         self.fail_br = fail_br
         self.fail_br_before_N = fail_br_before_N
+        self.mock_properties = {
+            "ro.build.id": "AB42",
+            "ro.build.type": "userdebug",
+            "ro.build.product": "FakeModel",
+            "ro.product.name": "FakeModel",
+            "sys.boot_completed": "1"
+        }
 
     def shell(self, params, timeout=None):
         if params == "id -u":
@@ -82,14 +89,11 @@ class MockAdbProxy(object):
             return b'1.1'
 
     def getprop(self, params):
-        if params == "ro.build.id":
-            return "AB42"
-        elif params == "ro.build.type":
-            return "userdebug"
-        elif params == "ro.build.product" or params == "ro.product.name":
-            return "FakeModel"
-        elif params == "sys.boot_completed":
-            return "1"
+        if params in self.mock_properties:
+            return self.mock_properties[params]
+
+    def getprops(self, params):
+        return self.mock_properties
 
     def bugreport(self, args, shell=False, timeout=None):
         expected = os.path.join(logging.log_path,
diff --git a/tests/mobly/base_test_test.py b/tests/mobly/base_test_test.py
index 43951f4..abe3a13 100755
--- a/tests/mobly/base_test_test.py
+++ b/tests/mobly/base_test_test.py
@@ -148,8 +148,8 @@ class BaseTestTest(unittest.TestCase):
 
         bt_cls = MockBaseTest(self.mock_test_cls_configs)
         expected_msg = (
-            'Test method name not_a_test_something does not follow '
-            'naming convention test_\*, abort.')
+            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()
 
@@ -186,8 +186,8 @@ class BaseTestTest(unittest.TestCase):
 
         bt_cls = MockBaseTest(self.mock_test_cls_configs)
         expected_msg = (
-            'Test method name not_a_test_something does not follow '
-            'naming convention test_\*, abort.')
+            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"])
 
@@ -1994,7 +1994,7 @@ class BaseTestTest(unittest.TestCase):
         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.load_all(f):
+            for c in yaml.safe_load_all(f):
                 if c['Type'] != records.TestSummaryEntryType.USER_DATA.value:
                     continue
                 hit = True
diff --git a/tests/mobly/controllers/android_device_lib/adb_test.py b/tests/mobly/controllers/android_device_lib/adb_test.py
index be3db43..911c36f 100755
--- a/tests/mobly/controllers/android_device_lib/adb_test.py
+++ b/tests/mobly/controllers/android_device_lib/adb_test.py
@@ -452,7 +452,48 @@ class AdbTest(unittest.TestCase):
                 ['adb', 'shell', 'getprop', 'haha'],
                 shell=False,
                 stderr=None,
-                timeout=5)
+                timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC)
+
+    def test_getprops(self):
+        with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
+            mock_exec_cmd.return_value = b'''
+[selinux.restorecon_recursive]: [/data/misc_ce/10]
+[sendbug.preferred.domain]: [google.com]
+[service.bootanim.exit]: [1]
+[sys.boot_completed]: [1]
+[sys.dvr.performance]: [idle]
+[sys.logbootcomplete]: [1]
+[sys.oem_unlock_allowed]: [1]
+[sys.rescue_boot_count]: [1]
+[sys.retaildemo.enabled]: [0]
+[sys.sysctl.extra_free_kbytes]: [27337]
+[sys.sysctl.tcp_def_init_rwnd]: [60]
+[sys.uidcpupower]: []
+[sys.usb.config]: [adb]
+[sys.usb.configfs]: [2]
+[sys.usb.controller]: [a600000.dwc3]
+[sys.usb.ffs.ready]: [1]
+[sys.usb.mtp.device_type]: [3]
+[sys.user.0.ce_available]: [true]
+[sys.wifitracing.started]: [1]
+[telephony.lteOnCdmaDevice]: [1]'''
+            actual_output = adb.AdbProxy().getprops([
+                'sys.wifitracing.started',  # "numeric" value
+                'sys.uidcpupower',  # empty value
+                'sendbug.preferred.domain',  # string value
+                'nonExistentProp'
+            ])
+            self.assertEqual(
+                actual_output, {
+                    'sys.wifitracing.started': '1',
+                    'sys.uidcpupower': '',
+                    'sendbug.preferred.domain': 'google.com'
+                })
+            mock_exec_cmd.assert_called_once_with(
+                ['adb', 'shell', 'getprop'],
+                shell=False,
+                stderr=None,
+                timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC)
 
     def test_forward(self):
         with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
diff --git a/tests/mobly/output_test.py b/tests/mobly/output_test.py
index 8a87902..6caf9b8 100755
--- a/tests/mobly/output_test.py
+++ b/tests/mobly/output_test.py
@@ -232,7 +232,7 @@ class OutputTest(unittest.TestCase):
          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.load_all(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'])
@@ -255,7 +255,7 @@ class OutputTest(unittest.TestCase):
         with io.open(summary_file_path, 'r', encoding='utf-8') as f:
             raw_content = f.read()
             f.seek(0)
-            for entry in yaml.load_all(f):
+            for entry in yaml.safe_load_all(f):
                 if (entry['Type'] == 'Record'
                         and entry[records.TestResultEnums.RECORD_NAME] ==
                         'teardown_class'):
diff --git a/tests/mobly/records_test.py b/tests/mobly/records_test.py
index ba25a69..a374347 100755
--- a/tests/mobly/records_test.py
+++ b/tests/mobly/records_test.py
@@ -361,7 +361,7 @@ class RecordsTest(unittest.TestCase):
         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.load(f)
+            content = yaml.safe_load(f)
             self.assertEqual(content['Type'],
                              records.TestSummaryEntryType.RECORD.value)
             self.assertEqual(content[records.TestResultEnums.RECORD_DETAILS],
@@ -380,7 +380,7 @@ class RecordsTest(unittest.TestCase):
         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.load(f)
+            content = yaml.safe_load(f)
             self.assertEqual(content['Type'],
                              records.TestSummaryEntryType.RECORD.value)
             self.assertEqual(content[records.TestResultEnums.RECORD_DETAILS],
@@ -398,7 +398,7 @@ class RecordsTest(unittest.TestCase):
             writer.dump(data, records.TestSummaryEntryType.USER_DATA)
         with io.open(dump_path, 'r', encoding='utf-8') as f:
             contents = []
-            for c in yaml.load_all(f):
+            for c in yaml.safe_load_all(f):
                 contents.append(c)
         for content in contents:
             self.assertEqual(content['Type'],
diff --git a/tests/mobly/test_runner_test.py b/tests/mobly/test_runner_test.py
index 0d282ba..26af2ee 100755
--- a/tests/mobly/test_runner_test.py
+++ b/tests/mobly/test_runner_test.py
@@ -132,7 +132,7 @@ class TestRunnerTest(unittest.TestCase):
         summary_path = os.path.join(logging.log_path,
                                     records.OUTPUT_FILE_SUMMARY)
         with io.open(summary_path, 'r', encoding='utf-8') as f:
-            summary_entries = list(yaml.load_all(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'],

pip install -e .[dev]
parse_log_pytest
requirements.txt
mock pytest pytz
apt-get update apt-get install -y adb
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
exceptiongroup==1.2.2
future==1.0.0
iniconfig==2.1.0
-e git+https://github.com/google/mobly.git@fc844080ab152a1b1853197d62ecf0798b209002#egg=mobly
mock==5.2.0
packaging==24.2
pluggy==1.5.0
portpicker==1.6.0
psutil==7.0.0
pyserial==3.5
pytest==8.3.5
pytz==2025.2
PyYAML==6.0.2
timeout-decorator==0.5.0
tomli==2.2.1

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
  - 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
  - pip=25.0=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
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - exceptiongroup==1.2.2
      - future==1.0.0
      - iniconfig==2.1.0
      - mock==5.2.0
      - packaging==24.2
      - pluggy==1.5.0
      - portpicker==1.6.0
      - psutil==7.0.0
      - pyserial==3.5
      - pytest==8.3.5
      - pytz==2025.2
      - pyyaml==6.0.2
      - timeout-decorator==0.5.0
      - tomli==2.2.1
prefix: /opt/conda/envs/mobly

tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_getprops
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_generate_tests_with_none_uid tests/mobly/base_test_test.py::BaseTestTest::test_generate_tests_with_uid 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_record_controller_info_fail 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_uid tests/mobly/base_test_test.py::BaseTestTest::test_uid_is_none tests/mobly/base_test_test.py::BaseTestTest::test_uid_not_specified 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/base_test_test.py::BaseTestTest::test_write_user_data 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_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_no_timeout_success 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_timed_out_without_serial tests/mobly/controllers/android_device_lib/adb_test.py::AdbTest::test_exec_cmd_with_negative_timeout_value 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_getprop 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/output_test.py::OutputTest::test_basic_output tests/mobly/output_test.py::OutputTest::test_run_twice_for_two_sets_of_logs tests/mobly/output_test.py::OutputTest::test_setup_logger_before_run tests/mobly/output_test.py::OutputTest::test_symlink tests/mobly/output_test.py::OutputTest::test_teardown_class_output tests/mobly/output_test.py::OutputTest::test_teardown_erases_logs tests/mobly/records_test.py::RecordsTest::test_add_controller_info_record tests/mobly/records_test.py::RecordsTest::test_exception_record_deepcopy tests/mobly/records_test.py::RecordsTest::test_is_all_pass tests/mobly/records_test.py::RecordsTest::test_is_all_pass_negative tests/mobly/records_test.py::RecordsTest::test_is_all_pass_with_add_class_error tests/mobly/records_test.py::RecordsTest::test_is_test_executed tests/mobly/records_test.py::RecordsTest::test_result_add_class_error_with_special_error tests/mobly/records_test.py::RecordsTest::test_result_add_class_error_with_test_signal tests/mobly/records_test.py::RecordsTest::test_result_add_operator_success tests/mobly/records_test.py::RecordsTest::test_result_add_operator_type_mismatch tests/mobly/records_test.py::RecordsTest::test_result_record_fail_none tests/mobly/records_test.py::RecordsTest::test_result_record_fail_stacktrace tests/mobly/records_test.py::RecordsTest::test_result_record_fail_with_float_extra tests/mobly/records_test.py::RecordsTest::test_result_record_fail_with_json_extra tests/mobly/records_test.py::RecordsTest::test_result_record_fail_with_unicode_exception tests/mobly/records_test.py::RecordsTest::test_result_record_fail_with_unicode_test_signal tests/mobly/records_test.py::RecordsTest::test_result_record_pass_none tests/mobly/records_test.py::RecordsTest::test_result_record_pass_with_float_extra tests/mobly/records_test.py::RecordsTest::test_result_record_pass_with_json_extra tests/mobly/records_test.py::RecordsTest::test_result_record_skip_none tests/mobly/records_test.py::RecordsTest::test_result_record_skip_with_float_extra tests/mobly/records_test.py::RecordsTest::test_result_record_skip_with_json_extra tests/mobly/records_test.py::RecordsTest::test_summary_user_data tests/mobly/records_test.py::RecordsTest::test_summary_write_dump tests/mobly/records_test.py::RecordsTest::test_summary_write_dump_with_unicode tests/mobly/records_test.py::RecordsTest::test_uid tests/mobly/test_runner_test.py::TestRunnerTest::test_add_test_class_mismatched_log_path tests/mobly/test_runner_test.py::TestRunnerTest::test_add_test_class_mismatched_test_bed_name tests/mobly/test_runner_test.py::TestRunnerTest::test_main_parse_args tests/mobly/test_runner_test.py::TestRunnerTest::test_run_no_tests tests/mobly/test_runner_test.py::TestRunnerTest::test_run_twice tests/mobly/test_runner_test.py::TestRunnerTest::test_run_two_test_classes tests/mobly/test_runner_test.py::TestRunnerTest::test_run_two_test_classes_different_configs_and_aliases tests/mobly/test_runner_test.py::TestRunnerTest::test_run_with_abort_all tests/mobly/test_runner_test.py::TestRunnerTest::test_summary_file_entries tests/mobly/test_runner_test.py::TestRunnerTest::test_teardown_logger_before_setup_logger
mobly/controllers/android_device.py mobly/config_parser.py mobly/controllers/android_device_lib/adb.py
mobly/controllers/android_device.py mobly/config_parser.py mobly/controllers/android_device_lib/adb.py