Что такое класс эквивалентности (Equivalence Class) в тест-дизайне?

Ответ

Класс эквивалентности (Equivalence Class) — это техника тест-дизайна, при которой все возможные входные данные для тестируемого модуля разбиваются на группы (классы), внутри которых поведение системы ожидается идентичным. Тестирование одного значения из класса считается достаточным для проверки всего класса.

Цель:

Значительно сократить количество тестовых случаев при сохранении высокого покрытия.

Алгоритм применения:

  1. Определите входные условия (поля, параметры).
  2. Выделите валидные и невалидные классы эквивалентности.
  3. Для каждого класса создайте минимум один тестовый случай.

Практический пример:

Функция: Валидация скидочного купона. Скидка применяется, если сумма заказа от 1000 до 10000 рублей включительно.

Класс эквивалентности Диапазон / Описание Ожидаемый результат Пример тестового значения
Валидный класс 1 Граничное нижнее значение Принят 1000
Валидный класс 2 Значение внутри диапазона Принят 5000
Валидный класс 3 Граничное верхнее значение Принят 10000
Невалидный класс 1 Меньше нижней границы Отклонён 999
Невалидный класс 2 Больше верхней границы Отклонён 10001
Невалидный класс 3 Нечисловое значение Отклонён "abc"

Код теста (псевдокод):

def test_discount_coupon(order_amount):
    if 1000 <= order_amount <= 10000:
        return "Принят"
    else:
        return "Отклонён"

# Достаточно протестировать по одному значению из каждого класса
assert test_discount_coupon(1000) == "Принят"
assert test_discount_coupon(5000) == "Принят"
assert test_discount_coupon(999) == "Отклонён"
assert test_discount_coupon(10001) == "Отклонён"

Связь с другими техниками: Часто используется вместе с анализом граничных значений, который фокусируется на тестировании значений на границах классов (как в примере выше).

Ответ 18+ 🔞

Да ты посмотри, что за красота, блядь! Класс эквивалентности, ёпта! Это ж как в армии: всех мужиков нахуй под одну гребёнку — один проверил, значит, и все остальные такие же, пизда!

Суть-то проще пареной репы, в рот меня чих-пых. У тебя есть куча разных входных данных, как эти ваши скидочные купоны. И вместо того чтобы тупо перебирать все числа от минус бесконечности до пизды, ты их в кучки разбиваешь. В одной кучке — годные, в другой — хуёвые. И проверяешь ты не каждого по отдельности, а взял из кучки одного бедолагу, протестил, и если он сработал как надо, то и вся его братва, блядь, такая же!

Зачем это надо, спросишь? А затем, чувак, чтобы не ебашить тесты до второго пришествия! Экономия времени и сил — овердохуища! Покрытие остаётся высоким, а работать надо в разы меньше. Волшебство, блядь, да и только.

Как этим пользоваться, этот твой алгоритм:

  1. Смотришь, что у тебя там на входе ползёт. Поле, параметр, хуй с горы.
  2. Делишь всё это добро на правильные и неправильные кучки. Правильные — те, что система должна проглотить. Неправильные — те, на которых она должна блевать.
  3. И из каждой кучки, даже из самой мелкой и позорной, ты вытаскиваешь по одному челу и пишешь на него тест. Всё, пиздец, готово!

Пример из жизни, чтобы вообще всё стало ясно, как божий день:

Есть у нас функция, которая проверяет скидочный купон. Скидка работает, если сумма заказа от 1000 до 10000 рублей, включительно, блядь.

Вот как мы это разложим по полочкам:

Класс эквивалентности Что внутри Что должно быть Пример для теста
Годная кучка 1 Самое нижнее пограничье Принят 1000
Годная кучка 2 Любое значение внутри Принят 5000
Годная кучка 3 Самое верхнее пограничье Принят 10000
Хуёвая кучка 1 Меньше нижней границы Отклонён 999
Хуёвая кучка 2 Больше верхней границы Отклонён 10001
Хуёвая кучка 3 Вообще не число, а какая-то дичь Отклонён "abc"

И смотри, какая магия: вместо того чтобы гонять числа 999, 1000, 1001, 5000, 9999, 10000, 10001 — а это уже семь тестов, блядь! — мы берём по одному представителю из шести кучек. И всё! Покрыли всю хуйню!

Код, который мы не трогаем, потому что так надо:

def test_discount_coupon(order_amount):
    if 1000 <= order_amount <= 10000:
        return "Принят"
    else:
        return "Отклонён"

# И тестируем наших подопытных из каждой кучки
assert test_discount_coupon(1000) == "Принят"
assert test_discount_coupon(5000) == "Принят"
assert test_discount_coupon(999) == "Отклонён"
assert test_discount_coupon(10001) == "Отклонён"

А ещё эту штуку часто в паре с анализом граничных значений используют. Это когда ты особенно пристально, блядь, смотришь на те самые пограничные значения (вот эти 999, 1000, 10000, 10001), потому что рядом с границей система чаще всего и плющит нахуй. Как в нашем примере, собственно. Красота!