← Назад к вопросам

Какие техники тест дизайна чаще всего используешь в работе?

1.7 Middle🔥 161 комментариев
#Теория тестирования

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI21 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Техники тест-дизайна в практике

В своей работе использую несколько техник, комбинируя их в зависимости от типа функционала и его сложности.

1. Граничные значения (Boundary Value Analysis)

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

Пример: Тестирование поля возраста пользователя (валидный диапазон 18-120 лет).

def test_age_validation():
    # Граничные значения
    assert validate_age(17) == False    # Ниже границы
    assert validate_age(18) == True     # На нижней границе
    assert validate_age(60) == True     # Внутри диапазона
    assert validate_age(120) == True    # На верхней границе
    assert validate_age(121) == False   # Выше границы

Результат: покрыл критичные точки тремя тестами вместо сотни случайных значений.

2. Эквивалентное разбиение (Equivalence Partitioning)

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

Пример: тестирование статуса заказа.

def test_order_processing():
    # Класс 1: новые заказы
    assert process_order(status="new") == "processing"
    
    # Класс 2: завершённые заказы
    assert process_order(status="completed") == "archived"
    
    # Класс 3: отменённые заказы
    assert process_order(status="cancelled") == "archived"
    
    # Класс 4: невалидные статусы
    with pytest.raises(InvalidOrderStatus):
        process_order(status="unknown")

Результат: вместо тестирования каждого статуса отдельно, проверяю представителя каждого класса.

3. Таблица решений (Decision Table)

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

Пример: скидка для покупателя зависит от количества и суммы покупки.

# Таблица решений:
# Quantity | Amount  | VIP | Expected Discount
# <=10     | <100    | No  | 0%
# <=10     | <100    | Yes | 5%
# <=10     | >=100   | No  | 5%
# <=10     | >=100   | Yes | 10%
# >10      | <100    | No  | 5%
# >10      | <100    | Yes | 10%
# >10      | >=100   | No  | 10%
# >10      | >=100   | Yes | 20%

import pytest

@pytest.mark.parametrize("quantity,amount,is_vip,expected", [
    (5, 50, False, 0),
    (5, 50, True, 5),
    (5, 150, False, 5),
    (5, 150, True, 10),
    (15, 50, False, 5),
    (15, 50, True, 10),
    (15, 150, False, 10),
    (15, 150, True, 20),
])
def test_discount_calculation(quantity, amount, is_vip, expected):
    discount = calculate_discount(quantity, amount, is_vip)
    assert discount == expected

Результат: систематически покрыл все комбинации условий.

4. Тестирование состояний и переходов (State Transition Testing)

Когда использую: когда объект проходит через разные состояния (заказ: новый → обработка → доставка → доставлен).

Пример: Payment Processing.

def test_payment_state_transitions():
    payment = Payment()
    
    # Валидные переходы
    assert payment.status == "pending"
    payment.authorize()  # pending -> authorized
    assert payment.status == "authorized"
    payment.capture()    # authorized -> captured
    assert payment.status == "captured"
    
    # Невалидные переходы (должны вызвать ошибку)
    with pytest.raises(InvalidStateTransition):
        payment.capture()  # уже в captured
    
    with pytest.raises(InvalidStateTransition):
        payment.authorize()  # уже прошли этот переход

Результат: проверил все корректные переходы и попытки неправильных переходов.

5. Pair-wise Testing (попарное тестирование)

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

Пример: Тестирование фильтров (Browser × OS × Resolution × Theme).

# Вместо 4 × 3 × 3 × 2 = 72 комбинации
# Попарное: ~10-15 тестов, покрывающих все пары

import pytest
from allpairspy import AllPairs

parameters = [
    ["Chrome", "Firefox", "Safari", "Edge"],      # Browser
    ["Windows", "macOS", "Linux"],                 # OS
    ["1920x1080", "1366x768", "768x1024"],        # Resolution
    ["light", "dark"],                             # Theme
]

pairs = list(AllPairs(parameters))

@pytest.mark.parametrize("browser,os,resolution,theme", pairs)
def test_app_compatibility(browser, os, resolution, theme):
    driver = setup_driver(browser, os, resolution, theme)
    # тест...

Результат: вместо 72 комбинаций — 15 тестов, но покрыл все попарные взаимодействия.

6. Mutation Testing

Когда использую: для проверки качества своих тестов (способны ли они поймать ошибки в коде).

# Инструмент: mutmut (Python)
pip install mutmut
mutmut run
mutmut results

Пример:

def calculate_bonus(salary: float, years: int) -> float:
    if years < 1:
        return 0
    if years < 5:
        return salary * 0.05
    if years < 10:
        return salary * 0.1
    return salary * 0.15

def test_bonus():
    assert calculate_bonus(1000, 0) == 0
    assert calculate_bonus(1000, 2) == 50
    assert calculate_bonus(1000, 7) == 100
    assert calculate_bonus(1000, 15) == 150

mutmut попробует изменить код (например, years < 5 на years <= 5), и проверит, поймет ли тест эту мутацию. Если нет — у теста есть gaps.

7. Use Case / User Journey Testing

Когда использую: для end-to-end сценариев, реальных пользовательских путей.

def test_complete_purchase_flow():
    """Покупатель заходит в приложение и покупает товар"""
    driver = get_driver()
    
    # Use Case: Browse → Add to Cart → Checkout → Payment → Confirmation
    home_page = HomePage(driver)
    home_page.navigate()
    
    search_page = home_page.search("laptop")
    product_page = search_page.click_first_result()
    
    cart_page = product_page.add_to_cart()
    checkout_page = cart_page.proceed_to_checkout()
    
    payment_page = checkout_page.fill_shipping_info()
    confirmation_page = payment_page.pay_with_card("4111111111111111")
    
    assert "Order Confirmed" in confirmation_page.get_title()

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

8. Exploratory Testing (в контексте автоматизации)

Когда использую: когда документация неполная или требования нечёткие, сначала исследую функционал ручно, потом автоматизирую.

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

Выбор техники: практический подход

Тип функционалаТехникаИнструмент
Валидация числовых полейBoundary Valuespytest.mark.parametrize
Сложная бизнес-логикаDecision Tableallpairspy
워ークфлоу с состояниямиState Transitionpytest
Интеграционные тестыUse Case TestingPlaywright / Selenium
Критичные путиUser JourneyPlaywright
Качество тестовMutation Testingmutmut

Комбинирование техник

В реальных проектах часто комбинирую:

# Эквивалентное разбиение × Boundary Values
@pytest.mark.parametrize("age,expected_category", [
    (0, "invalid"),      # Граница: минимум
    (1, "child"),        # Класс: дети (1-17)
    (17, "child"),       # Граница: верх
    (18, "adult"),       # Граница: низ
    (65, "adult"),       # Класс: взрослые (18-64)
    (64, "adult"),       # Граница: верх
    (65, "senior"),      # Граница: низ
    (150, "invalid"),    # Граница: максимум
])
def test_age_categorization(age, expected_category):
    assert categorize_age(age) == expected_category

Итог

Не использую одну технику на все случаи. Выбор зависит от:

  • Типа функционала (простой → сложный)
  • Количества параметров (мало → много)
  • Критичности (низко → высоко)
  • Времени на разработку (есть → нет)

Ключевая идея: минимум тестов, максимум покрытия рисков.

Какие техники тест дизайна чаще всего используешь в работе? | PrepBro