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
+30
View File
@@ -10,6 +10,36 @@ except ImportError:
collect_ignore_glob = [] if HAS_HA else ["test_ha_*.py"]
# Пакет интеграции без Home Assistant не импортируется: его __init__.py тянет
# весь HA. Чистым тестам нужны только подмодули, поэтому в окружении БЕЗ HA
# родительские пакеты подменяются пустышками с настоящим __path__ — подмодули
# после этого читаются, а тяжёлый __init__.py не исполняется.
#
# Подмена живёт здесь, а не в тестах, и это главное решение issue #394. Раньше
# её ставили сами тесты, под условием «если ещё не импортирован», и в CI она не
# срабатывала лишь потому, что настоящий пакет успевал импортироваться из файла,
# который идёт раньше по алфавиту. Корректность HA-харнесса держалась на именах
# файлов в каталоге; чем это кончается, показал #389 — 85 тестов упали с голым
# `assert False`, потому что HA получил пустышку вместо интеграции.
#
# Теперь развилка явная и по единственному честному признаку: есть Home
# Assistant — работаем с настоящим пакетом и ничего не подменяем; нет — значит
# HA-тесты и так пропущены, и подменять безопасно, ломать нечего.
if not HAS_HA:
import sys
import types
from pathlib import Path
_ROOT = Path(__file__).resolve().parent.parent
for _name, _path in (
("custom_components", _ROOT / "custom_components"),
("custom_components.houseplan", _ROOT / "custom_components" / "houseplan"),
):
if _name not in sys.modules:
_module = types.ModuleType(_name)
_module.__path__ = [str(_path)]
sys.modules[_name] = _module
if HAS_HA:
import shutil
from pathlib import Path