В большом репозитории CI повторно запускает неизменившиеся тесты с теми же входами. Какой механизм безопасно сократит такой прогон?
Следует применить кэширование результатов тестов с содержательным ключом валидности. Результат можно переиспользовать только тогда, когда совпадают версия теста, исходный код проверяемых компонентов, зависимости, тестовые данные, конфигурация и релевантное окружение.
По мере роста репозиториев полный запуск автотестов стал занимать значительное время, хотя большая часть тестов не затрагивалась изменениями. Кэширование результатов возникло как способ не выполнять повторно детерминированную работу, если доказано, что её входы остались прежними.
Подход особенно полезен в CI с частыми коммитами и дорогими интеграционными проверками. Он дополняет параллельный запуск, но не заменяет его: параллелизм сокращает время выполнения, а кэш исключает ненужное выполнение.
Простое правило вроде повторного использования результата по имени теста небезопасно. Тест может зависеть от изменившегося модуля, схемы базы данных, фикстур, версии браузера, переменных окружения, конфигурации или внешнего набора данных.
Слишком агрессивный кэш создаёт ложно зелёный CI: система показывает старый успешный результат, хотя текущий код уже сломан. Слишком консервативный кэш почти не даёт выигрыша, потому что изменения в несвязанных файлах постоянно делают записи недействительными.
Для каждого результата формируют ключ, отражающий все существенные входы теста. Обычно в него входят идентификатор и версия теста, хеш исходного кода и зависимостей, версия тестового раннера, конфигурация, тестовые данные, целевая платформа и параметры окружения, влияющие на поведение.
Если ключ совпал, CI может вернуть сохранённый результат без повторного запуска. При изменении любого существенного входа ключ должен измениться, и тест выполняется заново. На практике это требует явного описания зависимостей тестов или надёжного анализа графа зависимостей.
Безопаснее кэшировать подтверждённые успешные результаты детерминированных тестов. Кэширование падений требует особой осторожности: старый сбой не должен скрыть исправление, а временная ошибка инфраструктуры не должна считаться свойством текущего кода.
Кэш должен быть изолирован по ветке, версии платформы и другим значимым параметрам, если их смешивание меняет смысл результата. Также нужны срок жизни записей, контроль целостности и возможность принудительного полного прогона после изменения правил кэширования или при сомнительном результате.
Главный компромисс — скорость против сложности поддержания корректной инвалидизации. Если невозможно надёжно определить все входы теста, кэширование конкретного набора лучше не применять: предсказуемый полный запуск безопаснее сомнительной оптимизации.
В монорепозитории сервисные тесты занимали около часа. При изменении библиотеки форматирования CI снова запускал проверки, связанные с платежами, хотя их код и зависимости не менялись.
Рассматривались три варианта. Полный параллельный запуск был простым, но сохранял значительные затраты на вычисления. Ручной список тестов для каждого компонента ускорял CI, но быстро устаревал. Кэш результатов с ключом из версии теста, графа исходных зависимостей, конфигурации окружения и тестовых фикстур требовал начальной настройки, зато позволял автоматически различать затронутые и незатронутые проверки.
Выбрали третий вариант, оставив полный прогон по расписанию и после изменений инфраструктуры. В обычных сборках неизменившиеся детерминированные тесты пропускались, а сомнительные или зависящие от внешнего состояния тесты всегда выполнялись заново. Это сократило обратную связь без отказа от периодической полной проверки.
Нет. Хеш файлов может не отражать версию раннера, операционной системы, настроек локали, схемы базы данных, тестовых фикстур или внешних зависимостей. Нужно учитывать все входы, способные изменить результат; иначе кэш становится источником устаревших вердиктов.
Только если эти источники контролируются и входят в ключ. Например, фиксированное время и воспроизводимый seed делают запуск повторяемым. Если тест читает реальные часы, случайные значения или нестабильное внешнее состояние, одинаковый формальный ключ не гарантирует одинакового результата, поэтому такой тест обычно не следует кэшировать.
Кэш артефактов сохраняет продукты подготовки или компиляции, чтобы не создавать их повторно. Кэш результатов сохраняет сам вердикт проверки и утверждает, что тест уже был корректно выполнен для конкретного набора входов. Ошибка в инвалидизации кэша результатов опаснее: она может скрыть дефект, тогда как устаревший артефакт обычно приводит к повторной сборке или явной ошибке совместимости.