Add store_result common attribute to test items
Allows any test item to store its result (or PASS/FAIL status when result is None) into a named global variable, available to subsequent items via $(variable_name). store_result runs after expected_result but before no_fail so the real outcome is always captured. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -87,6 +87,10 @@ if not provided is given in the table as well.
|
|||||||
| | | see :ref:`Expected result<sec_expected_result>` |
|
| | | see :ref:`Expected result<sec_expected_result>` |
|
||||||
| | | for details. |
|
| | | for details. |
|
||||||
+-----------------------+-------------------+-------------------------------------------------------+
|
+-----------------------+-------------------+-------------------------------------------------------+
|
||||||
|
| ``store_result`` | / | Store the test result in a global variable. |
|
||||||
|
| | | see :ref:`Store result<sec_store_result>` |
|
||||||
|
| | | for details. |
|
||||||
|
+-----------------------+-------------------+-------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
last test result
|
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.
|
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
|
Export attribute
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ class TestItem:
|
|||||||
self.status_queue = status_queue
|
self.status_queue = status_queue
|
||||||
self._execute_on_stop = False
|
self._execute_on_stop = False
|
||||||
self._post_eval = None
|
self._post_eval = None
|
||||||
|
self._store_result = None
|
||||||
self._expected_result = None
|
self._expected_result = None
|
||||||
self._no_fail = None
|
self._no_fail = None
|
||||||
self._is_stopped = False
|
self._is_stopped = False
|
||||||
@@ -155,6 +156,9 @@ class TestItem:
|
|||||||
if "process_result" in dict_item:
|
if "process_result" in dict_item:
|
||||||
self._post_eval = dict_item["process_result"]
|
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:
|
if "expected_result" in dict_item:
|
||||||
self._expected_result = dict_item["expected_result"]
|
self._expected_result = dict_item["expected_result"]
|
||||||
|
|
||||||
@@ -277,6 +281,9 @@ class TestItem:
|
|||||||
self.process_result()
|
self.process_result()
|
||||||
# expected_result treatment
|
# expected_result treatment
|
||||||
self.result_expected()
|
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
|
# Case of the no_fail true parameter
|
||||||
self.process_no_fail()
|
self.process_no_fail()
|
||||||
|
|
||||||
@@ -319,6 +326,17 @@ class TestItem:
|
|||||||
print(e)
|
print(e)
|
||||||
self.result.set(TestValue.FAILURE, "Result processing failed")
|
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):
|
def process_report(self, report_eval):
|
||||||
tm.print_debug(f"Export reported values:")
|
tm.print_debug(f"Export reported values:")
|
||||||
rep_eval = self._prms.expanse(report_eval)
|
rep_eval = self._prms.expanse(report_eval)
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
file: $(test_path)$(psep)results$(psep)results.py
|
file: $(test_path)$(psep)results$(psep)results.py
|
||||||
func_name: echo
|
func_name: echo
|
||||||
param: [ 44 ]
|
param: [ 44 ]
|
||||||
process_result: "tm.setgd('process_result_value', $(result))"
|
store_result: process_result_value
|
||||||
- py_func:
|
- py_func:
|
||||||
name: Check the saved global variable
|
name: Check the saved global variable
|
||||||
key: $(test)_PASS
|
key: $(test)_PASS
|
||||||
@@ -108,6 +108,68 @@
|
|||||||
param: [ 44 ]
|
param: [ 44 ]
|
||||||
expected_result: $(process_result_value)
|
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:
|
- py_func:
|
||||||
name: Process result when result is None (must fail)
|
name: Process result when result is None (must fail)
|
||||||
key: $(test)_FAIL
|
key: $(test)_FAIL
|
||||||
|
|||||||
Reference in New Issue
Block a user