Как управлять ошибками в тестах
Что проверяют
Что вы делаете, когда тест упал или падает через раз: как находите причину, отличаете баг в коде от нестабильного теста и не даёте таким тестам обесценить CI. Следом обычно спрашивают про нестабильные тесты в Espresso и про тестирование корутин.
Как отвечать
- разделение уровней: локальные тесты на JVM (JUnit, MockK или Mockito) быстрые и детерминированные, инструментальные (Espresso, тесты Compose) медленнее и чаще нестабильны. Логику проверяют в первых, во вторых только интерфейс и интеграцию;
- ожидаемые исключения: проверяются явно через
assertThrowsилиassertFailsWith, а не черезtry-catchв теле теста; - асинхронность: для корутин
runTestизkotlinx-coroutines-testи подмена главного диспетчера черезDispatchers.setMainсоStandardTestDispatcher, Flow удобно проверять через Turbine. В Espresso вместоThread.sleepожидание черезIdlingResource; - изоляция: Android Test Orchestrator с
clearPackageDataзапускает каждый тест в отдельном процессе с чистыми данными, анимации отключаются черезtestOptions { animationsDisabled = true }; - диагностика: отчёты Gradle в
build/reports, скриншоты и logcat при падении, в CI воспроизводимые эмуляторы через Gradle Managed Devices; - нестабильные тесты: уходят в карантин с задачей на починку, а не перезапускаются до зелёного. Автоповтор допустим как временная мера, если число таких тестов отслеживается.
Покажите, что обработка ошибок самого приложения тоже покрыта: сетевые сбои, пустые и битые ответы удобно воспроизводить через MockWebServer.
Где спотыкаются
Оборачивают тест в try-catch и глотают исключение, в том числе AssertionError. Тест становится вечно зелёным и ничего не проверяет.
Вызывают android.util.Log в коде под локальным тестом и получают RuntimeException с сообщением «not mocked». Лечится абстракцией над логированием или Robolectric, а не бездумным включением isReturnDefaultValues.
Борются с нестабильностью через Thread.sleep. На медленном эмуляторе в CI задержки не хватит, а на быстрой машине тесты просто станут дольше.