Какая техника тест-дизайна в первую очередь опирается на опыт и интуицию тестировщика?

Ответ

Эвристическое тестирование (Heuristic Testing) — это неформальный, опытный подход, при котором тестировщик проектирует и выполняет тесты, основываясь на своих знаниях, интуиции и общих эмпирических правилах (эвристиках), а не на строгих формальных спецификациях.

Ключевые особенности:

  • Опыт-ориентированность: Используется, когда документация скудна, время ограничено или система слишком сложна для полного формального анализа.
  • Эвристики (правила-подсказки): Общие принципы, выведенные из практики:
    • Эвристика CRUD: Проверь все операции Create, Read, Update, Delete для сущности.
    • Эвристика "золотого пути": Сначала протестируй самый частый и правильный сценарий.
    • Эвристика граничных значений: Особое внимание к минимуму, максимуму и значениям вокруг них.
    • Эвристика "Где ломалось раньше": Прицельный тест модулей, исторически склонных к ошибкам.

Основные приемы в рамках эвристического подхода:

  1. Исследовательское тестирование (Exploratory Testing): Одновременное изучение системы, проектирование и выполнение тестов. Сессия ограничена по времени и фокусу.
  2. Тестирование на основе проверочных списков (Checklist-Based Testing): Использование чек-листов, составленных из эвристик, чтобы ничего не упустить.
  3. Атаки на приложение (Attack Testing): Целенаправленные попытки "сломать" систему, имитируя действия злоумышленника или невнимательного пользователя.

Практический пример применения эвристик: Допустим, тестируется поле для ввода возраста (допустимый диапазон: 18-120).

# Эвристика: Граничные значения и неверные данные
test_values = [
    (17, False),   # Ниже минимума
    (18, True),    # Минимум (граница)
    (30, True),    # Нормальное значение
    (120, True),   # Максимум (граница)
    (121, False),  # Выше максимума
    (0, False),    # Ноль
    (-5, False),   # Отрицательное
    ("abc", False), # Строка
    ("", False),    # Пустое значение
    ("18", True)   # Число как строка (потенциальная проблема типов)
]

for input_val, expected in test_values:
    result = validate_age(input_val)
    print(f"Input: {input_val:>4}, Expected: {expected}, Got: {result}, {'OK' if result == expected else 'FAIL'}")

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

Ответ 18+ 🔞

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

Представь, что тебе дали какую-то новую хрень — сайт, приложение, микросервис, да похуй что. А документации к ней — ноль ебать. Точнее, она есть, но написана так, что после третьего абзаца хочется вилкой в глаз себе ткнуть. Или её писал тот самый чувак, который уже уволился, и теперь его творение понимает только его кот, сука собака. Вот тут-то и начинается магия, блядь. Не какая-то там заумная наука с формулами, а чистой воды искусство, основанное на опыте, интуиции и знании, где система обычно дает течь.

Что это за зверь такой? Это когда ты не идешь по строгому плану, как робот, а включаешь голову и начинаешь ебашить по системе, основываясь на своих прошлых косяках и общих правилах-подсказках. Эти правила и есть эвристики — типа народной мудрости для тестировщика.

Какие бывают эти подсказки, чтобы не выглядеть пиздопроебибной?

  • Правило CRUD: Любая сущность в системе — пользователь, заказ, пост — должна уметь рождаться (Create), читаться (Read), меняться (Update) и отправляться на хуй (Delete). Не работает что-то одно? Пиздец, а не функционал.
  • «Золотой путь»: Сначала проверь, работает ли вообще основной, самый правильный сценарий. Зачем ебаться с краевыми случаями, если базовая регистрация падает с ошибкой «попробуйте позже»? Сначала добейся, чтобы хоть что-то работало.
  • Граничные значения: Это святое, блядь. Если поле «возраст» от 18 до 120, то тебя должно волновать не только число 25, а что будет с 17, 18, 120 и 121. А также с нулём, минусом и текстом «я джва года». Вот тут-то и вылазят самые сочные баги.
  • «Где ломалось раньше»: Самый ценный принцип. У каждой системы есть свои больные места, которые косят её раз за разом. Нашел такое? Долби именно туда, там точно что-то всплывет.

А как этим всем пользоваться-то на практике?

  1. Исследовательское тестирование (Exploratory). Это когда ты садишься за систему и просто начинаешь её щупать. Без скриптов, но с мыслью в голове. «А что будет, если я тут нажму? А если ввести сюда ебучие смайлики?». Одновременно изучаешь и ломаешь. Сессия обычно ограничена по времени, чтобы не уйти в дебри и не начать тестировать, блядь, цвет кнопки в разных браузерах три дня.
  2. По чек-листу. Но не по тому, который спустило начальство, а по своему, составленному из тех самых эвристик. Чтобы не забыть проверить все те же граничные значения или CRUD для новой фичи. Список — он и в Африке список, мозги разгружает.
  3. Атаки на приложение. Самый весёлый метод. Включаешь внутреннего мудака/хакера и думаешь: «Как бы я сломал эту штуку?». Вводишь тонну данных, пытаешься отправить запрос мимо фронта, лезешь, куда не просят. Часто на этом этапе открываются такие дыры, что волосы дыбом.

Ну и пример, чтобы не быть пустословом, блядь. Допустим, тебе надо проверить то самое поле «возраст». Документация говорит: «от 18 до 120». Ну окей.

# Берём нашу эвристику про границы и невалидные данные и тыкаем палкой
test_values = [
    (17, False),   # Чуть-чуть недолет
    (18, True),    # Ровно в нижнюю границу, должно работать
    (30, True),    # Нормальное значение для дебила, который не знает, что тестировать
    (120, True),   # Ровно в потолок
    (121, False),  # Перелет, должен быть отказ
    (0, False),    # Ноль — явно не возраст
    (-5, False),   # Отрицательное число — ты что, из будущего?
    ("abc", False), # Буквы — а вдруг пропустят?
    ("", False),    # Пустота — классика
    ("18", True)   # Число как строка — вот тут часто бывает засада, если тип данных не проверяют
]

for input_val, expected in test_values:
    result = validate_age(input_val)
    print(f"Input: {input_val:>4}, Expected: {expected}, Got: {result}, {'OK' if result == expected else 'FAIL'}")

Запускаешь этот скрипт и смотришь, где система начнёт гнать. Если пропустит -5 или «abc» — пиши пропало, разработчикам прилетает.

Когда это всё впиндюривать в процесс? Да почти всегда, когда ты в неопределённости, как мартышлюшка в космосе. В начале проекта, чтобы быстро оценить, насколько всё хуёво. При регрессионном тестировании, чтобы быстро пробежаться по основным рискам. Или когда просто нужно проверить юзабилити — удобно ли это пользователю, или он тоже захочет вилкой в глаз, но уже разработчику.