Классификация падений: интерпретация Stacktrace и Allure-отчетов
Классификация падений: интерпретация Stacktrace и Allure-отчетов
Представьте типичную пятницу: вы запускаете регресс проекта aeqs-api-test (наша система управления потоком клиентов), и тест assignClientToManagerTest загорается красным. Вы тратите час, проверяя базу данных, дергая разработчиков и перезапуская поды в Kubernetes, чтобы в итоге обнаружить, что в тесте просто отвалилась авторизация из-за протухшего токена.
Около 80% времени при отладке автотестов тратится впустую из-за неверного первого шага. Умение за 30 секунд прочитать отчет Allure и понять, в какую сторону копать, — это главный навык инженера по автоматизации.
В этой главе мы научимся отфильтровывать информационный шум и безошибочно определять класс проблемы.
Allure: Симптомы болезни
Когда мы открываем упавший тест в Allure, первое, на что нужно обратить внимание — это статус падения. Allure (и большинство тестовых фреймворков) концептуально разделяет все неуспешные тесты на две категории: Failed и Broken.
Это не просто разница в цвете иконки, это фундаментальное различие в природе ошибки.
| Статус в Allure | Цвет | Смысл | Типичные исключения | Где искать проблему |
|---|---|---|---|---|
| Failed (Упал) | Красный | Тест технически отработал корректно, но бизнес-логика приложения не совпала с ожиданиями. | AssertionError, ComparisonFailure |
В требованиях (Jira/Confluence) или в коде продукта (баг). |
| Broken (Сломан) | Желтый | Тест не смог выполниться до конца из-за технической ошибки (упал в процессе подготовки или выполнения). | NullPointerException, ConnectException, TimeoutException |
В коде самого автотеста, тестовых данных или инфраструктуре. |
Если тест желтый — бессмысленно идти к разработчику продукта. Проблема на нашей стороне: не поднялся браузер, недоступен тестовый стенд, или мы пытаемся обратиться к пустому объекту. Если тест красный — инфраструктура в порядке, API ответило, но ответило не то.
Анатомия Stacktrace: Ищем иголку в стоге сена
Определив статус, мы смотрим в Stacktrace — историю вызовов функций, которая привела к ошибке. Для новичка он выглядит как пугающая стена текста, но на деле 90% этих строк — информационный мусор фреймворков.
Stacktrace читается сверху вниз, но истинная причина часто кроется в самом низу, после слов
Caused by:(Вызвано тем-то).
Правило чтения стектрейса простое: ищите свой код.
Ваш проект имеет определенный пакет (package). Например, в нашем случае это ru.aeqs.api. Все строки, начинающиеся с java.base, org.junit, io.restassured или jdk.internal — это внутренности языков и библиотек. Они лишь передают ошибку наверх. Истинное место падения — это верхняя строка стектрейса, которая относится к вашему проекту.
Практика: разбор падения в aeqs-api-test
Рассмотрим реальный пример. Наш тест создает клиента в очереди и проверяет, что API возвращает статус IN_PROGRESS. Тест упал со статусом Broken. В Allure мы видим следующий лог:
java.lang.RuntimeException: Failed to create client flow
at ru.aeqs.api.steps.ClientSteps.createFlow(ClientSteps.java:45)
at ru.aeqs.api.tests.ClientQueueTest.assignClientToManagerTest(ClientQueueTest.java:22)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
... 25 more
Caused by: java.net.ConnectException: Connection refused: connect
at java.base/sun.nio.ch.Net.connect0(Native Method)
at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:75)
at ru.aeqs.api.clients.RestClient.sendPost(RestClient.java:89)
at ru.aeqs.api.steps.ClientSteps.createFlow(ClientSteps.java:43)
... 28 more
Давайте применим наш алгоритм:
- Игнорируем шум: Строки
org.junit...иjava.base...пропускаем. - Ищем корень: Видим блок
Caused by: java.net.ConnectException: Connection refused. Это означает, что приложение физически не смогло установить сетевое соединение. - Ищем свой код: В блоке
Caused byспускаемся до первой строки нашего проекта —ru.aeqs.api.clients.RestClient.sendPost(RestClient.java:89).
Вывод: ошибка произошла в нашем классе RestClient на 89-й строке, когда тест пытался отправить POST-запрос, но сервер отклонил подключение. Это типичная инфраструктурная проблема (упал тестовый стенд или неверный URL).
Алгоритм первичной классификации
Теперь мы можем собрать наши знания в единый алгоритм действий. Каждый раз, когда вы видите упавший тест, задайте себе три вопроса в строгой последовательности:
- Это Failed (Assertion) или Broken (Exception)?
- Если Failed — идем изучать логику ответа API и сверять с требованиями.
- Если Broken — переходим к шагу 2.
- Где в моем коде произошла ошибка?
- Находим блок
Caused by(если есть). - Находим верхнюю строку с пакетом
ru.aeqs.api....
- Находим блок
- К какому слою относится исключение?
- Сетевой слой (
ConnectException,SocketTimeoutException) → Проверяем доступность стенда. - Слой данных (
NullPointerException,IndexOutOfBoundsException) → Проверяем тестовые данные (возможно, клиент не создался в базе). - Слой парсинга (
JsonMappingException) → Изменился контракт API, мы не можем прочитать ответ.
- Сетевой слой (
Этот алгоритм — ваш фильтр. Он позволяет за минуту отсечь ложные пути. Если мы классифицировали ошибку как сбой бизнес-логики (API вернуло 500 ошибку вместо 200, и сработал AssertionError), нам уже недостаточно просто Allure-отчета. Нам нужно заглянуть "под капот" самого приложения. Как именно искать причины таких ответов в логах микросервисов, мы подробно разберем в следующей главе.