Тестировщик замечает проявление проблемы: сообщение об ошибке, неверное число, пропавшую кнопку. Но то, что видно на экране, — почти никогда не сам дефект, а лишь его симптом. Между «что я вижу» и «что на самом деле сломано» лежит цепочка причин, и чем ниже по ней вы спуститесь, тем полезнее будет ваш баг-репорт — и тем быстрее дефект починят. Систематический спуск по этой цепочке называют анализом первопричин (root cause analysis).

Симптом → причины → первопричина

Худший случай — проблема вообще не замечена. Чуть лучше — репорт описывает только внешнее проявление («иногда не открывается отчёт»). Приемлемо — описаны причины, лежащие на поверхности. Идеал — добраться до двух нижних уровней цепочки:

  • Первопричина — конкретный изъян, порождающий всё дерево следствий.
  • Условия, способствовавшие её появлению — почему изъян вообще возник (это уже чаще вопрос к процессу, чем к коду).

Вся идея укладывается в три вопроса: что произошло, почему это произошло и как снизить вероятность повторения. Устранение первопричины ценнее заплатки на симптом: ненайденная первопричина продолжит порождать новые дефекты — в других местах и в других формах.

Пример: спуск по цепочке

Живой пример из практики. Консольная утилита обрабатывает каталоги; команда с абсолютным путём /var/www возвращает ошибку «SOURCE_DIR name [var/www] is not a valid directory» — хотя каталог существует и доступен.

  1. Проявление. В сообщении об ошибке имя каталога отличается от заданного: пропал начальный /. Несколько контрольных запусков подтверждают: начальный слеш исчезает во всех параметрах.
  2. Причина N. Проверяем относительные пути — работают. Проверяем под Windows — работает. Значит, дело в обработке введённых имён. Гипотеза: обрезаются начальные и конечные слеши.
  3. Причина N-1. Запуск с путями вида \\\\c:\\\\ подтверждает: приложение убирает все слеши в начале и конце имени, в любом количестве.
  4. Первопричина. Гипотеза: где-то в коде есть первичный фильтр путей, и он работает неверно. Заглянув в код разбора параметров (или попросив разработчика), находим метод, который «канонизирует» имя и срезает краевые разделители. Для Linux это фатально: любой абсолютный путь начинается со слеша.

Теперь сравните два репорта. «Приложение не обнаруживает доступные каталоги» — описание симптома: некорректное по сути, и всё исследование ложится на программиста. «Удаление краевых / и \ из параметров запуска ломает абсолютные пути в Linux» — описание первопричины: разработчику осталось исправить конкретный метод.

Алгоритм поиска

Универсальная последовательность:

  1. Определить проявление проблемы. Что именно происходит и почему это плохо?
  2. Собрать информацию. Происходит ли то же самое в других ситуациях? Всегда ли одинаково? От чего зависит появление и исчезновение проблемы? Это тот же приём, что и варьирование условий при исследовательском тестировании.
  3. Выдвинуть гипотезу о причине. Что может её вызывать? Какие действия или условия приводят к проявлению?
  4. Проверить гипотезу дополнительными экспериментами. Не подтвердилась — выдвинуть другую.
  5. Убедиться, что найдена первопричина, а не очередное звено цепи. Если звено промежуточное — повторить алгоритм уже для него. Если первопричина — сформулировать, что и где чинить.

Заглядывать в код необязательно (хотя полезно, если умеете читать его): часто достаточно грамотных экспериментов снаружи плюс вопроса разработчику «где в коде это может обрабатываться?».

Где это применяется

Каждый «плавающий» баг — это непройденный до конца анализ первопричины: воспроизводимость «иногда» означает ровно то, что закономерность не найдена. Каждый возвращённый с «не воспроизводится» репорт — чаще всего описание симптома вместо причины. И наоборот: тестировщик, который приносит не «что-то сломалось», а «ломается вот здесь, вот почему и вот при каких условиях», экономит команде часы и быстро зарабатывает репутацию сильного специалиста. Сам алгоритм — определить, собрать, предположить, проверить — универсален: он же работает при отладке, в инцидентах на проде и далеко за пределами ИТ.

Где спотыкаются начинающие:

  • Заводят репорт по первому проявлению, не сделав ни одной дополнительной проверки. Пять минут экспериментов часто превращают «иногда не работает» в чёткую закономерность.
  • Останавливаются на первой причине и принимают её за первопричину. Спросите себя: «а почему происходит это?» — пока вопрос имеет ответ, вы ещё не на дне цепочки.
  • Подгоняют факты под гипотезу. Гипотеза, которую вы не пытались опровергнуть, — не проверенная гипотеза. Ищите эксперимент, который может её сломать.

Что учить дальше. Как оформить найденное в репорт, который чинят, — в статье про качество баг-репорта; откуда берётся цепочка «ошибка → дефект → сбой» — в статье про то, что такое баг; техника вариации условий — в статье про исследовательское тестирование.