Как вы применяете технику анализа граничных значений при тестировании?

«Как вы применяете технику анализа граничных значений при тестировании?» — вопрос из категории Техники тест-дизайна, который задают на 10% собеседований QA Тестировщик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Анализ граничных значений (Boundary Value Analysis, BVA) — это техника тест-дизайна для проверки поведения системы на границах допустимых диапазонов. Вот системный подход:

1. Основная теория: Для диапазона [min, max] тестируем:

  • min-1 (нижняя недопустимая граница)
  • min (нижняя допустимая граница)
  • min+1 (внутри диапазона, близко к границе)
  • max-1 (внутри диапазона, близко к границе)
  • max (верхняя допустимая граница)
  • max+1 (верхняя недопустимая граница)

2. Практические примеры:

Пример 1: Поле возраста (18-65 лет)

import pytest

@pytest.mark.parametrize("age,expected_valid", [
    (17, False),   # Ниже минимума
    (18, True),    # Минимальное допустимое
    (19, True),    # Чуть выше минимума
    (30, True),    # Типичное значение
    (64, True),    # Чуть ниже максимума
    (65, True),    # Максимальное допустимое
    (66, False),   # Выше максимума
    (0, False),    # Экстремально низкое
    (150, False),  # Экстремально высокое
])
def test_age_validation(age, expected_valid):
    result = validate_age(age)
    assert result.is_valid == expected_valid

    if not expected_valid:
        # Проверяем сообщение об ошибке
        assert "age must be between 18 and 65" in result.error_message

Пример 2: Поле длины строки (1-255 символов)

describe('String length validation', () => {
  const testCases = [
    { input: '', expected: false },           // 0 символов
    { input: 'a', expected: true },           // 1 символ (min)
    { input: 'ab', expected: true },          // 2 символа (min+1)
    { input: 'a'.repeat(254), expected: true }, // 254 символа (max-1)
    { input: 'a'.repeat(255), expected: true }, // 255 символов (max)
    { input: 'a'.repeat(256), expected: false }  // 256 символов (max+1)
  ];

  testCases.forEach(({ input, expected }) => {
    it(`validates "${input.length} chars" correctly`, () => {
      expect(isValidString(input)).toBe(expected);
    });
  });
});

3. Особые случаи и расширения:

Эквивалентные классы с границами:

# Для поля "Количество товаров в корзине" (0-99)
test_cases = [
    # Отрицательные значения
    (-1, "error"),
    (-100, "error"),

    # Граница 0
    (0, "success"),  # Пустая корзина допустима

    # Нормальные значения
    (1, "success"),
    (50, "success"),

    # Верхняя граница
    (99, "success"),
    (100, "error"),

    # Большие числа
    (999, "error"),
]

4. Граничные значения для дат и времени:

from datetime import datetime, timedelta

# Тестирование скидки, действующей с 2024-01-01 по 2024-12-31
test_dates = [
    (datetime(2023, 12, 31), False),  # За день до начала
    (datetime(2024, 1, 1), True),     # Первый день акции
    (datetime(2024, 1, 2), True),     # Второй день
    (datetime(2024, 12, 30), True),   # Предпоследний день
    (datetime(2024, 12, 31), True),   # Последний день
    (datetime(2025, 1, 1), False),    # День после окончания
]

5. Интеграция с другими техниками:

  • Попарное тестирование (Pairwise) для комбинаций нескольких полей с граничными значениями
  • Таблицы решений для сложных бизнес-правил с граничными условиями
  • Диаграммы переходов состояний для проверки граничных переходов

6. Автоматизация проверки граничных значений:

class BoundaryTester:
    def __init__(self, min_val, max_val):
        self.min = min_val
        self.max = max_val

    def generate_test_values(self):
        """Генерирует стандартный набор граничных значений"""
        return [
            self.min - 1,
            self.min,
            self.min + 1,
            (self.min + self.max) // 2,  # Среднее значение
            self.max - 1,
            self.max,
            self.max + 1
        ]

    def test_boundaries(self, validation_func):
        """Запускает тесты для всех граничных значений"""
        for value in self.generate_test_values():
            is_valid = self.min <= value <= self.max
            result = validation_func(value)

            assert result.is_valid == is_valid, 
                f"Failed for value {value}. Expected valid={is_valid}"

            if not is_valid:
                assert hasattr(result, 'error'), 
                    f"Error message missing for invalid value {value}"

Ключевые принципы:

  1. 7 тест-кейсов на один диапазон (min-1, min, min+1, nominal, max-1, max, max+1)
  2. Обработка ошибок – система должна давать понятные сообщения
  3. Инклюзивность/эксклюзивность – четкое понимание, включены ли границы в диапазон
  4. Смежные диапазоны – особое внимание стыкам между диапазонами