diff --git a/src/python_testing/TC_DeviceBasicComposition.py b/src/python_testing/TC_DeviceBasicComposition.py index 0742887c6fee25..a3f8db05765753 100644 --- a/src/python_testing/TC_DeviceBasicComposition.py +++ b/src/python_testing/TC_DeviceBasicComposition.py @@ -272,7 +272,7 @@ def check_no_duplicates(obj: Any) -> None: raise ValueError(f"Value {str(obj)} contains duplicate values") -class TC_DeviceBasicComposition(MatterBaseTest, BasicCompositionTests): +class TC_DeviceBasicComposition(BasicCompositionTests, MatterBaseTest): @async_test_body async def setup_class(self): super().setup_class() @@ -966,15 +966,8 @@ def test_TC_IDM_12_1(self): json_str, txt_str = self.dump_wildcard(dump_device_composition_path) # Structured dump so we can pull these back out of the logs - def log_structured_data(start_tag: str, dump_string): - lines = dump_string.splitlines() - logging.info(f'{start_tag}BEGIN ({len(lines)} lines)====') - for line in lines: - logging.info(f'{start_tag}{line}') - logging.info(f'{start_tag}END ====') - - log_structured_data('==== json: ', json_str) - log_structured_data('==== txt: ', txt_str) + self.log_structured_data('==== json: ', json_str) + self.log_structured_data('==== txt: ', txt_str) @async_test_body async def test_TC_DESC_2_1(self): diff --git a/src/python_testing/TC_DeviceConformance.py b/src/python_testing/TC_DeviceConformance.py index b1ebfecd36f60a..ddd6c2ea923a7c 100644 --- a/src/python_testing/TC_DeviceConformance.py +++ b/src/python_testing/TC_DeviceConformance.py @@ -41,7 +41,7 @@ from matter.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main -class TC_DeviceConformance(MatterBaseTest, DeviceConformanceTests): +class TC_DeviceConformance(DeviceConformanceTests, MatterBaseTest): @async_test_body async def setup_class(self): super().setup_class() diff --git a/src/python_testing/matter_testing_infrastructure/matter/testing/matter_testing.py b/src/python_testing/matter_testing_infrastructure/matter/testing/matter_testing.py index a9bed0941cabe9..2a0b8100c94b89 100644 --- a/src/python_testing/matter_testing_infrastructure/matter/testing/matter_testing.py +++ b/src/python_testing/matter_testing_infrastructure/matter/testing/matter_testing.py @@ -206,7 +206,7 @@ def setup_class(self): self.stored_global_wildcard = None def teardown_class(self): - """Final teardown after all tests: log all problems. + """Final teardown after all tests: log all problems and dump device attributes if available. Test authors may overwrite this method in the derived class to perform teardown that is common for all tests This function is called only once per class. To perform teardown after each test, use teardown_test. Test authors that implement steps in this function need to be careful of step handling if there is @@ -216,6 +216,9 @@ def teardown_class(self): """ if len(self.problems) > 0: + # Attempt to dump device attribute data for debugging when problems are found + self._dump_device_attributes_on_failure() + LOGGER.info("###########################################################") LOGGER.info("Problems found:") LOGGER.info("===============") @@ -224,6 +227,42 @@ def teardown_class(self): LOGGER.info("###########################################################") super().teardown_class() + def _dump_device_attributes_on_failure(self): + """ + Dump device attribute data when problems are found for debugging purposes. + + This method attempts to generate a device attribute dump if the test has + collected endpoint data. It's designed to be safe and not interfere with + the original test failure reporting. + """ + try: + # Check if we have endpoints_tlv data (from BasicCompositionTests or similar) + if hasattr(self, 'endpoints_tlv') and self.endpoints_tlv: + # Check if we have the dump_wildcard method (from BasicCompositionTests) + if hasattr(self, 'dump_wildcard'): + _, txt_str = self.dump_wildcard(None) + # Only dump the text format - it's more readable for debugging + self.log_structured_data('==== FAILURE_DUMP_txt: ', txt_str) + except (AttributeError, KeyError, ValueError, TypeError): + # Don't let data access or serialization errors interfere with the original test failure + pass + + def log_structured_data(self, start_tag: str, dump_string: str): + """Log structured data with a clear start and end marker. + + This function is used to output device attribute dumps and other structured + data to logs in a format that can be easily extracted for debugging. + + Args: + start_tag: A prefix tag to identify the type of data being logged + dump_string: The data to be logged + """ + lines = dump_string.splitlines() + LOGGER.info(f'{start_tag}BEGIN ({len(lines)} lines)====') + for line in lines: + LOGGER.info(f'{start_tag}{line}') + LOGGER.info(f'{start_tag}END ====') + def setup_test(self): """Set up for each individual test execution.