Что такое анализ граничных значений?

Анализ граничных значений (Boundary Value Analysis, BVA) — это техника тест-дизайна чёрного ящика, которая фокусируется на тестировании значений на краях классов эквивалентности. Если эквивалентное разбиение говорит, какие группы тестировать, то BVA говорит, где внутри этих групп дефекты прячутся с наибольшей вероятностью.

Почему границы важны

Исследования последовательно показывают, что непропорционально большое количество дефектов ПО возникает на граничных значениях. Причина проста: разработчики пишут условия вроде if (age >= 18) или if (quantity <= 100), и ошибки на единицу (> вместо >=, < вместо <=) — одни из самых распространённых ошибок в коде.

# Намерение: принимать возраст от 18 и старше
if age > 18:      # Баг! Отклоняет 18-летних
    allow_access()

# Правильно:
if age >= 18:
    allow_access()

Разница в один символ (> vs >=) вызывает дефект, который проявляется только на граничном значении 18. Тестирование с age=25 никогда бы его не обнаружило.

BVA с двумя значениями (стандартный)

Наиболее распространённый подход проверяет два значения на границу: саму границу и значение сразу за ней.

Для валидного диапазона от 1 до 100:

graph LR A["0 ❌"] --- B["1 ✅"] --- C["... валидный ..."] --- D["100 ✅"] --- E["101 ❌"] style A fill:#ffcccc style B fill:#ccffcc style D fill:#ccffcc style E fill:#ffcccc
ГраницаТестовые значенияОжидаемый результат
Нижняя0 (сразу ниже)Невалидно
Нижняя1 (граница)Валидно
Верхняя100 (граница)Валидно
Верхняя101 (сразу выше)Невалидно

4 тест-кейса покрывают обе границы.

BVA с тремя значениями (строгий)

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

Для того же диапазона от 1 до 100:

ГраницаТестовые значенияОжидаемый результат
Нижняя0Невалидно
Нижняя1Валидно
Нижняя2Валидно
Верхняя99Валидно
Верхняя100Валидно
Верхняя101Невалидно

6 тест-кейсов для более тщательного покрытия.

BVA для различных типов данных

Целые числа: Просто — граница ± 1.

  • Диапазон 1-10: проверяем 0, 1, 10, 11

Числа с плавающей точкой: Используйте наименьший значимый инкремент.

  • Диапазон 0.0-1.0: проверяем -0.01, 0.0, 1.0, 1.01

Строки (длина): Проверяем на границах длины.

  • Username 3-20 символов: проверяем 2 символа, 3 символа, 20 символов, 21 символ

Даты: Проверяем на границах дат.

  • Валидные даты 1 янв - 31 дек: проверяем 31 дек прошлого года, 1 янв, 31 дек, 1 янв следующего года

Коллекции (размер): Проверяем на границах количества.

  • Товары в корзине 1-50: проверяем 0, 1, 50, 51

Комбинирование EP и BVA

Эти две техники — естественные партнёры. EP определяет разделы; BVA фокусируется на их границах.

Пример: Стоимость доставки по весу

Вес (кг)Доставка
0.1 – 1.0$5
1.01 – 5.0$10
5.01 – 20.0$20
> 20.0$35

Представители EP (середина каждого класса): 0.5, 3.0, 12.0, 25.0

Значения BVA (на границах): 0.09, 0.1, 1.0, 1.01, 5.0, 5.01, 20.0, 20.01

В комбинации получаем полное покрытие всего из 12 тест-кейсов.

graph LR subgraph "Зона $5" A[0.09❌] --- B[0.1✅] --- C[0.5] --- D[1.0✅] end subgraph "Зона $10" D --- E[1.01✅] --- F[3.0] --- G[5.0✅] end subgraph "Зона $20" G --- H[5.01✅] --- I[12.0] --- J[20.0✅] end subgraph "Зона $35" J --- K[20.01✅] --- L[25.0] end

Продвинутые техники BVA

Многомерные границы

Когда система имеет несколько взаимодействующих параметров, границы существуют в нескольких измерениях. Рассмотрим систему ценообразования:

  • Количество: 1-1000
  • Цена за единицу: $0.01-$9999.99

Интересные границы — не только отдельные параметры, но и комбинации:

ТестКоличествоЦена за ед.ИтогоПочему
11$0.01$0.01Минимально возможный итог
21000$9999.99$9,999,990Максимально возможный итог
31$9999.99$9999.99Макс цена, мин количество
41000$0.01$10.00Мин цена, макс количество

Внутренние границы

Не все границы находятся на краях валидных/невалидных диапазонов. Внутренние границы разделяют разные пути обработки внутри валидного диапазона:

def calculate_tax(income):
    if income <= 10000:
        return income * 0.10
    elif income <= 50000:
        return 1000 + (income - 10000) * 0.20
    else:
        return 9000 + (income - 50000) * 0.30

Внутренние границы на $10 000 и $50 000 так же важны, как и границы общего валидного диапазона. Проверяем: $9 999, $10 000, $10 001, $49 999, $50 000, $50 001.

Неявные границы

Некоторые границы не указаны в спецификации, но существуют в реализации:

  • Переполнение целого числа: 2 147 483 647 (макс 32-битного int со знаком)
  • Границы массивов: Коллекции с индексацией от 0 vs от 1
  • Пустое/null: Граница между «что-то» и «ничего»
  • Границы точности: Проблемы сравнения чисел с плавающей точкой при очень малых разницах

BVA для систем с временными параметрами

Временные границы особенно коварны:

СценарийГраничные значения
Таймаут сессии (30 мин)29:59, 30:00, 30:01
Ежедневный batch job (полночь)23:59:59, 00:00:00, 00:00:01
Високосный год (28/29 фев)28 фев, 29 фев, 1 мар
Переход на летнее/зимнее время01:59, 02:00, 03:00

Упражнение: BVA для политики паролей

Сценарий: Система применяет следующую политику паролей:

  • Длина: 8-64 символа
  • Минимум 1 заглавная буква
  • Минимум 1 цифра
  • Минимум 1 спецсимвол (!@#$%^&*)

Задание: Определите все граничные значения для требования длины и спроектируйте тест-кейсы с BVA трёх значений. Затем определите, как требования к типам символов создают дополнительные границы.

Подсказка

Для длины границы — 8 (минимум) и 64 (максимум). BVA трёх значений означает проверку 7, 8, 9 на нижней границе и 63, 64, 65 на верхней.

Для типов символов граница находится между 0 и 1 вхождением каждого обязательного типа. Подумайте о пароле с ровно 0 заглавных букв и ровно 1.

Решение

BVA длины (три значения):

#ДлинаТестовое значениеОжидаемый результат
17 символовAa1!xyzОтклонить (слишком короткий)
28 символовAa1!xyzwПринять (нижняя граница)
39 символовAa1!xyzwqПринять (чуть выше нижней)
463 символаAa1! + 59 xПринять (чуть ниже верхней)
564 символаAa1! + 60 xПринять (верхняя граница)
665 символовAa1! + 61 xОтклонить (слишком длинный)

Границы типов символов:

#ТестОжидаемый результат
70 заглавных: aa1!xyzwОтклонить
81 заглавная: Aa1!xyzwПринять
90 цифр: Aa!!xyzwОтклонить
101 цифра: Aa1!xyzwПринять
110 спецсимволов: Aa1bxyzwОтклонить
121 спецсимвол: Aa1!xyzwПринять

Итого: 12 тест-кейсов, покрывающих все границы длины и требований к типам символов.

Советы профессионала

  • Всегда сочетайте BVA с EP. BVA без EP упускает общую картину; EP без BVA пропускает самые насыщенные дефектами области.
  • Не забывайте ноль и пустое. Ноль элементов, строки нулевой длины и пустые коллекции — границы, выявляющие NullPointerException, деление на ноль и другие частые дефекты.
  • Учитывайте минимальный инкремент. Для целых чисел это 1, для валюты может быть 0.01, для timestamp — 1 секунда или 1 миллисекунда.
  • Проверяйте обе стороны каждой границы. У границы две стороны — валидная и невалидная. Пропуск любой оставляет дефекты непокрытыми.
  • В API проверяйте граничные значения в параметрах запроса, заголовках и обработке ответов. Границы в пагинации API (page=0, page=1, page=maxInt) часто содержат баги.