Use this skill when implementing or migrating Matter server clusters to the code-driven pattern using Test-Driven Development (TDD).
[!IMPORTANT] > Preserve Legacy Behavior: If migrating an existing cluster, constantly refer to the legacy code to ensure no functional drop or unexpected behavior changes.
code-driven-cluster-development for core implementation patterns.matter-specification-access for instructions on how to access the Matter specification and test plans, so that tests can be based on the spec.code-driven-cluster-migration for general migration steps (renaming, directory layout). We assume you have already completed Phase 1 (Renames) and Phase 2 (Moves) before starting the TDD implementation.Follow these steps for the substantive implementation using TDD:
DefaultServerCluster.tests/Test<ClusterName>Cluster.cpp using ClusterTester.Attributes() to return the list of mandatory attributes.Attributes() using AttributeListBuilder and generated metadata.AcceptedCommands() to return the list of supported commands.AcceptedCommands() returning the list (conditional on features).tester.ReadAttribute() and expecting a default or mocked value.ReadAttribute switch, fetching data from Delegate or member variables.default case returns Protocols::InteractionModel::Status::UnsupportedAttribute directly.For each writable attribute or command, follow this cycle:
tester.WriteAttribute() and expect failure or success based on setup.tester.Invoke() and assert failure (e.g., UnsupportedCommand).WriteAttribute or InvokeCommand switch.UnsupportedAttribute or UnsupportedCommand in the default case.CodegenIntegration.h and .cpp in the cluster folder.Matter<ClusterName>ClusterInitCallback).CodegenClusterIntegration::RegisterServer to bridge ZAP defaults to the new cluster instance.ChimeServer) as proxy wrappers if needed for backward compatibility.config-data.yaml and zcl.json as per code-driven-cluster-migration skill.zap_regen_all.py and commit all generated files.chip-tool..adoc file..adoc file.tester.SetSubjectDescriptor() to simulate non-CASE session, or don't arm FailSafe, and expect specific error (UnsupportedAccess, FailsafeRequired).InvokeCommand.BreadCrumbTracker) occur.OnCommandNameComplete) to handle side effects. Return Status::UnsupportedCommand for unknown commands in InvokeCommand.IdentifyTime decrements).sleep(). Use TimerDelegate and TimerDelegateMock to advance the mock clock and trigger timer callbacks synchronously.ListEncodeHelper and delegate methods to fetch items by index and encode them.kFailSafeTimerExpired) directly on the platform event handler and verify expected side effects.OnPlatformEventHandler and hook it up in Startup/Shutdown to listen for needed events.MockDelegate, MockBreadcrumbTracker) to isolate cluster logic from platform dependencies. This ensures tests are fast and deterministic.source scripts/activate.sh
Or run commands directly in the environment:
scripts/run_in_build_env.sh "<command>"
To compile and run a specific cluster test:
scripts/run_in_build_env.sh "ninja -C out/linux-x64-tests-clang src/app/clusters/<cluster-folder>/tests:Test<ClusterName>Cluster.run"
To regenerate files after updating templates or ZCL JSON:
scripts/run_in_build_env.sh "scripts/tools/zap_regen_all.py"