Оглавление
Введение
Что такое исключения
Иерархия исключений
Обработка исключений
Типы исключений
Заключение
Введение
Когда пишешь автотесты на Java, рано или поздно сталкиваешься с ситуацией: тест упал, в консоли — длинная портянка текста, и непонятно, с чего начать разбираться. Элемент не найден? Переменная оказалась пустой? Или что-то совсем неожиданное?
Все эти падения — результат работы системы исключений (exceptions). Это встроенный механизм Java, который сигнализирует: «Что-то пошло не так, и вот что именно». Понимание того, как устроены исключения, помогает автоматизатору писать тесты, которые корректно реагируют на непредвиденные ситуации и не рушатся при малейшей проблеме. Так же эта тема является популярной на собеседованиях.
Что такое исключения
Исключение (Exception) — это событие, которое нарушает нормальный ход выполнения программы.
Проще говоря, это “сигнал” от JVM: что-то пошло не так во время выполнения кода.
Например:
Попытка открыть несуществующий файл →
FileNotFoundExceptionОбращение к неинициализированной переменной →
NullPointerExceptionКлик по несуществующему элементу →
NoSuchElementException
Если не обработать такое событие, программа завершится с ошибкой. Но Java даёт возможность перехватывать и обрабатывать исключения с помощью специальных конструкций.
Иерархия исключений
Всё начинается с класса Throwable, который является базовым для всех ошибок и исключений в Java. Всё, что может быть «брошено» с помощью throw, наследуется от него.
От Throwable наследуются два больших семейства: Error и Exception. Эти два типа можно условно разделить на системные ошибки, связанные с работой JVM и ресурсов системы, и программные ошибки, которые возникают в ходе выполнения кода и с которыми программа может справиться.

Error — это ошибки, связанные с самой виртуальной машиной Java или системными ресурсами. Обычно их не обрабатывают в коде, потому что они сигнализируют о серьёзных проблемах, от которых программа не сможет восстановиться. Примеры таких ошибок: OutOfMemoryError, StackOverflowError, VirtualMachineError. Для тестировщика важно понимать, что эти ошибки могут возникнуть при работе с большим количеством тестов или больших объёмов данных и их решают на уровне настроек среды, а не через обработку в коде.
Exception — это исключения, которые можно и нужно обрабатывать. Они показывают, что во время работы программы возникла проблема, с которой можно что-то сделать. Исключения делятся на два типа: проверяемые и непроверяемые.
Проверяемые исключения (checked) компилятор требует обязательно обработать или указать в сигнатуре метода. К ним относятся, например, IOException и SQLException. Они чаще всего связаны с внешними ресурсами, такими как файлы, базы данных или сетевые соединения.
Непроверяемые исключения (unchecked) наследуются от RuntimeException. Их можно не ловить, и компилятор не будет ругаться, но они часто приводят к падению программы, если их не предусмотреть. К таким исключениям относятся NullPointerException, IndexOutOfBoundsException и NoSuchElementException. Обычно они возникают из-за ошибок в логике программы или тестов.
Ссылки на официальную документацию Java для исключений
Error (критические ошибки JVM):
RuntimeException (непроверяемые исключения):
Checked Exception (проверяемые исключения):
Обработка исключений
Исключения в Java нужны для того, чтобы программа могла корректно реагировать на ошибки, не падала полностью и давала возможность продолжить работу или корректно завершиться. Для тестировщика это особенно важно, чтобы автотесты могли безопасно обрабатывать неожиданные ситуации и логировать их.
Когда в программе возникает исключение, есть два основных варианта действий:
Перехватить и обработать исключение — программа «ловит» ошибку и выполняет действия, которые позволяют безопасно продолжить выполнение или корректно завершить работу.
Пробросить исключение дальше — передать его выше по стеку вызовов, чтобы обработка произошла в другом месте.
try-catch-finally
try — блок кода, в котором может произойти ошибка.
catch — блок, который перехватывает конкретное исключение и позволяет с ним работать.
finally — блок, который выполняется всегда, независимо от того, произошло ли исключение. Обычно используется для освобождения ресурсов.
Пример:
WebDriver driver = null;
try {
driver = new ChromeDriver();
driver.get("https://example.com");
} catch (WebDriverException e) {
System.out.println("Не удалось запустить браузер: " + e.getMessage());
} finally {
if (driver != null) {
driver.quit();
}
System.out.println("Блок finally выполняется всегда");
}
Можно использовать несколько блоков catch для разных типов исключений:
try {
int[] numbers = {1, 2, 3};
System.out.println(numbers[5]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Ошибка индекса массива");
} catch (Exception e) { // Важно: более общее исключение должно быть ниже!
System.out.println("Общее исключение");
}
throw
Оператор
throwсоздаёт и «выбрасывает» исключение вручную.Используется, когда метод сталкивается с ситуацией, которую он не может обработать сам.
Пример:
public void checkAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("Возраст не может быть отрицательным");
}
System.out.println("Возраст корректный");
}
throws
С помощью
throwsметод сообщает, какие исключения он может выбросить.Вызывающий метод должен либо обработать эти исключения, либо тоже указать их через
throws.
Пример:
public void readFile() throws IOException {
FileReader reader = new FileReader("data.txt");
}
try-with-resources
Это специальная форма
try, которая автоматически закрывает ресурсы (например, файлы, потоки, соединения с базой данных) после завершения блока.Ресурс должен реализовывать интерфейс
AutoCloseable.Позволяет не писать отдельный блок
finallyдля освобождения ресурсов — методclose()вызывается автоматически.
Пример:
try (FileReader reader = new FileReader("data.txt");
BufferedReader bufferedReader = new BufferedReader(reader)) {
String line = bufferedReader.readLine();
System.out.println("Первая строка: " + line);
} catch (IOException e) {
System.out.println("Ошибка при работе с файлом: " + e.getMessage());
}
// reader и bufferedReader автоматически закрыты здесь
Можно объявить несколько ресурсов через точку с запятой — все они будут закрыты автоматически в обратном порядке объявления.
Сравните с подходом без try-with-resources:
FileReader reader = null;
BufferedReader bufferedReader = null;
try {
reader = new FileReader("data.txt");
bufferedReader = new BufferedReader(reader);
String line = bufferedReader.readLine();
System.out.println("Первая строка: " + line);
} catch (IOException e) {
System.out.println("Ошибка при работе с файлом: " + e.getMessage());
} finally {
try {
if (bufferedReader != null) bufferedReader.close();
if (reader != null) reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Как видите, try-with-resources делает код намного чище и безопаснее.
Проброс исключения
Иногда метод не может обработать ошибку сам и передаёт её выше по стеку вызовов с помощью throws. Это называется пробросом исключения.
В реальных автотестах часто бывает цепочка методов: один метод вызывает другой, и исключение «поднимается» по цепочке, пока не будет обработано.
Пример с цепочкой из трёх методов:
public void readFile() throws IOException {
FileReader reader = new FileReader("data.txt"); // может выбросить IOException
}
public void processFile() throws IOException {
readFile(); // вызываем метод, который может выбросить исключение
}
public void runTest() {
try {
processFile(); // вызываем верхний метод цепочки
} catch (IOException e) {
System.out.println("Не удалось прочитать файл: " + e.getMessage());
}
}
В этом примере:
readFile()— сам не обрабатывает исключение, указывает черезthrows, что оно может произойти.processFile()— также не обрабатывает, а пробрасывает дальше.runTest()— перехватывает исключение и решает, что с ним делать.
Такой подход помогает разделять ответственность: методы, выполняющие действия, не обязаны решать все проблемы сами, вызывающий код может принять решение о правильной обработке ошибки.
Когда пробрасывать, а когда обрабатывать? Пробрасывайте, если метод не может корректно обработать ошибку. Обрабатывайте на уровне, где знаете, что делать с ошибкой.
Типы исключений
RuntimeException (непроверяемые исключения)
Исключение |
Что значит |
|---|---|
|
Попытка обратиться к null |
|
Выход за пределы массива или списка |
|
Элемент не найден |
|
Метод получил неверный аргумент |
|
Деление на ноль или другие арифметические ошибки |
|
Метод вызван в неправильном состоянии объекта |
|
Неверное приведение объекта к другому типу |
|
Операция не поддерживается |
|
Коллекция была изменена во время итерации |
|
Неверный формат числа |
Checked Exception (проверяемые исключения)
Исключение |
Что значит |
|---|---|
|
Ошибка ввода/вывода |
|
Файл не найден |
|
Ошибка запроса к базе данных |
|
Класс не найден в classpath |
|
Поток был прерван |
|
Ошибка разбора формата |
|
Некорректный URL |
|
Ошибка подключения |
|
Неожиданный конец файла или потока |
Error (критические ошибки JVM)
Исключение |
Что значит |
|---|---|
|
Закончилась память |
|
Переполнение стека |
|
Ошибка виртуальной машины |
|
Внутренняя ошибка JVM |
|
Неизвестная критическая ошибка |
|
Конфликт версий классов или библиотек |
|
Проверка (assert) не прошла |
Исключения Selenium WebDriver (непроверяемые)
Исключение |
Что значит |
|---|---|
|
Элемент не найден на странице |
|
Элемент был обновлён или исчез со страницы |
|
Элемент не доступен для взаимодействия (не кликабелен) |
|
Элемент не появился за отведённое время |
|
Общая ошибка WebDriver |
|
Окно или вкладка браузера не найдены |
|
Фрейм не найден на странице |
|
Некорректный CSS или XPath селектор |
|
Клик перехвачен другим элементом (например, модалкой) |
|
Alert отсутствует на странице |
Примечание: Все исключения Selenium WebDriver наследуются от RuntimeException, поэтому их можно не обрабатывать явно, но в автотестах рекомендуется их перехватывать для более информативного логирования и корректной обработки ошибок.
Заключение
Исключения в Java — сигнализируют о проблемах в коде или окружении, помогают быстрее находить баги и принимать правильные решения. Понимая, как читать, обрабатывать и пробрасывать исключения, вы сможете писать более надёжные и устойчивые автотесты, которые не падают из-за непредвиденных ситуаций.
