Все разборы

Тест-дизайн

Как ответить на вопрос «Классы эквивалентности и граничные значения» на собеседовании QA

Как объяснить классы эквивалентности и граничные значения на собеседовании QA: невалидные классы, двух- и трёхзначная схема, границы строк, дат и денег.

Зачем это спрашивают

Классы эквивалентности и граничные значения — две самые используемые техники тест-дизайна. Почти любое поле ввода, параметр запроса или настройка проверяется с их помощью, поэтому интервьюер почти наверняка спросит о них на позицию junior и проверит глубину на позицию middle.

Обычно вопрос идёт в два захода: сначала определение, потом живая задача вроде «поле принимает от 1 до 100, какие значения вы проверите?». По ответу на задачу видно главное: думаете ли вы о невалидных данных и понимаете ли, что границы есть не только у чисел.

Как построить сильный ответ

Классы эквивалентности

Класс эквивалентности — группа входных значений, на которых система ведёт себя одинаково. Раз поведение одинаковое, достаточно проверить одного представителя класса, а не все значения подряд. Так техника сокращает число проверок.

Ключевое — выделять не только валидный класс. Для поля «возраст от 18 до 65» классов больше, чем кажется:

  • валидный: целые числа от 18 до 65;
  • невалидные: меньше 18, больше 65;
  • невалидные по типу: буквы, спецсимволы, дробное число, пустое поле, пробелы.

Каждый невалидный класс проверяют отдельно. Если в одном тесте смешать две ошибки, например пустое имя и неверный возраст, сообщение об одной может скрыть отсутствие проверки другой.

Граничные значения

Граница — край класса эквивалентности. На краях ошибаются чаще всего: перепутан строгий и нестрогий знак сравнения или допущена ошибка на единицу. Поэтому значения берут на самой границе и вплотную к ней.

Для диапазона от 1 до 100 есть две распространённые схемы:

Схема Нижняя граница Верхняя граница
Двухзначная 0, 1 100, 101
Трёхзначная 0, 1, 2 99, 100, 101

Двухзначная схема берёт саму границу и ближайшее значение по другую сторону. Трёхзначная добавляет соседа внутри класса. Назовите обе и скажите, какую выбираете и почему: трёхзначная надёжнее ловит ошибки в условии сравнения, двухзначная экономнее.

К границам добавьте представителей невалидных классов: пусто, отрицательное число, дробное, буквы, пробелы вокруг числа, очень большое число, которое может не поместиться в тип данных.

Границы есть не только у чисел

Это то, чем ответ middle отличается от ответа junior:

  • Строка: длина 0, 1, максимум, максимум плюс один; формат; пробелы в начале и конце; символы юникода и эмодзи, которые могут занимать больше одного байта или кодовой единицы.
  • Список или коллекция: пустой, один элемент, максимум, больше максимума.
  • Дата: последний день месяца, 29 февраля в високосный и невисокосный год, переход через Новый год, переход на летнее время, если система работает в часовом поясе, где он действует.
  • Деньги: 0, минимальная единица (0.01), отрицательная сумма, максимум, округление копеек при расчёте скидки.

Пример ответа

Класс эквивалентности — это группа значений, на которых система ведёт себя одинаково, поэтому из каждого класса достаточно одного представителя. Я обязательно выделяю невалидные классы: значения за диапазоном, пустое поле, буквы, дробные числа. Граничные значения — края этих классов, там ошибки встречаются чаще всего из-за неверного знака сравнения. Если поле принимает от 1 до 100, по трёхзначной схеме я проверю 0, 1, 2 и 99, 100, 101, а ещё пустое значение, отрицательное, дробное, буквы и очень большое число. Границы есть не только у чисел: у строки это длина 0, 1, максимум и максимум плюс один, у даты — конец месяца и 29 февраля, у денег — 0, 0.01 и округление.

Частые ошибки

  • Ответ «1, 50, 100». Значение 50 ничего не говорит о границах, а 0 и 101 пропущены — как раз те, где обычно прячется ошибка.
  • Только валидный класс. Без невалидных классов половина проверок теряется.
  • Границы только у чисел. Строки, даты, списки и суммы — такие же кандидаты.
  • Не уточнять требования. Включительно ли «до 100»? Принимаются ли дробные? Хороший кандидат задаёт эти вопросы, прежде чем выписывать значения.
  • Смешивать несколько невалидных значений в одном тесте. Одно сообщение об ошибке может скрыть другое.

Пример на MarketCove

Допустим, по требованиям поле «Имя» в форме оформления заказа учебного магазина https://shop.tomiddle.com принимает от 2 до 50 символов (гипотетическое правило — в реальной задаче его уточняют у аналитика). Проверки по трёхзначной схеме плюс пустое значение удобно записать как параметризованный тест для API оформления заказа:

import pytest

@pytest.mark.parametrize(
    ("length", "accepted"),
    [
        (0, False), (1, False), (2, True), (3, True),
        (49, True), (50, True), (51, False),
    ],
)
def test_order_name_length(api_client, order_payload, length, accepted):
    payload = {**order_payload, "name": "а" * length}
    response = api_client.post("/api/shop/orders", json=payload)
    if accepted:
        assert response.status_code in (200, 201)
    else:
        assert 400 <= response.status_code < 500

Здесь api_client и order_payload — фикстуры проекта (вторая собирает валидный заказ со всеми остальными полями), а имена полей условные: настоящую схему смотрите в Swagger на /api/docs. Обратите внимание на идею: проверка через API показывает, валидирует ли сервер длину сам, даже если интерфейс не даёт ввести 51 символ.

Длиной классы для имени не исчерпываются: добавьте строку из одних пробелов, имя с дефисом («Анна-Мария») и с буквой «ё» как валидных представителей, а цифры и спецсимволы — в тот класс, куда их отнесёт требование.

Задание для практики

Откройте форму оформления заказа в https://shop.tomiddle.com и выберите поле «Адрес». Выпишите классы эквивалентности: валидный и все невалидные, какие сможете придумать. Затем определите границы по длине и составьте список значений по трёхзначной схеме. Отдельно проверьте поведение через API в песочнице: совпадает ли валидация на сервере с ограничениями интерфейса. Итог проговорите вслух за полторы минуты.

Что спросят следом

  • Почему ошибки чаще всего встречаются именно на границах?
    Границы в коде — это операторы сравнения, и перепутать строгое и нестрогое сравнение очень легко: написать меньше вместо меньше или равно. Ещё одна частая причина — ошибка на единицу при работе с длиной строки или индексами. Внутри класса такие ошибки не видны, а на краю проявляются сразу.
  • Сколько значений брать из каждого класса эквивалентности?
    По определению достаточно одного представителя, потому что внутри класса система ведёт себя одинаково. Если вы не уверены, что класс выделен верно, возьмите ещё одно значение из середины: разное поведение на двух представителях означает, что класс на самом деле нужно разделить.
  • Можно ли проверять границы через API, а не через интерфейс?
    Да, и часто это даже правильнее. Интерфейс может ограничивать ввод, например не давать набрать больше символов, но сервер обязан проверять данные сам. Отправка запроса со значением за границей напрямую показывает, есть ли валидация на бэкенде.
  1. Q-01
    Какие техники тест-дизайна вы знаете и как выбираете?
  2. Q-02
    Протестируйте лифт (ручку, кофемашину)
  3. Q-03
    Что вы проверяете при тестировании API?

Отрепетировать ответ с куратором

В сопровождении — весь банк вопросов, мок-собеседование и разбор каждого настоящего собеседования, пока не придёт оффер. Гарантий трудоустройства не даём — готовим к тому, что спросят.

Весь банк вопросов

Здесь — разбор одного вопроса. Банк целиком, с разбором и повторением, открыт в сопровождении; три вопроса — в витрине тренажёра.