C Freeman | 9bde938 | 2024-01-23 03:29:24 -0500 | [diff] [blame] | 1 | # YAML tests |
| 2 | |
| 3 | YAML is a structured, human-readable data-serialization language. Much like json |
| 4 | or proto, YAML refers to the structure and parser, and the schema used for any |
| 5 | particular application is defined by the application. |
| 6 | |
| 7 | In Matter, we use YAML for describing tests and test steps. A YAML parser and |
| 8 | runner is then used to translate the YAML instructions into actions used to |
| 9 | interact with the device under test (DUT). |
| 10 | |
| 11 | The main runner we use for testing in Matter parses the YAML instructions into |
| 12 | chip-tool commands. |
| 13 | |
| 14 | The schema description for the Matter test YAML is available here: |
| 15 | [YAML Schema](./yaml_schema.md) |
| 16 | |
| 17 | ## Writing YAML tests |
| 18 | |
| 19 | Most YAML tests are written for certification. These follow a standard format |
| 20 | that is used to display the test easily in the test harness. |
| 21 | |
| 22 | ### Placeholder for anatomy of a yaml test - need diagram |
| 23 | |
| 24 | ### Placeholder for anatomy of a test step - need diagram |
| 25 | |
| 26 | ### Common actions |
| 27 | |
| 28 | #### Sending a cluster command |
| 29 | |
| 30 | The following shows a test step sending a simple command with no arguments. |
| 31 | |
| 32 | ``` |
| 33 | - label: "This label gets printed" |
| 34 | cluster: "On/Off" |
| 35 | command: "On" |
| 36 | ``` |
| 37 | |
| 38 | - label - label to print before performing the test step |
| 39 | - cluster - name of the cluster to send the command to |
| 40 | - command - name of the command to send |
| 41 | |
| 42 | This send the On command to the On/Off cluster on the DUT. For most tests, the |
| 43 | nodeID of the DUT and endpoint for the cluster are defined in the top-level |
| 44 | config section of the file and applied to every test step. However, these can |
| 45 | also be overwritten in the individual test steps. |
| 46 | |
| 47 | The following shows how to send a command with arguments: |
| 48 | |
| 49 | ``` |
| 50 | - label: "This label gets printed before the test step" |
| 51 | command: "MoveToColor" |
| 52 | arguments: |
| 53 | values: |
| 54 | - name: "ColorX" |
| 55 | value: 32768 |
| 56 | - name: "ColorY" |
| 57 | value: 19660 |
| 58 | - name: "TransitionTime" |
| 59 | value: 0 |
| 60 | - name: "OptionsMask" |
| 61 | value: 0 |
| 62 | - name: "OptionsOverride" |
| 63 | value: 0 |
| 64 | ``` |
| 65 | |
| 66 | - label - label to print before performing the test step |
| 67 | - command - name of the command to send |
| 68 | - argument - this is a list parameter that takes either a "value" or "values" |
| 69 | tag. Commands with arguments all use structured fields, which require the |
| 70 | "values" tag with a list. Each of the fields is represented by a "name" and |
| 71 | "value" pair |
| 72 | |
| 73 | In this command, the cluster: tag is elided. The cluster for the entire test can |
| 74 | be set in the config section at the top of the test. This can be overwritten for |
| 75 | individual test steps (as above). |
| 76 | |
| 77 | #### Reading and writing attributes |
| 78 | |
| 79 | Reading and writing attributes is represented in the Matter test YAML schemas as |
| 80 | a special command that requires an additional "attribute" tag. |
| 81 | |
| 82 | The following YAML would appear as a test step, and shows how to read an |
| 83 | attribute. |
| 84 | |
| 85 | ``` |
| 86 | - label: "TH reads the ClusterRevision from DUT" |
| 87 | command: "readAttribute" |
| 88 | attribute: "ClusterRevision" |
| 89 | ``` |
| 90 | |
| 91 | The following YAML would appear as a test step and shows how to write an |
| 92 | attribute. Commands to write attributes always require an argument: tag. |
| 93 | |
| 94 | ``` |
| 95 | - label: "Write example attribute" |
| 96 | command: "writeAttribute" |
| 97 | attribute: "ExampleAttribute" |
| 98 | arguments: |
| 99 | value: 1 |
| 100 | ``` |
| 101 | |
| 102 | #### Parsing Responses |
| 103 | |
| 104 | After sending a command or read or write attribute request, you may want to |
| 105 | verify the response. This is done using the "response" tag with various |
| 106 | sub-tags. |
| 107 | |
| 108 | The following shows a simple response parsing with two (somewhat redundant) |
| 109 | checks. |
| 110 | |
| 111 | ``` |
| 112 | - label: "TH reads the ClusterRevision from DUT" |
| 113 | command: "readAttribute" |
| 114 | attribute: "ClusterRevision" |
| 115 | response: |
| 116 | value: 1 |
| 117 | constraints: |
| 118 | minValue: 1 |
| 119 | ``` |
| 120 | |
| 121 | The following tags can be used to parse the response |
| 122 | |
| 123 | | Example | Description | |
| 124 | | :---------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------- | |
| 125 | | response:<br /> value: [1, 2, 3, 4] | must match exactly. Variables and saveAs values allowed | |
| 126 | | response:<br /> values:<br />  - name: response_field<br />   value: 1 | Must match exactly<br />Use for commands that return command responses with named fields | |
| 127 | | response:<br />   error: CONSTRAINT_ERROR | expect an error back (omit for success)<br />Variables and saveAs values will not work. | |
| 128 | | response:<br /> constraints: | more complex checks - see [Schema](./yaml_schema.md) for a complete description | |
| 129 | |
| 130 | #### Lists and structs |
| 131 | |
| 132 | Lists and structs can be represented as follows: |
| 133 | |
| 134 | Lists: `[1,2,3,4,5]` |
| 135 | |
| 136 | structs: `{field1:value, field2:value}` |
| 137 | |
| 138 | lists of structs: |
| 139 | |
| 140 | ``` |
| 141 | [ |
| 142 | |
| 143 | {field1:value, field2:value, optionalfield:value}, |
| 144 | |
| 145 | {field1:value, field2:value}, |
| 146 | |
| 147 | ] |
| 148 | ``` |
| 149 | |
| 150 | Note that structs are different than command and command response fields, which |
| 151 | are represented using name:, value: tags. |
| 152 | |
| 153 | #### Pseudo clusters |
| 154 | |
| 155 | Tests often require functionality that is not strictly cluster-based. Some of |
| 156 | this functionality is supported in YAML using pseudo-clusters. These clusters |
| 157 | accept command: tags like the DUT clusters to control the pseudo-cluster |
| 158 | functionality. |
| 159 | |
| 160 | Some of the more common functionality is shown below: |
| 161 | |
| 162 | Establishing a connection to the DUT. This is the first step in nearly every |
| 163 | test. |
| 164 | |
| 165 | ``` |
| 166 | - label: "Establish a connection to the DUT" |
| 167 | cluster: "DelayCommands" |
| 168 | command: "WaitForCommissionee" |
| 169 | arguments: |
| 170 | values: |
| 171 | - name: "nodeId" |
| 172 | value: nodeId |
| 173 | ``` |
| 174 | |
| 175 | Wait for a user action: |
| 176 | |
| 177 | ``` |
| 178 | - label: "Do a simple user prompt message. Expect 'y' to pass." |
| 179 | cluster: "LogCommands" |
| 180 | command: "UserPrompt" |
| 181 | arguments: |
| 182 | values: |
| 183 | - name: "message" |
| 184 | value: "Please enter 'y' for success" |
| 185 | - name: "expectedValue" |
| 186 | value: "y" |
| 187 | ``` |
| 188 | |
| 189 | Wait for a time: |
| 190 | |
| 191 | ``` |
| 192 | - label: "Wait for 5S" |
| 193 | cluster: "DelayCommands" |
| 194 | command: "WaitForMs" |
| 195 | arguments: |
| 196 | values: |
| 197 | - name: "ms" |
| 198 | value: 5000 |
| 199 | ``` |
| 200 | |
| 201 | A full description of the available pseudo-clusters and their commands is |
| 202 | available at [Pseudo-cluster description](./yaml_pseudocluster.md). |
| 203 | |
| 204 | #### Config variables and saveAs: |
| 205 | |
| 206 | Certain tags can use variables that are either declared in the config: section |
| 207 | or saved from other steps. Variables that are declared in the config can be |
| 208 | overwritten on the command line when running locally or through the config file |
| 209 | in the test harness. |
| 210 | |
| 211 | To declare config variables in the config section, use a label with the desired |
| 212 | name, then provide the type and defaultValue tags as sub-tags. |
| 213 | |
| 214 | ``` |
| 215 | config: |
| 216 | nodeId: 0x12344321 |
| 217 | cluster: "Unit Testing" |
| 218 | endpoint: 1 |
| 219 | myArg1: |
| 220 | type: int8u |
| 221 | defaultValue: 5 |
| 222 | ``` |
| 223 | |
| 224 | Variables can also be saved from responses: |
| 225 | |
| 226 | ``` |
| 227 | - label: "Send Test Add Arguments Command" |
| 228 | command: "TestAddArguments" |
| 229 | arguments: |
| 230 | values: |
| 231 | - name: "arg1" |
| 232 | value: 3 |
| 233 | - name: "arg2" |
| 234 | value: 17 |
| 235 | response: |
| 236 | values: |
| 237 | - name: "returnValue" |
| 238 | saveAs: TestAddArgumentDefaultValue |
| 239 | value: 20 |
| 240 | ``` |
| 241 | |
| 242 | Variables can then be used in later steps: |
| 243 | |
| 244 | ``` |
| 245 | - label: "Send Test Add Arguments Command" |
| 246 | command: "TestAddArguments" |
| 247 | arguments: |
| 248 | values: |
| 249 | - name: "arg1" |
| 250 | value: 3 |
| 251 | - name: "arg2" |
| 252 | value: 17 |
| 253 | response: |
| 254 | values: |
| 255 | - name: "returnValue" |
| 256 | value: TestAddArgumentDefaultValue |
| 257 | ``` |
| 258 | |
| 259 | Tags where variables can be used are noted in the |
| 260 | [schema description](./yaml_schema.md). |
| 261 | |
| 262 | Config variables can be used to implement PIXIT values in tests. |
| 263 | |
| 264 | #### Gating tests and steps: PICS, TestEqualities and runIf |
| 265 | |
| 266 | The PICS tag can be used to unconditionally gate a test step on the PICS value |
| 267 | in the file. |
| 268 | |
| 269 | The PICS tag can handle standard boolean operations on pics (!, ||, &&, ()). |
| 270 | |
| 271 | A PICS tag at the top level of the file can be used to gate the entire test in |
| 272 | the test harness. Note that full-test gating is not currently implemented in the |
| 273 | local runner or in the CI. |
| 274 | |
| 275 | Some test steps need to be gated on values from earlier in the test. In these |
| 276 | cases, PICS cannot be used. Instead, the runIf: tag can be used. This tag |
| 277 | requires a boolean value. To convert values to booleans, the TestEqualities |
| 278 | function can be use. See |
| 279 | [TestEqualities](https://github.com/project-chip/connectedhomeip/blob/master/src/app/tests/suites/TestEqualities.yaml) |
| 280 | for an example of how to use this pseudo-cluster. |
| 281 | |
C Freeman | a98dc79 | 2024-05-28 16:00:15 -0400 | [diff] [blame] | 282 | #### Setting step timeouts |
| 283 | |
| 284 | The timeout argument can be used for each individual test step to set the time |
| 285 | the runner will wait for a test step to complete before reporting a failure. |
| 286 | |
| 287 | Note that this timeout is different than the subscription report timeout and the |
| 288 | subscription report timeout is not currently adjustable in YAML. |
| 289 | |
| 290 | There several other options for configuring test steps as shown in the |
| 291 | [YAML schema](./yaml_schema.md) document. |
| 292 | |
C Freeman | 9bde938 | 2024-01-23 03:29:24 -0500 | [diff] [blame] | 293 | ## Running YAML tests |
| 294 | |
| 295 | YAML scripts are parsed and run using a python-based runner program that parses |
| 296 | the file, then translates the tags into chip-tool commands, and sends those |
| 297 | commands over a socket to chip-tool (running in interactive mode). |
| 298 | |
| 299 | ### Running locally |
| 300 | |
| 301 | #### Commissioning the DUT |
| 302 | |
| 303 | All YAML tests assume that the DUT has previously been commissioned before |
| 304 | running. DUTs should be commissioned using chip-tool. Use the same KVS file when |
| 305 | running the test. |
| 306 | |
C Freeman | fe889bd | 2024-03-27 13:31:24 -0400 | [diff] [blame] | 307 | By default, the tests use node ID 0x12344321. The easiest way to run the tests |
| 308 | is to commission with this node ID. Alternately, you can change the target node |
| 309 | ID on the command line, as shown in the [Running the tests](#running-the-tests) |
| 310 | section. |
| 311 | |
C Freeman | 9bde938 | 2024-01-23 03:29:24 -0500 | [diff] [blame] | 312 | #### Running the tests |
| 313 | |
| 314 | There are several options for running tests locally. Because the YAML runner |
| 315 | uses python, it is necessary to compile and install the chip python package |
| 316 | before using any YAML runner script. |
| 317 | |
C Freeman | a98dc79 | 2024-05-28 16:00:15 -0400 | [diff] [blame] | 318 | First activate the matter environment using either |
| 319 | |
| 320 | ``` |
| 321 | . ./scripts/bootstrap.sh |
| 322 | ``` |
| 323 | |
| 324 | or |
| 325 | |
| 326 | ``` |
| 327 | . ./scripts/activate.sh |
| 328 | ``` |
| 329 | |
| 330 | bootstrap.sh should be used for for the first setup, activate.sh may be used for |
| 331 | subsequent setups as it is faster. |
| 332 | |
| 333 | Next build the python wheels and create a venv (called `py` here, but any name |
| 334 | may be used) |
| 335 | |
C Freeman | 9bde938 | 2024-01-23 03:29:24 -0500 | [diff] [blame] | 336 | ``` |
| 337 | ./scripts/build_python.sh -i py |
| 338 | source py/bin/activate |
| 339 | ``` |
| 340 | |
| 341 | Compile chip-tool: |
| 342 | |
| 343 | ``` |
| 344 | ./scripts/build/build_examples.py --target linux-x64-chip-tool build |
| 345 | |
| 346 | ``` |
| 347 | |
| 348 | NOTE: use the target appropriate to your system |
| 349 | |
Vatsal Ghelani | 7a6ea3e | 2024-06-14 21:49:52 -0400 | [diff] [blame] | 350 | [chiptool.py](https://github.com/project-chip/connectedhomeip/blob/master/scripts/tests/chipyaml/chiptool.py) |
C Freeman | 9bde938 | 2024-01-23 03:29:24 -0500 | [diff] [blame] | 351 | can be used to run tests against a commissioned DUT (commissioned by chip-tool). |
C Freeman | ec8ee38 | 2024-06-19 11:49:06 -0400 | [diff] [blame] | 352 | To commission a DUT using chip-tool use the pairing command. For example: |
| 353 | |
| 354 | ``` |
| 355 | ./out/linux-x64-chip-tool/chip-tool pairing code 0x12344321 MT:-24J0AFN00KA0648G00 |
| 356 | ``` |
| 357 | |
| 358 | In this example, 0x12344321 is the node ID (0x12344321 is the test default) and |
| 359 | MT:-24J0AFN00KA0648G00 is the QR code. |
| 360 | |
| 361 | The chiptool.py tool can then be used to run the tests. For example: |
C Freeman | 9bde938 | 2024-01-23 03:29:24 -0500 | [diff] [blame] | 362 | |
| 363 | ``` |
Vatsal Ghelani | 7a6ea3e | 2024-06-14 21:49:52 -0400 | [diff] [blame] | 364 | ./scripts/tests/chipyaml/chiptool.py tests Test_TC_OO_2_1 --server_path ./out/linux-x64-chip-tool/chip-tool |
C Freeman | 9bde938 | 2024-01-23 03:29:24 -0500 | [diff] [blame] | 365 | |
| 366 | ``` |
| 367 | |
| 368 | NOTE: substitute the appropriate test name and chip-tool path as appropriate. |
| 369 | |
| 370 | A list of available tests can be generated using: |
| 371 | |
| 372 | ``` |
Vatsal Ghelani | 7a6ea3e | 2024-06-14 21:49:52 -0400 | [diff] [blame] | 373 | ./scripts/tests/chipyaml/chiptool.py list |
C Freeman | 9bde938 | 2024-01-23 03:29:24 -0500 | [diff] [blame] | 374 | ``` |
| 375 | |
| 376 | Config variables can be passed to chiptool.py after the script by separating |
| 377 | with -- |
| 378 | |
| 379 | ``` |
Vatsal Ghelani | 7a6ea3e | 2024-06-14 21:49:52 -0400 | [diff] [blame] | 380 | ./scripts/tests/chipyaml/chiptool.py tests Test_TC_OO_2_1 --server_path ./out/linux-x64-chip-tool/chip-tool -- nodeId 0x12344321 |
C Freeman | 9bde938 | 2024-01-23 03:29:24 -0500 | [diff] [blame] | 381 | |
| 382 | ``` |
| 383 | |
C Freeman | fe889bd | 2024-03-27 13:31:24 -0400 | [diff] [blame] | 384 | Each test defines a default endpoint to target. Root node cluster tests run |
| 385 | against endpoint 0 by default. Most other cluster tests run against endpoint 1. |
| 386 | You can set the endpoint for the test using the `endpoint` config variable. |
| 387 | |
C Freeman | 9bde938 | 2024-01-23 03:29:24 -0500 | [diff] [blame] | 388 | #### Factory resetting the DUT |
| 389 | |
| 390 | On the host machine, you can simulate a factory reset by deleting the KVS file. |
| 391 | If you did not specify a location for the KVS file when starting the |
| 392 | application, the KVS file will be in /tmp as chip_kvs |
| 393 | |
| 394 | ### Running in the CI |
| 395 | |
| 396 | - YAML tests added to the certification directory get run automatically |
| 397 | - src/app/tests/suites/certification/ |
| 398 | - PICS file: src/app/tests/suites/certification/ci-pics-values |
| 399 | - If you DON’T want to run a test in the CI |
| 400 | - (ex under development), add it to \_GetInDevelopmentTests in |
| 401 | `scripts/tests/chiptest/__init__.py` |
| 402 | |
| 403 | Please see [CI testing](./ci_testing.md) for more information about how to set |
| 404 | up examples apps, PICS and PIXIT values for use in the CI. |
| 405 | |
| 406 | ### Running in the TH |
| 407 | |
| 408 | TODO: Do we have a permanent link to the most up to date TH documentation? If |
| 409 | so, add here. |