Fix GHA and GMSCore version not shown in test report PiperOrigin-RevId: 604087771
diff --git a/ui_automator/test_reporter.py b/ui_automator/test_reporter.py index eae676d..d5d0852 100644 --- a/ui_automator/test_reporter.py +++ b/ui_automator/test_reporter.py
@@ -37,7 +37,7 @@ 'Removing from GHA': 'test_decommission', }) _NA = 'n/a' -_SUMMARY_COL_INDENTS = 25 +_MINIMUM_SUMMARY_COL_INDENTS = 25 _TEST_CASE_TITLE_INDENTS = 25 _TEST_RESULT_INDENTS = 8 @@ -54,11 +54,11 @@ class ReportInfo(TypedDict): """Type guard for summary of running unit tests.""" - gha_version: NotRequired[str | None] - gms_core_version: NotRequired[str | None] - hub_version: NotRequired[str | None] - device_firmware: NotRequired[str | None] - dut: NotRequired[str | None] + gha_version: NotRequired[str] + gms_core_version: NotRequired[str] + hub_version: NotRequired[str] + device_firmware: NotRequired[str] + dut: NotRequired[str] # pylint: disable=protected-access @@ -283,7 +283,12 @@ 100.0 * float(total_successful_runs) / float(total_runs) ) report_info = report_info or {} - # TODO(b/317837867): Replace all placeholders with real values. + data_indents = _MINIMUM_SUMMARY_COL_INDENTS + for value in report_info.values(): + # Set indents to the maximum length of values in report info. + # Add 2 extra spaces to separate data and next header. + # If the value is less than minimum column indents, use the minimum. + data_indents = max(data_indents, len(value) + 2) rows: list[list[str]] = [] rows.append(['Summary', '', 'Version Info', '']) rows.append([ @@ -316,19 +321,11 @@ ]) f = open(summary_file_path, 'w', encoding='utf-8') - data_indents = ( - # Set indents to the maximum length of values in report info if any. - # Add 2 extra spaces to separate data and next header. - # If the value is less than default column indents, use the default. - max(max(map(len, report_info.values())) + 2, _SUMMARY_COL_INDENTS) - if report_info - else _SUMMARY_COL_INDENTS - ) for row in rows: for i, element in enumerate(row): if i % 2 == 0: # Writes header. - f.write(element.ljust(_SUMMARY_COL_INDENTS)) + f.write(element.ljust(_MINIMUM_SUMMARY_COL_INDENTS)) else: f.write(element.ljust(data_indents)) f.write('\n')
diff --git a/ui_automator/ui_automator.py b/ui_automator/ui_automator.py index edb17ca..380ab31 100644 --- a/ui_automator/ui_automator.py +++ b/ui_automator/ui_automator.py
@@ -407,6 +407,7 @@ self._is_reg_test_finished = True executor.shutdown(wait=False) + @get_android_device_ready def get_report_info(self) -> test_reporter.ReportInfo: """Gets report info for regression tests. @@ -417,12 +418,16 @@ """ temp_info = collections.defaultdict() if self._connected_device: - temp_info['gha_version'] = ad.get_apk_version( + gha_version = ad.get_apk_version( self._connected_device, 'com.google.android.apps.chromecast.app' ) - temp_info['gms_core_version'] = ad.get_apk_version( + if gha_version: + temp_info['gha_version'] = gha_version + gms_core_version = ad.get_apk_version( self._connected_device, 'com.google.android.gms' ) + if gms_core_version: + temp_info['gms_core_version'] = gms_core_version if _DUT.value: temp_info['dut'] = f"<{', '.join(_DUT.value)}>"
diff --git a/ui_automator/ui_automator_test.py b/ui_automator/ui_automator_test.py index d8813ba..2b2a191 100644 --- a/ui_automator/ui_automator_test.py +++ b/ui_automator/ui_automator_test.py
@@ -1000,29 +1000,35 @@ mock_exit.assert_called_once() @mock.patch.object(android_device, 'get_all_instances', autospec=True) + @mock.patch.object(ui_automator.UIAutomator, 'load_snippet', autospec=True) def test_get_report_info_includes_apk_versions_with_device_connected( self, + mock_load_snippet, mock_get_all_instances, ): + mock_get_all_instances.return_value = [self.mock_android_device] self.mock_android_device.adb.shell.side_effect = [ b'versionName=0.0.0\n', b'versionName=0.0.1\n', ] - mock_get_all_instances.return_value = [self.mock_android_device] - self.ui_automator.load_device() report_info = self.ui_automator.get_report_info() - self.assertEqual(len(report_info), 2) - self.assertEqual(report_info.get('gha_version'), '0.0.0') - self.assertEqual(report_info.get('gms_core_version'), '0.0.1') + mock_load_snippet.assert_called_once() + self.assertDictEqual( + report_info, {'gha_version': '0.0.0', 'gms_core_version': '0.0.1'} + ) - def test_get_report_info_returns_empty_dict_when_no_device_connected( - self, + @mock.patch.object(android_device, 'get_all_instances', autospec=True) + def test_get_report_info_raises_an_error_when_no_device_connected( + self, mock_get_all_instances ): - report_info = self.ui_automator.get_report_info() + mock_get_all_instances.return_value = [] - self.assertDictEqual(report_info, {}) + with self.assertRaisesRegex( + errors.AndroidDeviceNotReadyError, 'get_report_info failed.' + ): + self.ui_automator.get_report_info() @mock.patch.object(time, 'sleep', autospec=True) @mock.patch('builtins.open', autospec=True) @@ -1064,48 +1070,95 @@ mock_open.assert_called_once() @flagsaver.flagsaver((ui_automator._DUT, ['model', 'type', 'protocol'])) - def test_get_report_info_includes_dut_value_from_flag_input(self): - report_info = self.ui_automator.get_report_info() - - self.assertEqual(len(report_info), 1) - self.assertEqual(report_info.get('dut'), '<model, type, protocol>') - - @flagsaver.flagsaver((ui_automator._DUT, None)) - def test_get_report_info_returns_empty_dict_without_dut_flag_input( - self, + @mock.patch.object(ui_automator.UIAutomator, 'load_device', autospec=True) + @mock.patch.object(ui_automator.UIAutomator, 'load_snippet', autospec=True) + def test_get_report_info_includes_dut_value_from_flag_input( + self, mock_load_snippet, mock_load_device ): report_info = self.ui_automator.get_report_info() + mock_load_device.assert_called_once() + mock_load_snippet.assert_called_once() + self.assertDictEqual(report_info, {'dut': '<model, type, protocol>'}) + + @flagsaver.flagsaver((ui_automator._DUT, None)) + @mock.patch.object(ui_automator.UIAutomator, 'load_device', autospec=True) + @mock.patch.object(ui_automator.UIAutomator, 'load_snippet', autospec=True) + def test_get_report_info_returns_empty_dict_without_dut_flag_input( + self, mock_load_snippet, mock_load_device + ): + report_info = self.ui_automator.get_report_info() + + mock_load_device.assert_called_once() + mock_load_snippet.assert_called_once() self.assertDictEqual(report_info, {}) @flagsaver.flagsaver((ui_automator._HUB, '10.1.3')) - def test_get_report_info_includes_hub_value_from_flag_input(self): - report_info = self.ui_automator.get_report_info() - - self.assertEqual(len(report_info), 1) - self.assertEqual(report_info.get('hub_version'), '10.1.3') - - @flagsaver.flagsaver((ui_automator._HUB, None)) - def test_get_report_info_returns_empty_dict_without_hub_flag_input( - self, + @mock.patch.object(ui_automator.UIAutomator, 'load_device', autospec=True) + @mock.patch.object(ui_automator.UIAutomator, 'load_snippet', autospec=True) + def test_get_report_info_includes_hub_value_from_flag_input( + self, mock_load_snippet, mock_load_device ): report_info = self.ui_automator.get_report_info() + mock_load_device.assert_called_once() + mock_load_snippet.assert_called_once() + self.assertDictEqual(report_info, {'hub_version': '10.1.3'}) + + @flagsaver.flagsaver((ui_automator._HUB, None)) + @mock.patch.object(ui_automator.UIAutomator, 'load_device', autospec=True) + @mock.patch.object(ui_automator.UIAutomator, 'load_snippet', autospec=True) + def test_get_report_info_returns_empty_dict_without_hub_flag_input( + self, mock_load_snippet, mock_load_device + ): + report_info = self.ui_automator.get_report_info() + + mock_load_device.assert_called_once() + mock_load_snippet.assert_called_once() self.assertDictEqual(report_info, {}) @flagsaver.flagsaver((ui_automator._DEVICE_FIRMWARE, '10.20.12')) - def test_get_report_info_includes_device_firmware_from_flag_input(self): - report_info = self.ui_automator.get_report_info() - - self.assertEqual(len(report_info), 1) - self.assertEqual(report_info.get('device_firmware'), '10.20.12') - - @flagsaver.flagsaver((ui_automator._DEVICE_FIRMWARE, None)) - def test_get_report_info_returns_empty_dict_without_device_firmware_flag( - self, + @mock.patch.object(ui_automator.UIAutomator, 'load_device', autospec=True) + @mock.patch.object(ui_automator.UIAutomator, 'load_snippet', autospec=True) + def test_get_report_info_includes_device_firmware_from_flag_input( + self, mock_load_snippet, mock_load_device ): report_info = self.ui_automator.get_report_info() + mock_load_device.assert_called_once() + mock_load_snippet.assert_called_once() + self.assertDictEqual(report_info, {'device_firmware': '10.20.12'}) + + @flagsaver.flagsaver((ui_automator._DEVICE_FIRMWARE, None)) + @mock.patch.object(ui_automator.UIAutomator, 'load_device', autospec=True) + @mock.patch.object(ui_automator.UIAutomator, 'load_snippet', autospec=True) + def test_get_report_info_returns_empty_dict_without_device_firmware_flag( + self, mock_load_snippet, mock_load_device + ): + report_info = self.ui_automator.get_report_info() + + mock_load_device.assert_called_once() + mock_load_snippet.assert_called_once() + self.assertDictEqual(report_info, {}) + + @mock.patch.object(android_device, 'get_all_instances', autospec=True) + @mock.patch.object(ui_automator.UIAutomator, 'load_snippet', autospec=True) + def test_get_report_info_should_not_write_none_in_report_info( + self, + mock_load_snippet, + mock_get_all_instances, + ): + mock_get_all_instances.return_value = [self.mock_android_device] + self.mock_android_device.adb.shell.side_effect = [ + # Response for getting gha version. + b'Unable to find package\n', + # Response for getting gms core version. + b'Unable to find package\n', + ] + + report_info = self.ui_automator.get_report_info() + + mock_load_snippet.assert_called_once() self.assertDictEqual(report_info, {}) if __name__ == '__main__':