test: put the package stub in one place, under an honest condition

Чистые тесты подменяли custom_components и custom_components.houseplan
пустышками и не убирали их никогда. В CI это не стреляло только потому, что
настоящий пакет успевал импортироваться из файла, который идёт раньше по
алфавиту: условие «если ещё не импортирован» оказывалось ложным. То есть
корректность HA-харнесса держалась на именах файлов в каталоге, и хватило бы
переименования, чтобы получить #389 заново.

Подмена переехала в conftest и стала условной по единственному честному
признаку: есть Home Assistant — работаем с настоящим пакетом и не подменяем
ничего; нет — HA-тесты и так пропущены, ломать нечего.

Первым заходом я делал подмену обратимой прямо в тестах, контекстным
менеджером. Замер показал, что так теряется работоспособность
test_wall_segment_model в песочнице: он импортирует пакет обычным способом и
жил как раз за счёт чужой пустышки. Развилка в conftest сохраняет оба
окружения и убирает зависимость от порядка файлов.

Проверено в обе стороны: в песочнице 240 passed, а в эмуляции «HA есть»
объект пакета после прогона тот же, что был до.

Issue: #394
User-Visible: no
This commit is contained in:
Matysh
2026-08-30 20:11:31 +03:00
parent a3dcee5241
commit 8dfb0a9e36
5 changed files with 108 additions and 39 deletions
+10 -18
View File
@@ -10,28 +10,20 @@ import types
import pytest
import voluptuous as vol
from pathlib import Path
from pure_imports import load_pure
_ROOT = os.path.dirname(os.path.dirname(__file__))
_PACKAGE_ROOT = os.path.join(_ROOT, "custom_components")
_HOUSEPLAN_ROOT = os.path.join(_PACKAGE_ROOT, "houseplan")
# Keep this pure test independent of Home Assistant even though Python normally
# executes package __init__.py before resolving the validation submodule.
if "custom_components" not in sys.modules:
package = types.ModuleType("custom_components")
package.__path__ = [_PACKAGE_ROOT]
sys.modules["custom_components"] = package
if "custom_components.houseplan" not in sys.modules:
package = types.ModuleType("custom_components.houseplan")
package.__path__ = [_HOUSEPLAN_ROOT]
sys.modules["custom_components.houseplan"] = package
_PATH = os.path.join(
_ROOT,
"custom_components", "houseplan", "validation.py",
)
_spec = importlib.util.spec_from_file_location("hp_validation", _PATH)
v = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(v)
# Тест обходится без Home Assistant, хотя Python выполнил бы __init__.py пакета
# прежде, чем добрался до validation. Подмена родительских пакетов живёт ровно
# на время загрузки: прежняя редакция ставила пустышки насовсем и не падала
# только потому, что настоящий пакет успевал импортироваться из файла, который
# идёт раньше по алфавиту (#394). См. tests_backend/pure_imports.py.
v = load_pure("hp_validation", Path(_HOUSEPLAN_ROOT) / "validation.py")
def test_backend_model_version_matches_frontend_constant():