Классы эквивалентности и граничные значения

Если на собеседовании будет только одна практическая задача — почти наверняка это будет она.

Класс эквивалентности — набор входных данных, которые система обрабатывает одинаково. Достаточно проверить один представитель класса: если сломается — сломается на всём классе.

Вопрос 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, где нет маски. И обязательно уточняю у аналитика, включительны ли границы.

Проверьте себя
1. Поле принимает целое число от 1 до 100. Какой набор лучше всего сочетает эквивалентное разбиение и анализ границ?
A1, 25, 50, 75, 100
B0, 1, 100, 101 и одно значение внутри диапазона
C50 и 500
DВсе значения от 1 до 100
2. Почему проверки 18, 25, 40 и 55 для диапазона 18–60 считаются избыточными?
AПотому что все они принадлежат одному классу эквивалентности и проверяют одно и то же поведение
BПотому что чётные числа тестировать не нужно
CПотому что 18 — это граница, а границы не тестируют
DПотому что для диапазонов применяют только попарное тестирование
3. К каким данным анализ граничных значений неприменим?
AК длине строки в поле «Комментарий»
BК дате рождения
CК неупорядоченному набору значений выпадающего списка городов
DК сумме перевода