Files
esphome/tests/components
J. Nick Koston 370cfb8898 [noise] Generate the responder ephemeral key ahead of the handshake
The responder's ephemeral key pair was generated inside the handshake
write step, a base point multiply of about 60 ms on ESP8266 that every
connecting client waited for. The noise component now keeps one spare key
pair (64 bytes of static storage, only in builds with an encrypted api
since the api server is the only refiller), the api server refills it from
loop() once the network is up and no api client is mid handshake, and both
the api and ota handshakes take it through noise-c's
noise_handshakestate_set_local_ephemeral(). A handshake that finds the
slot empty, or whose spare noise-c refuses, generates its own key as
before. The host gtest suite covers the slot's single use, the key pair's
consistency, and a full handshake whose message carries the supplied key.
2026-09-07 00:17:20 +02:00
..
2026-04-06 21:59:05 -10:00
2026-09-01 07:13:36 +10:00
2026-01-29 22:48:16 -05:00
2025-09-26 08:53:21 +12:00
2025-11-23 21:25:24 -06:00

How to write C++ ESPHome unit tests

  1. Locate the folder with your component or create a new one with the same name as the component.
  2. Write the tests. You can add as many .cpp and .h files as you need to organize your tests.

IMPORTANT: wrap all your testing code in a unique namespace to avoid linker collisions when compiling testing binaries that combine many components. By convention, this unique namespace is esphome::component::testing (where "component" is the component under test), for example: esphome::uart::testing.

Platform components

For components that expose to a platform component, create a folder under your component test folder with the platform component name, e.g. binary_sensor and include the relevant .cpp and .h test files there.

Override component code generation for testing

During C++ test builds, to_code is suppressed for every component by default — most components do not need to generate configuration code for a unit test binary.

Manifest overrides

If your component needs to customise code generation behavior for testing — for example to re-enable to_code, supply a lightweight stub, add a test-only dependency, or change any other manifest attribute — create an __init__.py in your component's test directory and define override_manifest:

Top-level component (tests/components/<component>/__init__.py):

from tests.testing_helpers import ComponentManifestOverride


def override_manifest(manifest: ComponentManifestOverride) -> None:
    # Re-enable the component's own to_code (needed when the component must
    # emit C++ setup code that the test binary depends on at link time).
    manifest.enable_codegen()

Or supply a lightweight stub instead of the real to_code:

from tests.testing_helpers import ComponentManifestOverride


def override_manifest(manifest: ComponentManifestOverride) -> None:
    async def to_code_testing(config):
        # Only emit what the C++ tests actually need
        pass

    manifest.to_code = to_code_testing
    manifest.dependencies = manifest.dependencies + ["some_test_only_dep"]

Platform component (tests/components/<component>/<domain>/__init__.py, e.g. tests/components/my_sensor/sensor/__init__.py):

from tests.testing_helpers import ComponentManifestOverride


def override_manifest(manifest: ComponentManifestOverride) -> None:
    manifest.enable_codegen()

override_manifest receives a ComponentManifestOverride that wraps the real manifest. Attribute assignments store an override; reads fall back to the real manifest when no override is present.

Key methods:

Method Effect
manifest.enable_codegen() Remove the to_code suppression, re-enabling code generation
manifest.restore() Clear all overrides, reverting every attribute to the original

The function is called after to_code has already been set to None, so calling enable_codegen() is a deliberate opt-in.

Running component unit tests

(from the repository root)

./script/cpp_unit_test.py component1 component2 ...

The above will compile and run the provided components and their tests.

To run all tests, you can invoke cpp_unit_test.py with the special --all flag:

./script/cpp_unit_test.py --all

To run a specific test suite, you can provide a Google Test filter:

GTEST_FILTER='UART*' ./script/cpp_unit_test.py uart modbus

The process will return 0 for success or nonzero for failure. In case of failure, the errors will be printed out to the console.