Решили: завели scripts/fast-tests.ps1 — прогон EditMode-тестов мимо редактора: сборки берутся у
compile-check.ps1, раннер (tools/FastTests) грузит их и зовёт методы с [Test] напрямую.
499 тестов проходят за 7 секунд, полный прогон через Unity остаётся за run-tests.ps1 и CI.
Почему: в batchmode платится не за тесты, а за запуск редактора — лицензия, импорт, domain reload,
компиляция (замер: компиляция 7.5 с, domain reload 1.1 с, инициализация ~10 с), тогда как сами тесты
считаются секунды. Отвергнутая альтернатива — ускорять сам batchmode (-nographics,
-disable-assembly-updater): это экономит секунды из десятков, то есть лечит симптом. Вторая
отвергнутая — переписать тесты, чтобы они не звали движок: тесты следуют за игрой, а не наоборот.
Сказано: «согласен, если никак хуже не сделает» (2026-08-03, сессия 87bf8fd2) — отсюда весь дизайн вокруг одного требования: не выдать ложный зелёный.
Как это требование выполнено:
- Три исхода вместо двух. Тест, упавший на отсутствии движка, не «провал» и не «успех», а
«нужен редактор» — их 611, и они НЕ зачтены. Признак движка:
SecurityExceptionсо словомECall(сборки Unity полны internal call’ов, которые линкует только её рантайм),DllNotFoundException,TypeLoadException,No log scope is available(это LogAssert из Unity Test Framework). - Пустой прогон — провал, как и в
run-tests.ps1: опечатка в фильтре не должна выглядеть успехом. Отдельный код 3 на «пусто в одной сборке» — при фильтре это нормально, и решает вызывающий, который видит все наборы. - Список «недостоверных вне редактора» печатается поимённо. Сейчас там один тест — он считает аллокации через GC, а вне Unity сборщик другой. Молча выкинутый тест неотличим от забытого.
- Проверено саботажем: сломанный
AttackTiming.AttacksPerSecond(×1.5) прогон поймал и вернул 1. Без такой проверки «зелёный за 7 секунд» — это вера, а не факт.
Грабли:
- Финализатор движкового объекта убивает процесс целиком.
VisualElement.FinalizeзовётDebug.LogError→ internal call →SecurityExceptionв потоке сборщика мусора. Поймать нельзя, процесс падает в случайный момент, унося отчёт по всем тестам. Лечится глушением логгера (Debug.unityLogger.logEnabled = false) плюс разведением сборок по отдельным процессам. - Покрытие оказалось вдвое ниже оценки по файлам. Считала по «файлы, где нет
GameObject» — вышло 148 из 178; на деле запускается 499 из 1121 теста (45%). Причина:ScriptableObject.CreateInstanceдля контентных SO рассыпан по тестам, которые в остальном чистая логика. - Прогон видит и чужую поломку. На проверке всплыл
CursorSkinData (домен cursor)— незакоммиченный тип соседней сессии без папки вContentPaths. Полезно, но красный не всегда твой.
Владелец правды: tools/FastTests/Program.cs, scripts/fast-tests.ps1.