Тестировать age=30 когда поле принимает 18–120 ничего не говорит о том что происходит при 17 или 18, а именно там живут баги на единицу. Разбиение на классы эквивалентности группирует все входные данные по ожидаемому поведению чтобы выбрать один представитель от каждой группы вместо повторения эквивалентных кейсов; анализ граничных значений затем нацеливается на значения на краях каждого раздела, где >= 18 случайно записанное как > 18 остаётся незамеченным. Здесь разобраны обе техники с проработанными примерами, как объединить их в повторяемый 10-минутный процесс проектирования тестов, и как перенести результаты в параметризованные Playwright-тесты.
Что такое разбиение на классы эквивалентности
Разбиение на классы эквивалентности (equivalence partitioning, EP) делит все возможные входные значения на группы (называемые разделами или классами эквивалентности), где каждое значение в группе ведёт себя одинаково. Если система правильно обрабатывает одно значение из раздела, она обработает все остальные так же. Поэтому достаточно проверить одного представителя из каждого раздела.
Пример: поле возраста для стримингового сервиса
Предположим в системе такие правила:
- Для регистрации пользователь должен быть старше 18 лет
- Пользователи до 13 лет полностью заблокированы
- Пользователи 13–17 лет получают ограниченный «подростковый» аккаунт
- Пользователи 18+ получают полный аккаунт
- Возраст должен быть целым числом от 1 до 120
Разделы видны сразу:
| Раздел | Диапазон | Тип | Ожидаемый результат |
|--------|----------|-----|---------------------|
| Валидный взрослый | 18–120 | Валидный | Полный аккаунт |
| Валидный подросток | 13–17 | Валидный | Подростковый аккаунт |
| Младше 13 | 1–12 | Невалидный | Заблокирован |
| Ноль или отрицательный | ≤ 0 | Невалидный | Ошибка |
| Выше максимума | > 120 | Невалидный | Ошибка |
| Не целое число | 17.5, "abc", "" | Невалидный | Ошибка валидации |
Из этих разделов выбираешь одного представителя от каждого. Не нужно тестировать age=19, age=25, age=50 и age=100. Все они в одном разделе. Тестируешь age=30 и покрываешь их всех.
Тест-кейсы:
30→ Полный аккаунт (раздел валидных взрослых)15→ Подростковый аккаунт (раздел валидных подростков)10→ Заблокирован (раздел до 13)-1→ Ошибка (раздел нулевых/отрицательных)200→ Ошибка (раздел выше максимума)"seventeen"→ Ошибка валидации (раздел не целых чисел)
6 тестов вместо потенциально сотен. Покрытие не потеряно.
Что такое анализ граничных значений
Анализ граничных значений (boundary value analysis, BVA) основан на хорошо наблюдаемом факте: баги концентрируются на краях разделов, а не в середине.
Разработчики пишут код вроде if (age >= 18). Баг почти никогда не выглядит как «работает для 30, ломается для 31». Баг почти всегда на границе: «работает для 18, ломается для 17» или «должно быть >= но написано >», поэтому граница смещена на единицу.
BVA говорит: вместо того чтобы просто выбирать произвольного представителя из раздела, всегда тестируй значения прямо на границе: последнее валидное значение, первое валидное значение и опционально значения сразу за ней.
Значения BVA для тестирования
Для любой границы тестируешь:
- Последнее значение перед валидным диапазоном (чуть ниже минимума)
- Первое валидное значение (минимум)
- Последнее валидное значение (максимум)
- Первое значение после валидного диапазона (чуть выше максимума)
Для нашего примера с возрастом при границах 1, 12, 13, 17, 18, 120:
| Граница | Значения для тестирования | Зачем |
|---------|--------------------------|-------|
| Минимальный валидный возраст (1) | 0, 1 | Ошибки смещения на единицу |
| Граница подросток/заблокирован (13) | 12, 13 | Правильное присвоение раздела |
| Граница подросток/взрослый (18) | 17, 18 | Самый частый баг бизнес-правил |
| Максимальный валидный возраст (120) | 120, 121 | Проверка верхнего ограничения |
Тест-кейсы BVA:
0→ Ошибка (ниже минимума)1→ Заблокирован (минимальное валидное значение)12→ Заблокирован (последнее значение в разделе до 13)13→ Подростковый аккаунт (первое значение в подростковом разделе)17→ Подростковый аккаунт (последнее значение в подростковом разделе)18→ Полный аккаунт (первое значение в разделе взрослых)120→ Полный аккаунт (последнее значение в валидном диапазоне)121→ Ошибка (первое значение выше максимума)
Это значительно основательнее случайного тестирования и куда вероятнее поймает реальные ошибки смещения на единицу.
EP и BVA работают вместе
На практике техники используются в связке:
1. Сначала EP: определи все разделы (валидные, невалидные, граничные случаи)
2. Затем BVA: для любого раздела с числовым или упорядоченным диапазоном тестируй на границах вместо (или в дополнение к) случайного значения из середины
Как выглядит комбинированное покрытие для поля возраста:
| Тест | Ввод | Техника | Ожидаемый результат |
|------|------|---------|---------------------|
| 1 | -1 | BVA (ниже минимума) | Ошибка |
| 2 | 0 | BVA (абсолютное дно) | Ошибка |
| 3 | 1 | BVA (минимально валидный) | Заблокирован |
| 4 | 12 | BVA (последний заблокированный) | Заблокирован |
| 5 | 13 | BVA (первый подросток) | Подростковый аккаунт |
| 6 | 15 | EP (середина подросткового раздела) | Подростковый аккаунт |
| 7 | 17 | BVA (последний подросток) | Подростковый аккаунт |
| 8 | 18 | BVA (первый взрослый) | Полный аккаунт |
| 9 | 30 | EP (середина раздела взрослых) | Полный аккаунт |
| 10 | 120 | BVA (последний валидный) | Полный аккаунт |
| 11 | 121 | BVA (первый сверх максимума) | Ошибка |
| 12 | "abc" | EP (раздел не целых чисел) | Ошибка валидации |
| 13 | "" | EP (пустой раздел) | Ошибка валидации |
13 тест-кейсов. Они поймают почти каждый реальный баг валидации возраста, включая нетривиальные.
Применение к реальным фичам
Длина пароля (8–64 символа)
Разделы
- Пустой → ошибка
- Слишком короткий (1–7) → ошибка
- Валидный (8–64) → принят
- Слишком длинный (65+) → ошибка
Тесты BVA на каждой границе
""(пустой) → ошибка7 символов→ ошибка (последнее значение ниже минимума)8 символов→ принят (первое валидное значение)64 символа→ принят (последнее валидное значение)65 символов→ ошибка (первое сверх максимума)
20 символов → принят
6 тестов покрывающих весь валидный/невалидный диапазон.
Поле email
Сценарий только для разбиения (нет чистых числовых границ):
Разделы
- Пустой → ошибка
- Валидный формат (name@domain.com) → принят
- Отсутствует @ → ошибка
- Отсутствует домен → ошибка
- Несколько знаков @ → ошибка
- Международные символы → зависит от спецификации системы
Тестируй по одному значению от каждого раздела. Не нужно тестировать 50 форматов валидного email: все они в разделе «валидный формат».
Dropdown с фиксированными значениями
Если поле принимает только конкретные значения (Small/Medium/Large), границ для анализа BVA нет. Достаточно EP:
Тестируй валидное значение (Medium), невалидное вне списка (XL) и пустое значение.
Частые ошибки
Тестирование слишком многих значений из одного раздела
Если тестируешь возрасты 20, 25, 30, 35 и 45, написал 5 тестов которые живут в одном разделе. Они либо все пройдут либо все упадут вместе. Эти 4 лишних теста ничего не добавили.
Решение: выбирай одного представителя от каждого раздела и тестируй на границах.
Забытые невалидные разделы
Новички часто думают только о валидном вводе. Реальные баги живут в том что происходит с невалидным вводом: отрицательными числами, пустыми строками, значениями чуть выше максимума.
Решение: всегда явно перечисляй невалидные разделы. Там часто прячутся интересные баги.
Пропущенные неочевидные разделы
Для поля «промокод»:
Частые разделы: валидный код, невалидный код, пустой. Легко пропустить: истёкший код, уже использованный, код для другого продукта и код в неправильном регистре (учитывается ли регистр?).
Решение: думай о поведении системы, а не только о формате. Разные поведения = разные разделы.
Применение BVA к неупорядоченным данным
BVA имеет смысл только для данных с естественным порядком: чисел, дат, длин. К списку кодов стран или набору enum-значений BVA не применяется. Для них используй EP.
Практический процесс
Когда встречаешь любое поле ввода или бизнес-правило:
Шаг 1. Какие значения принимает это поле? Каковы правила? Шаг 2. Перечисли все разделы: валидные и невалидные. Запиши ожидаемое поведение для каждого. Шаг 3. Для любого раздела с числовым или упорядоченным диапазоном определи границы. Перечисли значения последний-невалидный/первый-валидный и последний-валидный/первый-невалидный. Шаг 4. Выбери одного представителя от каждого раздела без границ (для середины валидных диапазонов). Добавь граничные значения. Шаг 5. Напиши тест-кейсы, по одному на каждое выявленное значение.На это уходит 5–10 минут на фичу и даёт обоснованный, эффективный набор тестов который можно объяснить кому угодно.
Почему это важно для автоматизации QA
При написании Playwright-тестов эти техники помогают решить что параметризовать. Вместо 20 почти идентичных тестов которые просто меняют входное значение, пишешь один параметризованный тест с 6–8 значениями которые выявили EP и BVA:
const AGE_CASES = [
{ input: '-1', expect: 'error', label: 'below minimum' },
{ input: '1', expect: 'blocked', label: 'minimum valid' },
{ input: '12', expect: 'blocked', label: 'last blocked' },
{ input: '13', expect: 'teen account', label: 'first teen' },
{ input: '17', expect: 'teen account', label: 'last teen' },
{ input: '18', expect: 'full account', label: 'first adult' },
{ input: '120', expect: 'full account', label: 'last valid' },
{ input: '121', expect: 'error', label: 'over maximum' },
];
for (const { input, expect, label } of AGE_CASES) {
test(`age ${label}: ${expect}`, async ({ page }) => {
await page.fill('[data-testid="age-input"]', input);
await page.click('[data-testid="submit"]');
await expect(page.locator('[data-testid="result"]')).toContainText(expect);
});
}Чисто, читаемо, и у каждого теста есть понятная причина существовать.
Ключевые выводы
- Разбиение на классы эквивалентности группирует вводы по ожидаемому поведению: тестируй одно значение от группы
- Анализ граничных значений нацеливается на края между группами, где живут ошибки смещения на единицу
- Используй EP для определения разделов, BVA для выбора точных значений для тестирования
- Всегда включай невалидные разделы: тесты «что происходит с плохим вводом» ловят реальные баги
- Цель: минимум тестов при максимальном покрытии. Не тестировать всё, а тестировать правильное
Эти две техники составляют основу структурированного проектирования тестов. После того как они станут интуитивными, будешь применять их автоматически при взгляде на каждую новую фичу, ещё до открытия редактора тестов.
→ See also: Техники проектирования тест-кейсов: EP, BVA, таблицы решений, переходы состояний | Как писать тест-кейсы: формат, примеры и частые ошибки | Тестирование на основе рисков: как расставить приоритеты, когда нельзя протестировать всё