Skip to main content

code-driven-cluster-tdd-implementation

Guidelines for implementing or migrating Matter server clusters to the code-driven pattern using Test-Driven Development (TDD).

Source facts

Repository
project-chip/connectedhomeip
Last source activity
May 15, 2026 at 19:14
Detected SKILL.md language
English
Stars
8,960
Forks
2,486

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
code-driven-cluster-tdd-implementation
description
Guidelines for implementing or migrating Matter server clusters to the code-driven pattern using Test-Driven Development (TDD).
# Code-Driven Cluster TDD Implementation ## When to use this skill 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. ## 1. Prerequisites - Read `code-driven-cluster-development` for core implementation patterns. - Read `matter-specification-access` for instructions on how to access the Matter specification and test plans, so that tests can be based on the spec. - If performing a **migration**, read `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. ## 2. Step-by-Step Implementation Workflow Follow these steps for the substantive implementation using TDD: ### Step 1: Initial Boilerplate & Tests Setup 1. Create the new cluster class inheriting from `DefaultServerCluster`. 2. Create a basic test fixture in `tests/Test<ClusterName>Cluster.cpp` using `ClusterTester`. 3. Verify that the cluster compiles and tests can run (even if empty). ### Step 2: Implement Static Metadata Methods (TDD) 1. **Attributes()**: - Write a **failing** test expecting `Attributes()` to return the list of mandatory attributes. - Implement `Attributes()` using `AttributeListBuilder` and generated metadata. - Verify test passes. 2. **AcceptedCommands()**: - Write a **failing** test expecting `AcceptedCommands()` to return the list of supported commands. - Implement `AcceptedCommands()` returning the list (conditional on features). - Verify test passes. ### Step 3: Implement ReadAttribute (TDD) 1. For each mandatory or supported attribute: - Write a **failing** test reading the attribute via `tester.ReadAttribute()` and expecting a default or mocked value. - Implement the case in `ReadAttribute` switch, fetching data from Delegate or member variables. - Ensure the `default` case returns `Protocols::InteractionModel::Status::UnsupportedAttribute` directly. - Verify test passes. ### Step 4: Implement Writable Attributes and Commands (TDD) For each writable attribute or command, follow this cycle: 1. **Write a Failing Test**: - **Attributes**: Use `tester.WriteAttribute()` and expect failure or success based on setup. - **Commands**: Invoke via `tester.Invoke()` and assert failure (e.g., `UnsupportedCommand`). 2. **Implement**: - Add the case in `WriteAttribute` or `InvokeCommand` switch. - Decode the payload. - Execute logic (update state or call delegate). - Return `UnsupportedAttribute` or `UnsupportedCommand` in the `default` case. 3. **Verify Success**: Run tests and ensure they pass. ### Step 5: Create CodegenIntegration Layer 1. Create or update `CodegenIntegration.h` and `.cpp` in the cluster folder. 2. Provide implementations for generated callbacks (e.g., `Matter<ClusterName>ClusterInitCallback`). 3. Use `CodegenClusterIntegration::RegisterServer` to bridge ZAP defaults to the new cluster instance. 4. Maintain legacy classes (e.g., `ChimeServer`) as proxy wrappers if needed for backward compatibility. ### Step 6: Verification & ZAP Regen 1. Run all unit tests. 2. Update `config-data.yaml` and `zcl.json` as per `code-driven-cluster-migration` skill. 3. Run `zap_regen_all.py` and commit all generated files. 4. **Integration Testing**: Build an example app and test against `chip-tool`. 5. **Verify Spec Conformance**: Refer to the relevant cluster specification `.adoc` file. 6. **Verify Against Test Plan**: Refer to the relevant test plan `.adoc` file. ## 4. Common TDD Scenarios ### 4.1 Security Checks (CASE/FailSafe) - **Failing Test**: Use `tester.SetSubjectDescriptor()` to simulate non-CASE session, or don't arm FailSafe, and expect specific error (`UnsupportedAccess`, `FailsafeRequired`). - **Implementation**: Add checks at top of `InvokeCommand`. ### 4.2 Async Completion & Breadcrumbs - **Failing Test**: Mock the async callback and verify that side effects (like setting breadcrumb via `BreadCrumbTracker`) occur. - **Implementation**: Use the appropriate interface or callback (e.g., `OnCommandNameComplete`) to handle side effects. Return `Status::UnsupportedCommand` for unknown commands in `InvokeCommand`. ### 4.3 Timer-Driven Logic - **Failing Test**: Verify that time passes and state changes (e.g., `IdentifyTime` decrements). - **Mocking**: Do NOT use `sleep()`. Use `TimerDelegate` and `TimerDelegateMock` to advance the mock clock and trigger timer callbacks synchronously. ### 4.4 List Attributes - **Failing Test**: Read the list attribute and verify its contents. - **Implementation**: Use `ListEncodeHelper` and delegate methods to fetch items by index and encode them. ### 4.5 Handling Platform Events - **Failing Test**: Write tests that trigger specific platform events (e.g., `kFailSafeTimerExpired`) directly on the platform event handler and verify expected side effects. - **Implementation**: Implement `OnPlatformEventHandler` and hook it up in `Startup`/`Shutdown` to listen for needed events. ## 5. Best Practices for Test Design - **Focused Tests**: Keep tests small and focused on a single requirement. Avoid monolithic tests that verify multiple behaviors at once. - **Isolation**: Use mocks (e.g., `MockDelegate`, `MockBreadcrumbTracker`) to isolate cluster logic from platform dependencies. This ensures tests are fast and deterministic. - **Edge Cases**: Always test boundary values (min/max) and invalid inputs to verify spec compliance and error handling. ## 6. Common Commands Reference ### Environment Activation ```bash source scripts/activate.sh ``` Or run commands directly in the environment: ```bash scripts/run_in_build_env.sh "<command>" ``` ### Running Unit Tests To compile and run a specific cluster test: ```bash scripts/run_in_build_env.sh "ninja -C out/linux-x64-tests-clang src/app/clusters/<cluster-folder>/tests:Test<ClusterName>Cluster.run" ``` ### ZAP Regeneration To regenerate files after updating templates or ZCL JSON: ```bash scripts/run_in_build_env.sh "scripts/tools/zap_regen_all.py" ```
View on GitHub