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
+23
View File
@@ -26,3 +26,26 @@ test('backend-тесты не правят sys.path (#393)', () => {
+ ' Читать модуль без Home Assistant можно и без этого — см. test_trails.py:'
+ ' текст файла и exec нужного среза.');
});
test('пакет интеграции подменяет только conftest и только без HA (#394)', () => {
// Пустышка вместо `custom_components.houseplan` — единственный способ читать
// подмодули без Home Assistant, и запретить её нельзя. Но место у неё одно:
// conftest, где решение принимается по честному признаку «есть ли HA».
//
// Когда её ставили сами тесты под условием «если ещё не импортирован», в CI
// она не срабатывала лишь потому, что настоящий пакет успевал импортироваться
// из файла, который идёт раньше по алфавиту. Корректность харнесса держалась
// на именах файлов; чем это кончается, показал #389.
const assigns = /sys\.modules\[\s*(['"])custom_components/;
const offenders = files().filter((name) => name !== 'conftest.py' && assigns.test(read(name)));
assert.deepEqual(offenders, [],
'подмена пакета интеграции живёт в tests_backend/conftest.py и только там:'
+ ' там она условная (нет Home Assistant — нечего ломать), а в тесте она'
+ ' переживает свой тест и достаётся всей сессии (#389, #394).');
const conftest = read('conftest.py');
assert.match(conftest, /if not HAS_HA:/,
'подмена в conftest обязана быть под условием отсутствия Home Assistant');
const stub = conftest.slice(conftest.indexOf('if not HAS_HA:'));
assert.match(stub, /sys\.modules\[_name\] = _module/);
});