[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.""" """Tests for mpip_spi configuration validation."""
from collections.abc import Callable, Generator from collections.abc import Callable, Generator
from pathlib import Path
from unittest import mock from unittest import mock
import pytest import pytest
from esphome import config_validation as cv 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 import KEY_ESP32, KEY_VARIANT, VARIANTS
from esphome.components.esp32.gpio import validate_gpio_pin from esphome.components.esp32.gpio import validate_gpio_pin
from esphome.const import CONF_INPUT, CONF_OUTPUT from esphome.const import CONF_INPUT, CONF_OUTPUT
@@ -23,6 +25,40 @@ def mock_spi_final_validate():
yield 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 @pytest.fixture
def choose_variant_with_pins() -> Generator[Callable[[list], None]]: 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( 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], component_fixture_path: Callable[[str], Path],
) -> None: ) -> None:
"""Full code generation for native.yaml should produce correct metadata.""" """Full code generation for native.yaml should produce correct metadata."""
generate_main(component_fixture_path("native.yaml")) _, all_meta = cached_generate_main(component_fixture_path("native.yaml"))
all_meta = get_all_display_metadata()
# native.yaml: model JC3636W518 -> 360x360, no writer, full hardware rotation # native.yaml: model JC3636W518 -> 360x360, no writer, full hardware rotation
assert len(all_meta) == 1 assert len(all_meta) == 1
meta = next(iter(all_meta.values())) meta = next(iter(all_meta.values()))
@@ -188,12 +187,11 @@ def test_metadata_via_code_generation_native(
def test_metadata_via_code_generation_lvgl( 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], component_fixture_path: Callable[[str], Path],
) -> None: ) -> None:
"""Full code generation for lvgl.yaml should produce correct metadata.""" """Full code generation for lvgl.yaml should produce correct metadata."""
generate_main(component_fixture_path("lvgl.yaml")) _, all_meta = cached_generate_main(component_fixture_path("lvgl.yaml"))
all_meta = get_all_display_metadata()
# lvgl.yaml: model ST7735 -> 128x160, no writer (lvgl draws directly), full hw rotation # lvgl.yaml: model ST7735 -> 128x160, no writer (lvgl draws directly), full hw rotation
assert len(all_meta) == 1 assert len(all_meta) == 1
meta = next(iter(all_meta.values())) meta = next(iter(all_meta.values()))

View File

@@ -307,12 +307,12 @@ def test_all_predefined_models(
def test_native_generation( 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], component_fixture_path: Callable[[str], Path],
) -> None: ) -> None:
"""Test code generation for display.""" """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 ( 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>()" "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 in main_cpp
@@ -323,12 +323,12 @@ def test_native_generation(
def test_lvgl_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], component_fixture_path: Callable[[str], Path],
) -> None: ) -> None:
"""Test LVGL generation configuration.""" """Test LVGL generation configuration."""
main_cpp = generate_main(component_fixture_path("lvgl.yaml")) main_cpp, _ = cached_generate_main(component_fixture_path("lvgl.yaml"))
assert ( 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>();" "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 in main_cpp