Классы эквивалентности и граничные значения
Если на собеседовании будет только одна практическая задача — почти наверняка это будет она.
Класс эквивалентности — набор входных данных, которые система обрабатывает одинаково. Достаточно проверить один представитель класса: если сломается — сломается на всём классе.
Вопрос 1: «Поле принимает возраст от 18 до 60. Какие тесты напишете?»
Что на самом деле проверяет интервьюер
Умеете ли вы сокращать бесконечное множество входов до конечного набора проверок и осознанно объяснять, почему именно этих проверок достаточно. Плохой ответ — «проверю 18, 25, 40, 55, 60». Это пять тестов из одного класса.
Развёрнутый ответ
Сначала делим область значений на классы:
- невалидный класс «меньше 18»: представитель — 17;
- валидный класс «от 18 до 60»: представитель — любой, например 30;
- невалидный класс «больше 60»: представитель — 61.
Затем накладываем анализ граничных значений: ошибки программистов концентрируются на границах, потому что там живут перепутанные < и <=, i < n вместо i <= n и off-by-one. Берём по два значения на каждой границе (граница и соседнее с ней) — получаем 17, 18 и 60, 61.
def valid_age(age):
return 18 <= age <= 60
for age in [17, 18, 19, 59, 60, 61]:
print(age, "->", "принято" if valid_age(age) else "отклонено")
Вывод:
17 -> отклонено 18 -> принято 19 -> принято 59 -> принято 60 -> принято 61 -> отклонено
Классическая техника называется «двухточечной» (граница и соседнее значение) — 17/18 и 60/61. Трёхточечная добавляет ещё по значению внутри: 17/18/19 и 59/60/61. На собеседовании назовите обе и скажите, что выбор зависит от риска и цены проверки.
Где кандидаты недобирают баллов
Сильный ответ не заканчивается числами. Поле ввода — это не только диапазон, и стоит проговорить вторую группу классов:
- тип данных: буквы, спецсимволы, пробел, пустая строка;
- формат: дробное «25.5», отрицательное «−5», ведущие нули «018»;
- переполнение: 999999999999, очень длинная строка;
- интерфейс: вставка из буфера, ввод с клавиатуры, автозаполнение браузера;
- источник данных: то же поле через API — там нет маски ввода, и «18» может прилететь строкой или
null.
Отдельно упомяните вопрос к аналитику: «что значит возраст 18 — на момент регистрации или на дату события?» Умение задать уточняющий вопрос ценится выше, чем длинный список тестов по угадыванию.
Вопрос 2: «Чем эквивалентное разбиение отличается от анализа границ и зачем нужны обе техники?»
Что на самом деле проверяет интервьюер
Понимаете ли вы, что техники дополняют, а не заменяют друг друга.
Развёрнутый ответ
| Техника | Что даёт | Пример для 18–60 |
| Эквивалентное разбиение | сокращает число тестов: один представитель на класс | 17, 30, 61 |
| Анализ граничных значений | повышает шанс найти дефект в самом опасном месте класса | 17, 18, 60, 61 |
Разбиение отвечает на вопрос «сколько тестов?», анализ границ — «какие именно значения брать?». Вместе они дают минимальный набор с максимальной вероятностью находки. Важная оговорка: техника границ применима только там, где значения упорядочены (числа, даты, длины строк). Для набора «Москва / Санкт-Петербург / Казань» границ нет — работает только разбиение.
Типичные ошибки кандидатов
- Проверяют несколько значений из одного класса (18, 25, 40, 55) и считают это покрытием — это одна и та же проверка, повторённая четыре раза.
- Забывают невалидные классы: тестируют только то, что должно работать.
- Берут границу, но не берут соседнее значение — тогда перепутанные
<и<=не ловятся. - Ограничиваются числами, не проверяя тип, формат, длину и путь через API.
- Не уточняют требования, а «додумывают» их — на собеседовании это считается за красный флаг.
Как ответить кратко
Разбиваю входные данные на классы эквивалентности: «меньше 18», «18–60», «больше 60» — внутри класса система ведёт себя одинаково, поэтому хватит одного представителя. Дальше накладываю анализ граничных значений: беру 17 и 18, 60 и 61, потому что типовые дефекты — это перепутанные «меньше» и «меньше или равно». Итог — примерно пять проверок вместо перебора. Отдельно проверяю нечисловые классы: буквы, спецсимволы, пустое поле, дробное и отрицательное значение, очень длинную строку, а также ввод через API, где нет маски. И обязательно уточняю у аналитика, включительны ли границы.