Modern QA2026Анализ граничных значений и эквивалентное разбиение с помощью ИИ
Join

Course02 AI-Augmented Test Design

Cutting-edge · Chapter 02

Анализ граничных значений и эквивалентное разбиение с помощью ИИ

Updated Jul 2026

Почему классические техники по-прежнему важны

Анализ граничных значений (BVA) и эквивалентное разбиение (EP) -- одни из старейших формальных техник проектирования тестов, восходящие к 1970-м годам. Они остаются фундаментальными, потому что отражают универсальную истину: ошибки концентрируются на границах. Ошибки на единицу, путаница между включающими и исключающими диапазонами, а также граничные случаи приведения типов составляют непропорционально большую долю дефектов в продакшене.

Что изменилось -- так это скорость, с которой вы можете применять эти техники. Ручное определение всех разбиений и граничных значений для сложного API с 15 входными полями занимает часы. С ИИ это занимает минуты -- и ИИ с меньшей вероятностью забудет крайний случай.

Анализ граничных значений с ИИ

Паттерн промпта

Опишите ограничения входных данных и позвольте LLM перечислить все границы:

Given the following input field constraints, generate boundary value test cases:

Field: age (integer)
Valid range: 18-65 (inclusive)
Required: yes

Generate test values for:
- Just below minimum (17)
- At minimum (18)
- Just above minimum (19)
- Nominal value (40)
- Just below maximum (64)
- At maximum (65)
- Just above maximum (66)
- Zero
- Negative (-1)
- Null/undefined
- Non-numeric ("abc")
- Float (18.5)
- Very large number (999999999)
- Empty string

For each, state: input value, expected result (accept/reject), and why.

Ожидаемый вывод

Хорошо обученная LLM возвращает структурированную таблицу:

Входное значение Ожидаемый результат Обоснование
17 Отклонить Ниже минимальной границы
18 Принять Минимальная граница (включительно)
19 Принять Чуть выше минимума
40 Принять Номинальное/среднее значение
64 Принять Чуть ниже максимума
65 Принять Максимальная граница (включительно)
66 Отклонить Выше максимальной границы
0 Отклонить Ниже минимума
-1 Отклонить Отрицательное число
null Отклонить Обязательное поле
"abc" Отклонить Несоответствие типа
18.5 Отклонить Не целое число
999999999 Отклонить Выше максимума
"" Отклонить Пустое/обязательное поле

Преобразование BVA-таблиц в код

Таблица выше напрямую преобразуется в параметризованные тесты:

import pytest

class TestAgeValidation:
    """Boundary value tests for the age field."""

    @pytest.mark.parametrize("age,should_accept", [
        (17, False),        # Just below minimum
        (18, True),         # Minimum boundary (inclusive)
        (19, True),         # Just above minimum
        (40, True),         # Nominal/mid-range
        (64, True),         # Just below maximum
        (65, True),         # Maximum boundary (inclusive)
        (66, False),        # Just above maximum
        (0, False),         # Zero
        (-1, False),        # Negative
    ])
    def test_age_integer_boundaries(self, client, age, should_accept):
        response = client.post("/api/users", json={"age": age, "name": "Test"})
        if should_accept:
            assert response.status_code == 201, f"age={age} should be accepted"
        else:
            assert response.status_code == 400, f"age={age} should be rejected"

    @pytest.mark.parametrize("age,description", [
        (None, "null value"),
        ("abc", "non-numeric string"),
        (18.5, "float instead of integer"),
        ("", "empty string"),
        (999999999, "extremely large number"),
    ])
    def test_age_type_boundaries(self, client, age, description):
        response = client.post("/api/users", json={"age": age, "name": "Test"})
        assert response.status_code == 400, f"age={age} ({description}) should be rejected"

Многопольное BVA

Реальные API имеют несколько полей с ограничениями. Попросите ИИ сгенерировать BVA для всех сразу:

Generate boundary value test cases for the following fields in the
POST /api/v2/products endpoint:

Fields:
- name: string, required, minLength=1, maxLength=200
- price: number, required, minimum=0 (exclusive: price > 0)
- quantity: integer, required, minimum=0 (inclusive), maximum=10000
- weight_kg: number, optional, minimum=0.01, maximum=500.0

For each field, test:
- At and around each boundary (min-1, min, min+1, max-1, max, max+1)
- Type mismatches
- Null/missing
- Empty string (for string fields)
- Precision limits (for number fields: 0.001, 0.009, etc.)

Эквивалентное разбиение с помощью ИИ

Концепция

Эквивалентное разбиение делит входное пространство на классы, в которых все значения ведут себя одинаково. Вы тестируете один репрезентативный экземпляр из каждого класса вместо всех возможных значений.

Паттерн промпта

For the following API endpoint, identify equivalence classes for each input
parameter and generate one representative test per class:

POST /api/orders
{
  "product_id": "string (UUID format)",
  "quantity": "integer (1-100)",
  "shipping_method": "enum: standard | express | overnight",
  "coupon_code": "string (optional, alphanumeric, 8 chars)"
}

For each parameter, identify:
1. Valid equivalence classes
2. Invalid equivalence classes
3. One representative value per class

Ожидаемый вывод

LLM должна выдать разбиения наподобие:

product_id:

  • Валидный класс 1: существующий UUID ("550e8400-e29b-41d4-a716-446655440000")
  • Невалидный класс 1: несуществующий UUID ("00000000-0000-0000-0000-000000000000")
  • Невалидный класс 2: не UUID ("not-a-uuid")
  • Невалидный класс 3: пустая строка ("")
  • Невалидный класс 4: null

quantity:

  • Валидный класс 1: минимум (1)
  • Валидный класс 2: середина диапазона (50)
  • Валидный класс 3: максимум (100)
  • Невалидный класс 1: ноль (0)
  • Невалидный класс 2: отрицательное (-5)
  • Невалидный класс 3: выше максимума (101)
  • Невалидный класс 4: не целое число (2.5)
  • Невалидный класс 5: не числовое ("ten")

shipping_method:

  • Валидный класс 1: "standard"
  • Валидный класс 2: "express"
  • Валидный класс 3: "overnight"
  • Невалидный класс 1: значение не из перечисления ("drone")
  • Невалидный класс 2: пустая строка ("")
  • Невалидный класс 3: вариант регистра ("Standard")

coupon_code:

  • Валидный класс 1: валидный код ("SAVE20AB")
  • Валидный класс 2: отсутствует/опущен (необязательное поле)
  • Невалидный класс 1: слишком короткий ("SAVE20")
  • Невалидный класс 2: слишком длинный ("SAVE20ABC")
  • Невалидный класс 3: не алфавитно-цифровой ("SAVE-20!")
  • Невалидный класс 4: нижний регистр ("save20ab")

Преобразование EP в параметризованные тесты

class TestOrderCreationPartitions:
    """Equivalence partition tests for POST /api/orders."""

    @pytest.mark.parametrize("quantity,expected_status", [
        (1, 201),       # Valid: minimum
        (50, 201),      # Valid: mid-range
        (100, 201),     # Valid: maximum
        (0, 400),       # Invalid: zero
        (-5, 400),      # Invalid: negative
        (101, 400),     # Invalid: above max
    ])
    def test_quantity_partitions(self, client, auth, valid_product, quantity, expected_status):
        response = client.post("/api/orders", json={
            "product_id": str(valid_product.id),
            "quantity": quantity,
            "shipping_method": "standard",
            "idempotency_key": str(uuid4()),
        }, headers=auth)
        assert response.status_code == expected_status

    @pytest.mark.parametrize("method,expected_status", [
        ("standard", 201),
        ("express", 201),
        ("overnight", 201),
        ("drone", 400),
        ("", 400),
        ("Standard", 400),   # Case sensitivity check
    ])
    def test_shipping_method_partitions(self, client, auth, valid_product, method, expected_status):
        response = client.post("/api/orders", json={
            "product_id": str(valid_product.id),
            "quantity": 1,
            "shipping_method": method,
            "idempotency_key": str(uuid4()),
        }, headers=auth)
        assert response.status_code == expected_status

Комбинирование BVA и EP: мощный приём

Наиболее тщательный подход комбинирует обе техники. Используйте EP для определения классов, затем BVA для тестирования границ каждого класса.

For the "quantity" field (integer, range 1-100):

Equivalence classes:
  Valid: [1, 100]
  Invalid below: [-inf, 0]
  Invalid above: [101, +inf]

Boundary values:
  -1 (invalid below, near zero)
  0  (invalid below, at boundary)
  1  (valid, lower boundary)
  2  (valid, just above lower boundary)
  50 (valid, nominal)
  99 (valid, just below upper boundary)
  100 (valid, upper boundary)
  101 (invalid above, at boundary)

Эта комбинация даёт ровно 8 тестовых значений, покрывающих всё входное пространство с высокой уверенностью. Без ИИ определение и кодирование всех 8 значений занимает 15-20 минут на поле. С ИИ -- менее минуты.

Практические советы для обсуждения на собеседованиях

При обсуждении BVA/EP с интервьюерами:

  1. Знайте терминологию. «Граничное значение», «класс эквивалентности», «разбиение» -- это термины, которые свидетельствуют о формальной подготовке.

  2. Объясните экономику. «Полное исчерпывающее тестирование формы с 5 полями по 10 значений каждое требует 100 000 комбинаций. EP сокращает это до примерно 30-50 тестов с аналогичной способностью обнаружения дефектов на уровне категорий.»

  3. Покажите преимущество ИИ. «Я использую ИИ для перечисления разбиений и граничных значений из OpenAPI-схемы, затем преобразую таблицу в параметризованные тесты. Это превращает полудневной ручной анализ в 15-минутный автоматизированный процесс.»

  4. Признайте ограничения. «BVA и EP отлично подходят для валидации входных данных, но не ловят ошибки бизнес-логики, состояния гонки или сбои интеграции. Это один слой в многоуровневой стратегии тестирования.»

Ключевой вывод

BVA и EP -- это классические техники, которые стали значительно быстрее с ИИ. Вместо того чтобы вручную определять разбиения, опишите входной домен и позвольте LLM перечислить их. Затем преобразуйте результат в параметризованные тесты для максимального покрытия при минимальном количестве тестов.