diff --git a/doc/manual/sphinx/source/test_items/items_common_attributes.rst b/doc/manual/sphinx/source/test_items/items_common_attributes.rst index cc7e024..32c3df3 100644 --- a/doc/manual/sphinx/source/test_items/items_common_attributes.rst +++ b/doc/manual/sphinx/source/test_items/items_common_attributes.rst @@ -87,6 +87,10 @@ if not provided is given in the table as well. | | | see :ref:`Expected result` | | | | for details. | +-----------------------+-------------------+-------------------------------------------------------+ + | ``store_result`` | / | Store the test result in a global variable. | + | | | see :ref:`Store result` | + | | | for details. | + +-----------------------+-------------------+-------------------------------------------------------+ last test result @@ -183,6 +187,61 @@ If the result and the expected_result is equal, the test will be *PASSED* if ``T The special ``$(result)`` variable is replaced in the ``expected_result`` attribute content with the test result value. +.. _sec_store_result: + +Store result +----------------------------------------------- + +The ``store_result`` attribute stores the test result into a named global variable, +making it available to subsequent test items via ``$(variable_name)``. + +If the test item returns a value (e.g. ``py_func``, ``json_rpc``), that value is stored. +If ``process_result`` is also specified, the stored value is the post-processed result. + +If the test item produces no value (result is ``None``), the stored value is the +test status string: ``"PASS"`` or ``"FAIL"``, evaluated after ``expected_result`` +but **before** ``no_fail``. This ensures the real outcome is captured even when +``no_fail: True`` would otherwise mask a failure. + +.. code-block:: yaml + :caption: Store a function return value + + - py_func: + name: Read sensor + func_name: read_temperature + store_result: temperature + + - py_func: + name: Check temperature in range + func_name: check_range + param: [$(temperature), 20, 30] + +.. code-block:: yaml + :caption: Store a post-processed value + + - py_func: + name: Get firmware version string + func_name: get_version + process_result: "'$(result)'.split('.')[0]" + store_result: fw_major + +.. code-block:: yaml + :caption: Store the pass/fail status of a test with no return value + + - console: + name: Send command + console_name: device + steps: + - writeln: reboot + - read_until: {expected: "ready", timeout: 10} + store_result: reboot_status + + - py_func: + name: Use reboot status + func_name: log_status + param: [$(reboot_status)] + + Export attribute ----------------------------------------------- diff --git a/src/testium/interpreter/test_items/test_item.py b/src/testium/interpreter/test_items/test_item.py index 4d1c852..7adb8b0 100644 --- a/src/testium/interpreter/test_items/test_item.py +++ b/src/testium/interpreter/test_items/test_item.py @@ -101,6 +101,7 @@ class TestItem: self.status_queue = status_queue self._execute_on_stop = False self._post_eval = None + self._store_result = None self._expected_result = None self._no_fail = None self._is_stopped = False @@ -155,6 +156,9 @@ class TestItem: if "process_result" in dict_item: self._post_eval = dict_item["process_result"] + if "store_result" in dict_item: + self._store_result = dict_item["store_result"] + if "expected_result" in dict_item: self._expected_result = dict_item["expected_result"] @@ -277,6 +281,9 @@ class TestItem: self.process_result() # expected_result treatment self.result_expected() + # Store result in a global variable if requested (before no_fail so + # the real outcome is captured when result.value is None) + self.store_result() # Case of the no_fail true parameter self.process_no_fail() @@ -319,6 +326,17 @@ class TestItem: print(e) self.result.set(TestValue.FAILURE, "Result processing failed") + def store_result(self): + if self._store_result is None: + return + var_name = self._prms.expanse(self._store_result) + if self.result.value is None: + value = str(self.result.test_result) + else: + value = self.result.value + tm.setgd(var_name, value) + print(f"Stored result in '$({var_name})': {value}") + def process_report(self, report_eval): tm.print_debug(f"Export reported values:") rep_eval = self._prms.expanse(report_eval) diff --git a/test/validation/items/common/results/test.tum b/test/validation/items/common/results/test.tum index b4d795d..bfc1215 100644 --- a/test/validation/items/common/results/test.tum +++ b/test/validation/items/common/results/test.tum @@ -99,7 +99,7 @@ file: $(test_path)$(psep)results$(psep)results.py func_name: echo param: [ 44 ] - process_result: "tm.setgd('process_result_value', $(result))" + store_result: process_result_value - py_func: name: Check the saved global variable key: $(test)_PASS @@ -108,6 +108,68 @@ param: [ 44 ] expected_result: $(process_result_value) + - py_func: + name: store_result with process_result + key: $(test)_PASS + file: $(test_path)$(psep)results$(psep)results.py + func_name: echo + param: [ $(str_example) ] + process_result: "'$(result)'.upper()" + store_result: upper_str_example + - py_func: + name: Check store_result with process_result + key: $(test)_PASS + file: $(test_path)$(psep)results$(psep)results.py + func_name: echo + param: [ $(str_example) ] + process_result: "'$(result)'.upper()" + expected_result: $(upper_str_example) + + - let: + name: store_result on let item (None value → stores PASS) + key: $(test)_PASS + values: + - dummy: 0 + store_result: let_store_result + - py_func: + name: Check store_result on let stores PASS + key: $(test)_PASS + file: $(test_path)$(psep)results$(psep)results.py + func_name: echo + param: [PASS] + expected_result: $(let_store_result) + + - py_func: + name: store_result on failing test (None value → stores FAIL) + key: $(test)_FAIL + file: $(test_path)$(psep)results$(psep)results.py + func_name: return_none + expected_result: FAIL + store_result: none_fail_store_result + - py_func: + name: Check store_result on failing test stores FAIL + key: $(test)_PASS + file: $(test_path)$(psep)results$(psep)results.py + func_name: echo + param: [FAIL] + expected_result: $(none_fail_store_result) + + - py_func: + name: store_result with no_fail (None value → stores real FAIL, not forced PASS) + key: $(test)_PASS + file: $(test_path)$(psep)results$(psep)results.py + func_name: return_none + expected_result: FAIL + no_fail: True + store_result: none_nofail_store_result + - py_func: + name: Check store_result with no_fail stores real FAIL + key: $(test)_PASS + file: $(test_path)$(psep)results$(psep)results.py + func_name: echo + param: [FAIL] + expected_result: $(none_nofail_store_result) + - py_func: name: Process result when result is None (must fail) key: $(test)_FAIL