[mipi_spi] Cache code generation across display tests

The native.yaml and lvgl.yaml fixtures are each compiled twice; once by
the codegen assertions in test_init.py and once by the metadata
assertions in test_display_metadata.py. Add a session scoped cache so
each fixture is generated once, with the resulting main.cpp text and a
snapshot of the display metadata reused across tests. CI hits the
duplicated tests in well under 10ms instead of paying the full
generation cost a second time.
This commit is contained in:
J. Nick Koston
2026-05-22 08:32:57 -05:00
parent 99de741f99
commit 9efc327622
3 changed files with 44 additions and 10 deletions

View File

@@ -1,11 +1,13 @@
"""Tests for mpip_spi configuration validation."""
from collections.abc import Callable, Generator
from pathlib import Path
from unittest import mock
import pytest
from esphome import config_validation as cv
from esphome.components.display import DisplayMetaData, get_all_display_metadata
from esphome.components.esp32 import KEY_ESP32, KEY_VARIANT, VARIANTS
from esphome.components.esp32.gpio import validate_gpio_pin
from esphome.const import CONF_INPUT, CONF_OUTPUT
@@ -23,6 +25,40 @@ def mock_spi_final_validate():
yield
@pytest.fixture(scope="session")
def _generation_cache() -> dict[Path, tuple[str, dict[str, DisplayMetaData]]]:
"""Session-wide cache of generation output keyed by fixture yaml path.
Stores ``(main_cpp_text, display_metadata_snapshot)`` so multiple tests
that exercise the same fixture only pay for code generation once.
"""
return {}
@pytest.fixture
def cached_generate_main(
generate_main: Callable[[str | Path], str],
_generation_cache: dict[Path, tuple[str, dict[str, DisplayMetaData]]],
) -> Callable[[Path], tuple[str, dict[str, DisplayMetaData]]]:
"""Like ``generate_main`` but caches results across the test session.
Returns ``(main_cpp_text, display_metadata_snapshot)``; the snapshot is
captured at generation time so callers see the same data after CORE has
been reset for the next test.
"""
def _get(path: Path) -> tuple[str, dict[str, DisplayMetaData]]:
path = Path(path)
cached = _generation_cache.get(path)
if cached is None:
main_cpp = generate_main(path)
cached = (main_cpp, dict(get_all_display_metadata()))
_generation_cache[path] = cached
return cached
return _get
@pytest.fixture
def choose_variant_with_pins() -> Generator[Callable[[list], None]]:
"""

View File

@@ -173,12 +173,11 @@ def test_metadata_multiple_displays_independent(
def test_metadata_via_code_generation_native(
generate_main: Callable[[str | Path], str],
cached_generate_main: Callable[[Path], tuple[str, dict[str, DisplayMetaData]]],
component_fixture_path: Callable[[str], Path],
) -> None:
"""Full code generation for native.yaml should produce correct metadata."""
generate_main(component_fixture_path("native.yaml"))
all_meta = get_all_display_metadata()
_, all_meta = cached_generate_main(component_fixture_path("native.yaml"))
# native.yaml: model JC3636W518 -> 360x360, no writer, full hardware rotation
assert len(all_meta) == 1
meta = next(iter(all_meta.values()))
@@ -188,12 +187,11 @@ def test_metadata_via_code_generation_native(
def test_metadata_via_code_generation_lvgl(
generate_main: Callable[[str | Path], str],
cached_generate_main: Callable[[Path], tuple[str, dict[str, DisplayMetaData]]],
component_fixture_path: Callable[[str], Path],
) -> None:
"""Full code generation for lvgl.yaml should produce correct metadata."""
generate_main(component_fixture_path("lvgl.yaml"))
all_meta = get_all_display_metadata()
_, all_meta = cached_generate_main(component_fixture_path("lvgl.yaml"))
# lvgl.yaml: model ST7735 -> 128x160, no writer (lvgl draws directly), full hw rotation
assert len(all_meta) == 1
meta = next(iter(all_meta.values()))

View File

@@ -307,12 +307,12 @@ def test_all_predefined_models(
def test_native_generation(
generate_main: Callable[[str | Path], str],
cached_generate_main: Callable[[Path], tuple[str, dict[str, Any]]],
component_fixture_path: Callable[[str], Path],
) -> None:
"""Test code generation for display."""
main_cpp = generate_main(component_fixture_path("native.yaml"))
main_cpp, _ = cached_generate_main(component_fixture_path("native.yaml"))
assert (
"mipi_spi::MipiSpiBuffer<uint16_t, mipi_spi::PIXEL_MODE_16, true, mipi_spi::PIXEL_MODE_16, mipi_spi::BUS_TYPE_QUAD, 360, 360, 0, 1, 0, true, 1, 1>()"
in main_cpp
@@ -323,12 +323,12 @@ def test_native_generation(
def test_lvgl_generation(
generate_main: Callable[[str | Path], str],
cached_generate_main: Callable[[Path], tuple[str, dict[str, Any]]],
component_fixture_path: Callable[[str], Path],
) -> None:
"""Test LVGL generation configuration."""
main_cpp = generate_main(component_fixture_path("lvgl.yaml"))
main_cpp, _ = cached_generate_main(component_fixture_path("lvgl.yaml"))
assert (
"mipi_spi::MipiSpi<uint16_t, mipi_spi::PIXEL_MODE_16, true, mipi_spi::PIXEL_MODE_16, mipi_spi::BUS_TYPE_SINGLE, 128, 160, 0, 0, 0, true>();"
in main_cpp