Allow groupId to be a variable in YAML tests. (#29641)

This allows targeting group messages at a group id that's a config define.

Fixes https://github.com/project-chip/connectedhomeip/issues/29637
diff --git a/scripts/py_matter_yamltests/matter_yamltests/parser.py b/scripts/py_matter_yamltests/matter_yamltests/parser.py
index 18e643d..ec4462b 100644
--- a/scripts/py_matter_yamltests/matter_yamltests/parser.py
+++ b/scripts/py_matter_yamltests/matter_yamltests/parser.py
@@ -593,6 +593,8 @@
                 self._test.event)
             self._test.endpoint = self._config_variable_substitution(
                 self._test.endpoint)
+            self._test.group_id = self._config_variable_substitution(
+                self._test.group_id)
             test.update_arguments(self.arguments)
             test.update_responses(self.responses)
 
diff --git a/scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py b/scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py
index d798ef5..aba7315 100644
--- a/scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py
+++ b/scripts/py_matter_yamltests/matter_yamltests/yaml_loader.py
@@ -91,7 +91,7 @@
             'identity': str,
             'nodeId': int,
             'runIf': str,  # Should be a variable.
-            'groupId': int,
+            'groupId': (int, str),  # Can be a variable.
             'endpoint': (int, str),  # Can be a variable
             'cluster': str,
             'attribute': str,
diff --git a/scripts/py_matter_yamltests/test_yaml_loader.py b/scripts/py_matter_yamltests/test_yaml_loader.py
index d0078a8..41929d9 100644
--- a/scripts/py_matter_yamltests/test_yaml_loader.py
+++ b/scripts/py_matter_yamltests/test_yaml_loader.py
@@ -247,7 +247,6 @@
                    '  - {key}: {value}')
         keys = [
             'nodeId',
-            'groupId',
             'minInterval',
             'maxInterval',
             'timedInteractionTimeoutMs',
@@ -324,6 +323,23 @@
             x = content.format(value=value)
             self.assertRaises(TestStepInvalidTypeError, load, x)
 
+    def test_key_tests_step_group_id_key(self):
+        load = YamlLoader().load
+
+        content = ('tests:\n'
+                   '  - groupId: {value}')
+
+        _, _, _, _, tests = load(content.format(value=1))
+        self.assertEqual(tests, [{'groupId': 1}])
+
+        _, _, _, _, tests = load(content.format(value='TestKey'))
+        self.assertEqual(tests, [{'groupId': 'TestKey'}])
+
+        wrong_values = self._get_wrong_values([str, int], spaces=6)
+        for value in wrong_values:
+            x = content.format(value=value)
+            self.assertRaises(TestStepInvalidTypeError, load, x)
+
     def test_key_tests_step_event_number_key(self):
         load = YamlLoader().load
 
diff --git a/src/app/tests/suites/TestGroupMessaging.yaml b/src/app/tests/suites/TestGroupMessaging.yaml
index 74aeef6..89935b6 100644
--- a/src/app/tests/suites/TestGroupMessaging.yaml
+++ b/src/app/tests/suites/TestGroupMessaging.yaml
@@ -22,6 +22,10 @@
     nodeId: 0x12344321
     cluster: "Basic Information"
     endpoint: 0
+    # Test that a group id can be a variable.
+    groupIdVariable:
+        type: int16u
+        defaultValue: 0x0101
     nodeId2:
         type: node_id
         defaultValue: 0x43211234
@@ -215,7 +219,7 @@
     - label: "Turn On the light to see attribute change"
       cluster: "On/Off"
       command: "On"
-      groupId: 0x0101
+      groupId: groupIdVariable # 0x0101
 
     # Give the group invoke time to actually happen; unicast delivery can outrace
     # multicast if the unicast packet is sent immediately after the multicast one.