Короткий ответ
Тесты начинают зависеть от порядка, когда делят общее изменяемое состояние — глобальные переменные, данные в тестовой БД без отката, кеш, файлы на диске — и один тест неявно опирается на состояние, оставленное предыдущим; решение — явная изоляция через фикстуры с очисткой/откатом перед или после каждого теста.
Как это работает подробнее
Если тест A создаёт запись в БД и не удаляет её, а тест B неявно рассчитывает на пустую таблицу (например, проверяет count() == 0), результат теста B зависит от того, выполнялся ли тест A раньше. Запуск тестов в случайном порядке (pytest-randomly) — хороший способ быстро выявить такие скрытые зависимости.
Пример кода
testing_example_318.py
# Плохо: тесты неявно зависят от порядка
_counter = {"value": 0}
def test_increment():
_counter["value"] += 1
assert _counter["value"] == 1 # упадёт, если запустить после другого теста
# Хорошо: состояние изолировано фикстурой на каждый тест
@pytest.fixture
def counter():
return {"value": 0}
def test_increment_isolated(counter):
counter["value"] += 1
assert counter["value"] == 1Что использовать на практике
- Практика. Надёжная изоляция обычно достигается транзакционным откатом БД между тестами, пересозданием моков в каждой фикстуре function-уровня вместо модульных глобальных моков, и избеганием мутируемых global/module-level переменных в тестируемом коде либо их явным сбросом в фикстуре.
Подводные камни
- Риск. Использовать module-scope или session-scope фикстуры для объектов, которые тест изменяет, без последующей очистки состояния между тестами. Полагаться на то, что тесты в файле всегда будут запускаться в порядке их объявления — pytest формально это обычно делает, но параллельные раннеры (pytest-xdist) и переупорядочивание плагинами этого не гарантируют.