QA Interview Hub · База знань · Тести

Selenium + Java

Стабільність і дебаг

Флейкові тести: причини, діагностика, артефакти й Allure

Флейковий тест — той, що на тому самому коді то проходить, то падає. Він руйнує довіру до набору, тому його лікують, а не «перезапускають, доки зелений».

Типові причини в Selenium-тестах:

  • неправильні очікування: Thread.sleep, клік до того, як елемент клікабельний, перевірка до завершення асинхронного запиту;
  • залежності між тестами: спільні дані, порядок виконання, чужий стан у БД;
  • нестабільні локатори: індекси, згенеровані класи, текст, який змінюють;
  • середовище: повільний CI, мала пам’ять браузера в контейнері, зовнішні сервіси, час і часові пояси;
  • анімації, перекриття, віддалені ресурси без заглушок.

Діагностика: відтворити в циклі (запустити тест 20–50 разів), порівняти упалі й успішні запуски, подивитись скриншот, DOM, логи браузера й сервера та час кроків. Лише після причини вирішують: поправити очікування, ізолювати дані, стабілізувати середовище чи карантинувати тест із тікетом.

Артефакти при падінні: скриншот (((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES)), URL, джерело сторінки, логи, а в Grid ще відео. Їх знімають автоматично: у JUnit 5 — розширення з TestWatcher (testFailed), у TestNG — ITestListener.onTestFailure. Скриншот у @AfterEach «якщо впав» без розширення виходить громіздким і про нього забувають.

Allure збирає це у звіт: підключають allure-jupiter (колишній allure-junit5) чи allure-testng, кроки позначають @Step, вкладення додають Allure.addAttachment(...), результати лежать у allure-results, а HTML будує allure generate. Історія запусків показує, які тести нестабільні.

Автоматичний retry (повтор упалих) допустимий як тимчасова міра й обов’язково з позначкою flaky у звіті. Якщо він мовчки робить усе зеленим, справжні дефекти ховаються.

BiDi замість CDP, Actions, файли, iframe і вікна

CDP проти BiDi. Selenium 4 дає доступ до Chrome DevTools Protocol (((HasDevTools) driver).getDevTools()): перехоплення мережі, емуляція, події консолі. Проте CDP працює лише в Chromium, прив’язаний до версії браузера, а Selenium постачає прив’язки під конкретні версії, тож після оновлення Chrome код може не знайти відповідної реалізації. Документація Selenium називає підтримку CDP тимчасовою, доки не реалізовано WebDriver BiDi: це W3C-стандарт двостороннього зв’язку через WebSocket, кросбраузерний (Chrome, Firefox, Edge).

ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true);
WebDriver driver = new ChromeDriver(options);
try (LogInspector logs = new LogInspector(driver)) {
    logs.onConsoleEntry(entry -> System.out.println(entry.getText()));
    driver.get("https://example.com");
}

Для нового коду BiDi обирають за замовчуванням (події консолі й JS-помилки, мережа, скрипти); CDP — лише коли потрібна можливість, якої в BiDi ще немає. Старий driver.manage().logs() працює лише в Chromium.

Actions API складає складні жести: наведення, перетягування, подвійний/контекстний клік, комбінації клавіш, прокрутка.

new Actions(driver).moveToElement(menu).pause(Duration.ofMillis(200)).click(sub).perform();
new Actions(driver).scrollToElement(footer).perform();
new Actions(driver).dragAndDrop(card, column).perform();

Без perform() нічого не станеться.

Файли. Завантаження: sendKeys з абсолютним шляхом у input type="file" (без кліку по кнопці, діалог ОС Selenium не бачить); на Grid додають setFileDetector(new LocalFileDetector()). Скачування: тека й заборона діалогу задаються в опціях браузера, а далі очікують появи файла.

iframe. Елемент усередині frame невидимий для пошуку, доки не перемкнутись: driver.switchTo().frame(...), назад — parentFrame() або defaultContent(); ExpectedConditions.frameToBeAvailableAndSwitchToIt поєднує очікування й перемикання.

Вікна й вкладки. Запам’ятати поточний handle, дочекатись нового (numberOfWindowsToBe), перемкнутись на інший; driver.switchTo().newWindow(WindowType.TAB) відкриває вкладку. Після close() треба явно повернутись до потрібного вікна, інакше будуть NoSuchWindowException.