При параллельном запуске Go-тестов несколько кейсов работают с файлами: какое свойство даёт каждому кейсу отдельный каталог через t.TempDir?
Отдельный каталог через t.TempDir обеспечивает файловую изоляцию тестовых кейсов: один кейс не читает и не перезаписывает файлы другого. Каталог автоматически удаляется после завершения теста и всех его дочерних subtests.
Без специализированного помощника тесту приходилось вручную создавать временный каталог, выбирать уникальное имя и регистрировать очистку через defer или механизм cleanup. Ошибка в любом из этих шагов могла оставить файлы после теста или привести к конфликтам при параллельном запуске.
t.TempDir объединил создание временного каталога и его гарантированную очистку в API тестового фреймворка. Это уменьшает шаблонный код и делает изоляцию частью структуры теста.
Если несколько тестов используют общий путь, они могут перезаписывать один и тот же файл, зависеть от порядка выполнения или видеть остатки данных предыдущего кейса. Такие ошибки особенно трудно воспроизводить: последовательный запуск может проходить, а параллельный — нестабильно падать.
Важно отличать файловую изоляцию от потокобезопасности. Разные каталоги не защищают от гонок в общей памяти, общем внешнем сервисе или глобальной конфигурации процесса.
Вызывайте t.TempDir внутри конкретного теста или subtest, а не один раз в родительском тесте для всех кейсов. Каждый такой вызов возвращает отдельный временный путь, поэтому относительные имена файлов внутри него не пересекаются.
Вызов внутри callback каждого subtest даёт каждому кейсу свой каталог. После завершения subtest каталог и его содержимое удаляются автоматически.
Если вызвать t.TempDir в родительском тесте и передать один путь всем параллельным subtests, изоляции между ними не будет. Также t.TempDir не очищает ресурсы вне этого каталога и не отменяет фоновые goroutine: соединения, серверы и процессы нужно закрывать отдельно через t.Cleanup или явное завершение.
Набор тестов для загрузчика конфигурации сначала использовал фиксированный путь вроде testdata/current.json. При параллельном запуске один кейс иногда читал файл, который только что записал другой.
Рассматривались три варианта. Отключить параллельность проще всего, но это замедляет тесты и маскирует проблему изоляции. Генерировать уникальные имена файлов вручную возможно, однако остаются вопросы очистки и корректного удаления вложенных файлов. Использовать отдельный каталог через t.TempDir лучше, потому что уникальность и жизненный цикл временных данных передаются тестовому фреймворку.
Выбранный вариант разместил вызов t.TempDir внутри каждого subtest. После этого тесты перестали зависеть от порядка выполнения, а временные файлы не накапливались в рабочем каталоге.
Обнаружит ли race detector конфликт двух тестов, записывающих один файл?
Обычно нет. Race detector отслеживает конфликтующие обращения к общей памяти Go, а не логические конфликты операций файловой системы. Два теста могут одновременно менять один файл и не получить отчёт -race, поэтому для файловой изоляции нужны разные каталоги или имена, а для проверки поведения при конкурентной записи — отдельный специализированный тест.
Достаточно ли создать один временный каталог в родительском тесте?
Нет, если параллельные subtests используют его совместно. Сам каталог будет временным, но файлы внутри останутся общим состоянием. Для независимости вызов t.TempDir должен находиться в каждом subtest, которому нужна собственная файловая среда.
Можно ли полагаться на t.TempDir для очистки внешних ресурсов?
Нет. Он отвечает за каталог и его содержимое, но не останавливает HTTP-сервер, не закрывает базу данных и не завершает созданную goroutine. Такие ресурсы следует регистрировать через t.Cleanup; cleanup-функции выполняются после теста в обратном порядке регистрации, что позволяет явно задать порядок освобождения зависимых ресурсов.