Признаки хорошего теста
Тесты, которым доверяют: быстрые, независимые, стабильные и понятные.
Хороший тест — быстрый, изолированный, детерминированный и читаемый. Эти свойства часто запоминают аббревиатурой FIRST: Fast, Isolated, Repeatable, Self-validating, Timely.
Четыре главных свойства
- Быстрый (Fast). Тысячи тестов должны проходить за секунды. Медленный набор перестают запускать — и он умирает.
- Изолированный (Isolated). Тест не зависит от других тестов и порядка запуска. Каждый сам готовит своё состояние.
- Детерминированный (Repeatable). Один и тот же тест на одном коде всегда даёт один результат — без зависимости от времени, случайности, сети.
- Читаемый и самопроверяющийся (Self-validating). Тест сам говорит «прошёл/не прошёл» через assert, и из него понятно, что проверяется.
Изолированность на примере
Плохо, когда тесты делят общее изменяемое состояние — порядок запуска начинает влиять на результат. Хорошо — когда каждый тест создаёт своё.
def add_item(cart, item):
cart.append(item)
return cart
# ИЗОЛИРОВАННЫЕ тесты: каждый создаёт свою корзину
def test_first_item():
cart = [] # своё состояние
add_item(cart, "книга")
assert cart == ["книга"]
def test_second_item():
cart = [] # независимо от первого теста
add_item(cart, "ручка")
assert cart == ["ручка"]
test_first_item()
test_second_item()
print("Оба теста изолированы: порядок запуска не влияет на результат")
Вывод:
Оба теста изолированы: порядок запуска не влияет на результат
Детерминированность
Тест, опирающийся на random или текущее время без фиксации, иногда зелёный, иногда красный — это флаки-тест (о нём в следующем уроке). Детерминированный тест фиксирует все источники недетерминизма: передаёт время и случайность снаружи или задаёт seed.
import random
def shuffle_deck(seed):
"""Перемешивает колоду детерминированно по seed."""
deck = list(range(1, 6))
rnd = random.Random(seed) # фиксируем источник случайности
rnd.shuffle(deck)
return deck
# Детерминированно: один seed -> всегда один результат
assert shuffle_deck(42) == shuffle_deck(42)
print("Детерминированный тест: одинаковый seed даёт одинаковый результат")
Вывод:
Детерминированный тест: одинаковый seed даёт одинаковый результат
Итог
- Хороший тест: быстрый, изолированный, детерминированный, читаемый (FIRST).
- Изоляция — своё состояние в каждом тесте, независимость от порядка.
- Детерминизм — фиксируем время и случайность, иначе получим флаки-тесты.
Проверьте себя
1. Что значит «изолированный» тест?
AОн запускается на отдельном сервере
BОн не зависит от других тестов и от порядка запуска, сам готовит своё состояние
CОн проверяет изоляцию проводов
DОн написан в отдельном файле
2. Почему важна детерминированность теста?
AЧтобы тест был длиннее
BЧтобы на одном коде он всегда давал один результат, а не «иногда красный»
CЧтобы использовать больше random
DЧтобы зависеть от текущего времени
3. Что расшифровывает аббревиатура FIRST применительно к тестам?
AСтиль форматирования кода
BFast, Isolated, Repeatable, Self-validating, Timely
CНазвание фреймворка
DЭтапы релиза