test(backend): HA-зависимый тест объявляет это сам, а не именем файла

`python3 -m pytest tests_backend/` без Home Assistant обрывался НА СБОРКЕ:
`test_coordinate_canonicalization.py` тянет HA через `store`, а
`collect_ignore_glob` в conftest отсекает только `test_ha_*.py`. Ни один
из трёх сотен чистых тестов при этом не выполнялся, хотя CLAUDE.md и
PROCESS.md §8 обещают ровно обратное. В CI дефект невидим: там HA есть и
список игнора пуст.

Признак «нужен ли файлу HA» был подменён признаком «как файл назван» —
та же конструкция, которая в #389 уронила 85 тестов с голым assert False.

Вариант владельца — третий: `pytest.importorskip("homeassistant")` в
самом файле, до импортов, которые тянут HA. Теперь это честный скип
(«1 skipped» вместо «Interrupted»), остальные файлы прогоняются, а в CI
не скипается ничего.

Обещанная проверка остальных файлов сделана пофайловым collect: из
двадцати HA требует ровно один непоименованный — этот. Чтобы второй не
появился молча, добавлен статический гейт: он читает импорты (не
исполняет), строит множество модулей интеграции, тянущих HA, — с
замыканием по относительным импортам, потому что `import_export`
зависит от HA только через `store`, — и требует у такого теста либо имя
`test_ha_*`, либо importorskip.

Свидетели, каждый проверен отрицательным прогоном:
- снять importorskip → красный «файлам нужен HA, но они этого не
  объявляют»;
- новый чистый файл с импортом store → тот же красный;
- убрать замыкание → красный синтетический тест сканера;
- перестать исключать TYPE_CHECKING → красный он же;
- считать импорты внутри функций → красный он же.
Плюс два свидетеля самого сканера в теле гейта: `store` обязан быть
найден, `coordinate_canonicalization` обязан остаться чистым — иначе
«ничего не нашёл» выглядело бы как «всё в порядке».

Мутант `pure-backend-test-pulls-home-assistant` в реестре: добавляет
импорт store в чистый test_projection.py, guard — этот гейт.

Гейты: npm test 1791 tests, 1790 pass, 0 fail; pytest без HA
312 passed, 3 skipped (было: Interrupted, 0 выполнено);
mutation-gate --check зелёный.

Issue: #436
User-Visible: no
This commit is contained in:
Claude
2026-09-03 11:06:25 +03:00
parent bdf53dc482
commit 8b9548775f
3 changed files with 174 additions and 0 deletions
+13
View File
@@ -4771,6 +4771,19 @@ const MUTANT_DEFINITIONS = [
replace: ' if (row.url !== expectedUrl',
}],
},
{
id: 'pure-backend-test-pulls-home-assistant',
guard: 'python3 -m pytest tests_backend/test_backend_quality.py -q -p no:cacheprovider',
because: 'a pure test module that imports an HA-dependent backend module must be caught '
+ 'statically: pytest aborts on collection, so ALL pure tests stop running and the '
+ 'output looks nothing like a normal failure (#436, the #389 pattern)',
patches: [{
file: 'tests_backend/test_projection.py',
find: 'import copy\nimport importlib.util\nimport os',
replace: 'import copy\nimport importlib.util\nimport os\n'
+ 'from custom_components.houseplan.store import async_save_config_state',
}],
},
{
id: 'benchmark-page-verdict-unwatched',
guard: 'node demo/guard/verify-guard.mjs',