THREADQAОбразовательная платформа
    THREADQA
    Главная
    Услуги
    Блог
    FAQ
    Для компаний
    Roadmap
    1. Домой
    2. Блог
    3. Обучение
    4. Топ-10 ошибок в автотестах на Java которые я вижу каждую неделю
    Все статьи
    Обучение
    27 апреля 2026 г. 14 мин чтения

    Топ-10 ошибок в автотестах на Java которые я вижу каждую неделю

    Tech Lead из Ozon и VK разбирает 10 самых частых ошибок в Java-автотестах: отсутствие архитектуры, кривые локаторы, слабое знание языка, устаревший стек, игнорирование JUnit Extensions и нейросетей. С примерами кода как делать правильно.

    Олег Пендрак
    Tech Lead QA Automation · Ozon, VK

    Топ-10 ошибок в автотестах на Java которые я вижу каждую неделю

    Я провожу code review автотестов каждую неделю — в рамках менторства, на мок-собеседованиях и в командах где работаю. За несколько лет сложился устойчивый список ошибок которые встречаются снова и снова, независимо от компании и уровня специалиста. Некоторые из них делают даже Middle-инженеры с 2–3 годами опыта.

    Это не теория из учебника. Это реальные проблемы из реальных проектов. Разберём каждую с примером как делают и как надо.


    Ошибка #1: Нет архитектуры — нельзя переиспользовать компоненты

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

    Как делают неправильно:

    java
    1// Плохо: логика дублируется в каждом тесте
    2@Test
    3void testCheckout() {
    4    open("https://shop.example.com/login");
    5    $("#email").setValue("user@test.com");
    6    $("#password").setValue("pass123");
    7    $("button[type=submit]").click();
    8    // ... 30 строк логики покупки
    9}
    10
    11@Test
    12void testOrderHistory() {
    13    open("https://shop.example.com/login");
    14    $("#email").setValue("user@test.com");  // дублирование
    15    $("#password").setValue("pass123");     // дублирование
    16    $("button[type=submit]").click();        // дублирование
    17}

    Как надо — Page Object Model + степы:

    java
    1// Хорошо: логика в одном месте, тесты читаемые
    2public class LoginPage {
    3    private final SelenideElement email    = $("#email");
    4    private final SelenideElement password = $("#password");
    5    private final SelenideElement submit   = $("button[type=submit]");
    6
    7    public MainPage loginAs(String email, String password) {
    8        this.email.setValue(email);
    9        this.password.setValue(password);
    10        submit.click();
    11        return new MainPage();
    12    }
    13}
    14
    15@Test
    16void testCheckout() {
    17    new LoginPage().loginAs("user@test.com", "pass123")
    18        .goToCart()
    19        .checkout();
    20}

    Правило простое: если одно и то же действие встречается в двух тестах — оно должно быть в Page Object или степе. Не в тесте.


    Ошибка #2: Кривые локаторы

    Хрупкие локаторы — вторая по частоте причина нестабильных тестов. Тест падает не потому что сломалась функциональность, а потому что разработчик переименовал CSS-класс или изменил структуру DOM.

    java
    1// Плохо: хрупкие локаторы
    2$("div.sc-bdXxxt.fKBQlc > span:nth-child(2)").click();  // XPath по структуре
    3$(".btn-primary-large-rounded-shadow").click();          // CSS по визуальному классу
    4$("//div[3]/button[1]").click();                         // XPath по позиции
    5
    6// Хорошо: стабильные локаторы
    7$("[data-testid='submit-button']").click();   // атрибут для тестов
    8$("[data-qa='login-form']").click();          // явный QA-атрибут
    9$(byText("Оформить заказ")).click();           // по тексту (если текст стабилен)
    10$("#checkout-submit").click();                // по ID

    Иерархия надёжности локаторов (от лучшего к худшему): data-testid / data-qa → ID → aria-label → текст → CSS по семантическому классу → XPath по структуре. Если в проекте нет data-testid — договоритесь с разработчиками добавить их. Это занимает 10 минут и экономит часы отладки.


    Ошибка #3: Слабое знание Java

    QA-инженеры часто учат Java ровно настолько чтобы написать тест. Это работает до первого code review. Потом выясняется что человек не знает generics, не понимает разницу между equals() и ==, не умеет работать со Stream API и пишет циклы там где нужна одна строка.

    java
    1// Плохо: не знает Stream API
    2List<String> activeUsers = new ArrayList<>();
    3for (User user : users) {
    4    if (user.isActive()) {
    5        activeUsers.add(user.getEmail());
    6    }
    7}
    8
    9// Хорошо: Stream API
    10List<String> activeUsers = users.stream()
    11    .filter(User::isActive)
    12    .map(User::getEmail)
    13    .toList();
    14
    15// Плохо: сравнение строк через ==
    16if (status == "ACTIVE") { ... }
    17
    18// Хорошо: null-safe сравнение
    19if (Objects.equals(status, "ACTIVE")) { ... }

    Минимум который должен знать Java QA Automation инженер: ООП (наследование, интерфейсы, абстрактные классы), generics, коллекции (List, Map, Set), Stream API, Optional, лямбды, исключения. Без этого код будет работать, но его будет стыдно показывать на собеседовании.


    Ошибка #4: Устаревший стек

    В 2026 году я всё ещё вижу проекты на JUnit 4, Selenium 3, TestNG без причины. Это не просто эстетическая проблема — старый стек медленнее, менее функционален и создаёт проблемы при найме.

    УстарелоАктуально в 2026Почему менять
    JUnit 4JUnit 5Extensions, параметризация, вложенные тесты
    Selenium 3 + явные ожиданияSelenide 7 / PlaywrightАвтоожидания, читаемость, скорость
    TestNG (без причины)JUnit 5Лучшая экосистема, активная разработка
    RestTemplate в тестахREST Assured 5+Специализированный инструмент для API
    Allure 2.xAllure 3 / Allure TestOpsИнтеграция с CI, история запусков
    Jenkins (legacy)GitLab CI / GitHub ActionsДекларативные пайплайны, проще поддержка

    Переход с JUnit 4 на JUnit 5 занимает день. Переход с Selenium на Selenide — неделю. Это инвестиция которая окупается за месяц.


    Ошибка #5: Повторяющиеся тесты без параметризации

    Классика: три теста которые делают одно и то же с разными данными. Вместо одного параметризованного теста — три копии с разными значениями в коде.

    java
    1// Плохо: три одинаковых теста
    2@Test void loginWithGmail()     { loginPage.loginAs("user@gmail.com",   "pass"); }
    3@Test void loginWithCorporate() { loginPage.loginAs("user@company.ru",  "pass"); }
    4@Test void loginWithSubdomain() { loginPage.loginAs("u@mail.example.com","pass"); }
    5
    6// Хорошо: @ParameterizedTest
    7@ParameterizedTest
    8@ValueSource(strings = {"user@gmail.com", "user@company.ru", "u@mail.example.com"})
    9void loginWithValidEmail(String email) {
    10    loginPage.loginAs(email, "pass");
    11    assertThat(mainPage.isLoaded()).isTrue();
    12}
    13
    14// Для сложных данных — @MethodSource
    15@ParameterizedTest
    16@MethodSource("validCredentials")
    17void loginWithValidCredentials(String email, String password, String expectedRole) {
    18    loginPage.loginAs(email, password);
    19    assertThat(userProfile.getRole()).isEqualTo(expectedRole);
    20}
    21
    22static Stream<Arguments> validCredentials() {
    23    return Stream.of(
    24        Arguments.of("admin@test.com",  "admin123",  "ADMIN"),
    25        Arguments.of("user@test.com",   "user123",   "USER"),
    26        Arguments.of("mentor@test.com", "mentor123", "MENTOR")
    27    );
    28}

    Ошибка #6: Не используют JUnit 5 Extensions

    JUnit 5 Extensions — один из самых мощных инструментов фреймворка. Они позволяют вынести повторяющуюся логику (setup/teardown, логирование, скриншоты, управление браузером) в одно место. Большинство QA-инженеров знают только @BeforeEach и @AfterEach и не подозревают о существовании Extensions.

    java
    1// Хорошо: Extension для автоматических скриншотов при падении
    2public class ScreenshotExtension implements TestWatcher {
    3    @Override
    4    public void testFailed(ExtensionContext context, Throwable cause) {
    5        String name = context.getDisplayName();
    6        Selenide.screenshot("screenshots/" + name);
    7        Allure.addAttachment("Screenshot", new FileInputStream("screenshots/" + name + ".png"));
    8    }
    9}
    10
    11// Хорошо: Extension для управления браузером
    12public class BrowserExtension implements BeforeEachCallback, AfterEachCallback {
    13    @Override
    14    public void beforeEach(ExtensionContext ctx) {
    15        Configuration.browser = "chrome";
    16        Configuration.headless = true;
    17        Configuration.baseUrl = System.getProperty("base.url", "https://app.example.com");
    18    }
    19    @Override
    20    public void afterEach(ExtensionContext ctx) { closeWebDriver(); }
    21}
    22
    23// Использование — чистые тесты без setup/teardown
    24@ExtendWith({BrowserExtension.class, ScreenshotExtension.class})
    25class LoginTests {
    26    @Test
    27    void loginTest() { /* только бизнес-логика */ }
    28}

    Другие полезные Extension: ParameterResolver для инжекции зависимостей в тесты, ExecutionCondition для условного запуска, @RegisterExtension для динамической регистрации.


    Ошибка #7: Thread.sleep() вместо ожиданий

    Thread.sleep() — признак того что инженер не понимает как работает асинхронность в браузере. Тест либо ждёт слишком долго (медленный), либо недостаточно (нестабильный).

    java
    1// Плохо
    2$("#submit").click();
    3Thread.sleep(3000);  // ждём 3 секунды вслепую
    4$("#success").shouldBe(visible);
    5
    6// Хорошо: Selenide ждёт автоматически (до 4 сек по умолчанию)
    7$("#submit").click();
    8$("#success").shouldBe(visible);
    9
    10// Хорошо: кастомное время ожидания если нужно
    11$("#heavy-report").shouldBe(visible, Duration.ofSeconds(30));
    12
    13// Хорошо: для чистого Selenium — WebDriverWait
    14new WebDriverWait(driver, Duration.ofSeconds(10))
    15    .until(ExpectedConditions.visibilityOfElementLocated(By.id("success")));

    Ошибка #8: Игнорирование нейросетей в работе

    В 2026 году QA-инженер который не использует AI-инструменты работает в 2–3 раза медленнее конкурентов. Нейросети не заменяют инженера — они убирают рутину.

    • ▸Генерация тестовых данных: попросите ChatGPT/Claude сгенерировать 50 вариантов невалидных email-адресов для негативных тестов — 10 секунд вместо 10 минут
    • ▸Boilerplate-код: Page Object для новой страницы, POJO-классы для API-ответов, конфигурационные классы — генерируется за секунды
    • ▸Анализ упавших тестов: вставьте стектрейс в Claude и получите объяснение причины и варианты исправления
    • ▸Рефакторинг: попросите улучшить читаемость метода или предложить более идиоматичный Java-код
    • ▸Граничные случаи: опишите функциональность и получите список edge cases которые вы могли пропустить

    Главное правило: AI генерирует черновик, инженер проверяет и дорабатывает. Слепо копировать код из ChatGPT — такая же ошибка как не использовать его вообще.


    Ошибка #9: Тесты зависят друг от друга

    Тест B падает потому что тест A не создал нужные данные. Или тест C проходит только если запускать после теста B. Это делает тест-сьют хрупким: нельзя запустить один тест, нельзя запустить в параллель, нельзя изменить порядок.

    java
    1// Плохо: тест зависит от состояния после предыдущего
    2@Test @Order(1)
    3void createUser() { /* создаёт пользователя в БД */ }
    4
    5@Test @Order(2)
    6void updateUser() { /* упадёт если createUser не запускался */ }
    7
    8// Хорошо: каждый тест самодостаточен
    9@Test
    10void updateUser() {
    11    // создаём данные прямо здесь через API
    12    User user = userApi.create(UserFactory.defaultUser());
    13    userApi.update(user.getId(), UpdateRequest.builder().name("New Name").build());
    14    assertThat(userApi.get(user.getId()).getName()).isEqualTo("New Name");
    15}

    @Order в JUnit 5 существует для специфичных сценариев — не для компенсации зависимостей между тестами. Каждый тест должен сам создавать нужные данные и сам убирать за собой.


    Ошибка #10: Нет разделения на слои (UI / API / DB)

    Зрелый тест-фреймворк использует разные слои для разных задач. Когда всё делается через UI — тесты медленные и хрупкие.

    java
    1// Плохо: всё через UI, включая подготовку данных (5 минут на тест)
    2@Test
    3void testOrderHistory() {
    4    loginPage.loginAs("user", "pass");
    5    catalogPage.open().addToCart("Product A");
    6    cartPage.checkout().fillAddress(address).pay();
    7    orderHistoryPage.open().assertOrderExists("Product A");
    8}
    9
    10// Хорошо: подготовка через API, UI только для проверки отображения (30 секунд)
    11@Test
    12void testOrderHistory() {
    13    String token = authApi.login("user", "pass");
    14    Order order  = orderApi.create(token, OrderRequest.of("Product A"));
    15
    16    open("/orders");
    17    $("[data-testid='order-" + order.getId() + "']").shouldBe(visible);
    18}

    Правило: используй самый быстрый и надёжный способ для каждой задачи. Создание данных — API или DB. Проверка бизнес-логики — API. Проверка отображения — UI. Это пирамида тестирования, и она работает.


    Итого: чеклист перед code review

    • Есть Page Object Model

      логика не дублируется в тестах

    • Локаторы используют data-testid / data-qa / ID

      не XPath по структуре

    • Код использует Stream API, Optional, лямбды

      не for-циклы везде

    • Стек актуальный: JUnit 5, Selenide 7+, REST Assured 5+
    • Повторяющиеся тесты заменены на @ParameterizedTest
    • Общая логика вынесена в JUnit 5 Extensions
    • Нет Thread.sleep()

      только автоожидания Selenide или WebDriverWait

    • AI использовался для генерации boilerplate и тестовых данных
    • Каждый тест самодостаточен

      не зависит от других тестов

    • Подготовка данных через API/DB

      UI только для проверки отображения

    Хочешь писать автотесты без этих ошибок с первого дня?

    На курсе Java QA Automation от ThreadQA все эти практики заложены в основу с первого урока. Page Object Model, JUnit 5 Extensions, REST Assured, Selenide, параметризованные тесты, работа с AI — не как отдельные темы, а как единый подход к написанию качественного кода. 90 уроков, 40 часов, практика на реальном проекте. Первые уроки бесплатно.

    #ошибки в автотестах java#java qa automation ошибки#code review автотесты#page object model java#junit 5 extensions#локаторы selenium#параметризованные тесты junit#архитектура автотестов#java qa automation best practices#автоматизация тестирования java советы

    Хочешь практиковаться, а не только читать?

    Курсы по Java, Python и iOS автоматизации. Первые уроки бесплатно.

    Начать бесплатно

    Читайте также

    Обучение
    9 мин

    Playwright vs Selenium в 2026: что выбрать для автоматизации тестирования

    Честное сравнение Playwright и Selenium в 2026 году: скорость, поддержка браузеров, синтаксис, популярность. Когда использовать Playwright, а когда Selenium.

    Обучение
    18 мин

    REST Assured: полное руководство по тестированию API на Java

    Изучаем REST Assured для автоматизации API тестирования: установка, базовые запросы, валидация JSON, аутентификация, десериализация в классы, спецификации и практические паттерны.

    Обучение
    16 мин

    Selenide для начинающих: полный гайд по автоматизации тестирования в 2026

    Изучаем Selenide с нуля: установка, первые тесты, Page Object Model, Container, кастомные проверки, работа с элементами. Практический туториал для Java QA Automation.

    Все статьи блога

    Содержание

    Топ-10 ошибок в автотестах на Java которые я вижу каждую неделюОшибка #1: Нет архитектуры — нельзя переиспользовать компонентыОшибка #2: Кривые локаторыОшибка #3: Слабое знание JavaОшибка #4: Устаревший стекОшибка #5: Повторяющиеся тесты без параметризацииОшибка #6: Не используют JUnit 5 ExtensionsОшибка #7: Thread.sleep() вместо ожиданийОшибка #8: Игнорирование нейросетей в работеОшибка #9: Тесты зависят друг от другаОшибка #10: Нет разделения на слои (UI / API / DB)Итого: чеклист перед code reviewХочешь писать автотесты без этих ошибок с первого дня?

    Автор

    Олег Пендрак
    Tech Lead QA

    Опыт в Ozon и VK. YouTube-канал 10к+ подписчиков.

    Готов к практике?

    Первые уроки бесплатно

    Начать бесплатно
    THREADQAОбразовательная платформа
    VK

    О платформе

    Образовательная платформа для разработчиков и тестировщиков. Обучаем современным технологиям и помогаем строить успешную карьеру в IT.

    Онлайн 24/7

    Курсы

    • Про ThreadQA
    • iOS Курс
    • Java Курс
    • Python Курс

    Услуги

    • Мок-собеседования
    • QA Буткемп
    • Записи собеседований

    Инструменты

    • Roadmap
    • Тренажер XPath
    • XPath Diner

    Документы

    • Публичная оферта
    • Политика конфиденциальности
    • Условия использования

    Контакты

    • Email
      info@threadqa.ru
    • Telegram
      @penolegrus
    © 2026•ThreadQA LMS•Все права защищены