From f96697f95e5d0ec16e83ff228449bc235cf61b80 Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Mon, 27 Jan 2025 13:15:46 +0100 Subject: [PATCH] feat: record `app_path` in junit reports --- .../pytest_embedded_idf/unity_tester.py | 11 +++++++---- pytest-embedded-idf/tests/test_idf.py | 14 ++++++++++++++ pytest-embedded/pytest_embedded/dut.py | 7 ++++++- pytest-embedded/tests/test_base.py | 4 +++- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/pytest-embedded-idf/pytest_embedded_idf/unity_tester.py b/pytest-embedded-idf/pytest_embedded_idf/unity_tester.py index c5074d19..25e15a39 100644 --- a/pytest-embedded-idf/pytest_embedded_idf/unity_tester.py +++ b/pytest-embedded-idf/pytest_embedded_idf/unity_tester.py @@ -288,7 +288,9 @@ def wrapper(self, *args, **kwargs): finally: _end_at = time.perf_counter() self._add_single_unity_test_case( - _case, _log, additional_attrs={'time': round(_end_at - _start_at, 3)} + _case, + _log, + additional_attrs={'app_path': self.app.app_path, 'time': round(_end_at - _start_at, 3)}, ) return wrapper @@ -695,6 +697,8 @@ def process_raw_report_data(self, raw_data_to_report) -> t.Dict: if log: attrs.update({'stdout': log}) + attrs.update({'app_path': self.dut.app.app_path}) + return attrs def add_to_report(self, attrs): @@ -765,9 +769,6 @@ def gather(self): for _t in self.workers: _t.close() - def get_processed_report_data(self, res: t.List[t.Any]) -> t.List[t.Dict]: - return [self.workers[i].process_raw_report_data(res[i]) for i in range(len(res))] - @staticmethod def get_merge_data(test_cases_attr: t.List[t.Dict]) -> t.Dict: output = {} @@ -794,6 +795,8 @@ def get_merge_data(test_cases_attr: t.List[t.Dict]) -> t.Dict: for k, val in output.items(): if k in ('file', 'line'): output[k] = val[0] + elif k == 'app_path': + output[k] = '|'.join(val) else: output[k] = '<------------------->\n'.join(val) diff --git a/pytest-embedded-idf/tests/test_idf.py b/pytest-embedded-idf/tests/test_idf.py index 53989aa3..7a9d8c56 100644 --- a/pytest-embedded-idf/tests/test_idf.py +++ b/pytest-embedded-idf/tests/test_idf.py @@ -858,6 +858,10 @@ def test_dut_run_all_single_board_cases(dut): assert junit_report.attrib['failures'] == '1' assert junit_report.attrib['skipped'] == '0' assert junit_report.attrib['tests'] == '1' + cases = junit_report.findall('.//testcase') + assert len(cases) == 2 + assert cases[0].attrib['app_path'] == os.path.join(testdir.tmpdir, 'unit_test_app_esp32') + assert cases[1].attrib['app_path'] == os.path.join(testdir.tmpdir, 'unit_test_app_esp32') def test_dut_run_all_single_board_cases_invert_group(testdir): @@ -939,14 +943,24 @@ def test_unity_test_case_runner(unity_tester): assert junit_report.attrib['skipped'] == '0' assert junit_report.attrib['tests'] == '3' + # single-dut app_path should be the dut[0] one assert junit_report[0].get('name') == 'normal_case1' assert junit_report[0].find('failure') is None + assert junit_report[0].get('app_path') == os.path.join(testdir.tmpdir, 'unit_test_app_esp32') assert junit_report[1].get('name') == 'normal_case2' assert junit_report[1].find('failure') is not None + assert junit_report[1].get('app_path') == os.path.join(testdir.tmpdir, 'unit_test_app_esp32') assert junit_report[2].get('name') == 'multiple_stages_test' assert junit_report[2].find('failure') is None + assert junit_report[2].get('app_path') == os.path.join(testdir.tmpdir, 'unit_test_app_esp32') + # multi-dut app_path should be concatenated assert junit_report[3].get('name') == 'multiple_devices_test' assert junit_report[3].find('failure') is None + assert ( + junit_report[3].get('app_path') == f'{os.path.join(testdir.tmpdir, "unit_test_app_esp32")}' + f'|' + f'{os.path.join(testdir.tmpdir, "unit_test_app_esp32c3")}' + ) def test_erase_all_with_port_cache(testdir): diff --git a/pytest-embedded/pytest_embedded/dut.py b/pytest-embedded/pytest_embedded/dut.py index 2d03aa42..ef39b7c0 100644 --- a/pytest-embedded/pytest_embedded/dut.py +++ b/pytest-embedded/pytest_embedded/dut.py @@ -187,7 +187,12 @@ def expect_unity_test_output( if remove_asci_escape_code: log = remove_asci_color_code(log) - self.testsuite.add_unity_test_cases(log) + self.testsuite.add_unity_test_cases( + log, + additional_attrs={ + 'app_path': self.app.app_path, + }, + ) @_InjectMixinCls.require_services('idf') def run_all_single_board_cases( diff --git a/pytest-embedded/tests/test_base.py b/pytest-embedded/tests/test_base.py index d2db85ce..77280d27 100644 --- a/pytest-embedded/tests/test_base.py +++ b/pytest-embedded/tests/test_base.py @@ -476,7 +476,7 @@ def test_expect_unity_test_output_multi_dut_with_illegal_chars(dut): dut_1.expect_unity_test_output() """) - result = testdir.runpytest('--junitxml', 'report.xml') + result = testdir.runpytest('--app-path', f'{testdir.tmpdir}/foo|{testdir.tmpdir}/bar', '--junitxml', 'report.xml') try: result.assert_outcomes(failed=1) @@ -492,8 +492,10 @@ def test_expect_unity_test_output_multi_dut_with_illegal_chars(dut): assert junit_report[0].get('name') == 'test_case' assert junit_report[0].find('failure') is not None + assert junit_report[0].get('app_path') == f'{testdir.tmpdir}/foo' assert junit_report[1].get('name') == 'test_case' assert junit_report[1].find('failure') is not None + assert junit_report[1].get('app_path') == f'{testdir.tmpdir}/bar' def test_duplicate_stdout_popen(testdir):