Przejdź do treści

Jak Selenium clicka?

Wstęp

Jedną z podstawowych operacji w testach WEB GUI jest klikanie. Choć na pierwszy rzut oka może wydawać się to prostą czynnością, w praktyce może stwarzać wiele wyzwań i generować różnorodne problemy. W niniejszym artykule skupię się na zagadnieniu klikania w elementy za pomocą Selenium – popularnego narzędzia do automatyzacji testów aplikacji webowych. Przeanalizujemy różne aspekty tego procesu oraz omówimy strategie radzenia sobie z potencjalnymi trudnościami. Na koniec porównamy klikanie w Selenium z klikaniem w Playwright.

Jak działa click w Selenium

Najprostszy przykład klikania w element:

Java
WebElement element = driver.findElement(By.id("elementToClick"));
element.click();

Selenium najpierw wyszukuje element, jeżeli element nie znajduje się w polu widzenia, to strona jest przesuwana, tak aby element był widoczny, następnie Selenium klika w jego środek. Tak w skrócie. Dokładny opis znajdziesz w dokumentacji.

The Element Click command scrolls into view the element if it is not already pointer-interactable, and clicks its in-view center point.

https://w3c.github.io/webdriver/#element-click

Istotne są tutaj dwa fakty:

  • Selenium najpierw wyszukuje element, a później w niego kilka – są to dwie operacje
  • Selenium klika we współrzędne środka

Problemy z klikaniem

Przesunięcie elementu

Może wystąpić sytuacja, w której element ulega przesunięciu pomiędzy jego znalezieniem przez Selenium a próbą kliknięcia. Może to być spowodowane na przykład animacjami, dynamicznym wczytywaniem treści, czy reakcjami na interakcje użytkownika. W takim przypadku, jeśli element przesunie się poza obszar, który Selenium uznał za jego pozycję, kliknięcie zostanie wykonane w miejscu, gdzie element był widoczny w momencie jego znalezienia. Oznacza to, że kliknięcie może nie trafić dokładnie w środek elementu, jak oczekiwano.

Sprawdźmy, jaka jest szansa, że Selenium kliknie ruszający się element. Używając jQuery i java script przygotowałem przykład niewielkiego kwadracika, który porusza się w boki.

W prawym górnym rogu mamy statystyki kliknięć. Jeżeli Selenium trafi w nasz uciekający element, to wzrasta liczba „Clicked”. Jeżeli nie trafi, to rośnie liczba „Missed”.

Możesz sam przetestować na stronie: http://examples.webqa.pl/clickcoordinates/

Zaimplementujmy prosty test w Selenium na klikanie:

Java
public class ClickTest {

    @Test
    public void test()  {
        WebDriverManager.chromedriver().setup();
        WebDriver driver = new ChromeDriver();
        driver.get("http://examples.webqa.pl/clickcoordinates/");
        for (int i = 0; i < 5000; i++) {
            WebElement element = driver.findElement(By.id("divToClick"));
            try {
                element.click();
            } catch (Exception e) {
                System.err.println("Click się nie udał: " + e.getMessage());
            }
        }
    }
}

Jaki wynik?

Clicked: 4500 Missed: 495

5 kliknięć zgubiło się nam gdzieś. Na konsoli możemy zobaczyć:

Click się nie udał: element click intercepted: Element <div id="divToClick" style="top: 208.779px; left: 141.221px;"></div> is not clickable at point (490, 280). Other element would receive the click: <div id="arena">...</div>

495 kliknięć nie zadziałało, tak jak powinno, czyli czas pomiędzy wyszukaniem elementu a kliknięciem, był na tyle długi, że element zdążył się przesunąć.

Oczywiście nasz przykład jest mało realny, bo normalnie nie klikamy w uciekający kwadracik, ale ma on udowodniać to, że Selenium może chybić. A może się to stać:

  • gdy doładuje się asynchronicznie wyżej element, który przesunie nam stronę
  • gdy trwa jakaś animacja, np. bootstrapowe wyjeżdżanie okienka modalnego
  • najechanie na element rozwija jakaś inną listę i przesuwa stronę
  • klikamy w wiersze tabeli, która nie do końca się jeszcze załadowała
  • sortujemy tabele i nie zaczekaliśmy poprawnie na zmianę kolejności elementów

Jak sobie radzić z klikaniem?

Jako że w większości realnych przypadków animacja nie trwa wiecznie, tylko kiedyś się kończy, to powinniśmy ją uwzględnić w naszych testach i poprawnie na nią zaczekać. Selenium nie ma wbudowanych auto-waitów tak jak Playwright, który czeka na:

  • locator resolves to an exactly one element
  • element is Visible
  • element is Stable, as in not animating or completed animation
  • element Receives Events, as in not obscured by other elements
  • element is Enabled
https://playwright.dev/docs/actionability

Musimy więc sami zadbać o odpowiednie poczekanie. A jak czekać? Na co czekać? Możemy wykorzystywać zmieniające się atrybuty css i czekać np. na ten, który zmieni się jako ostatni. A skąd wziąć te zmieniające się atrybuty? Np. z zakładki Animations z narzędzi developerskich.

Playwright vs Selenium

Pokusiłem się o sprawdzenie, czy w Playwright będziemy mieli ten sam problem, ale przecież tam mamy auto-waita, który automatycznie czeka na zakończenie animacji. A że animacja u nas trwa cały czas to.. to jak kliknąć?

Wymuszone wyłączenie auto-waita

Twórcy Playwrighta umożliwiają wyłączenie auto-waita w konkretnych przypadkach, a więc skorzystajmy z tego:

Java
page.click("#divToClick", new Page.ClickOptions().setForce(true));

Wyniki

Clicked: 4890 Missed: 110

Wynik duży lepszy niż w Selenium. Tylko 110 nietrafionych klików vs. 495 w Selenium. W dodatku brak wyjątków.

Tabelka do porównania:

SeleniumPlaywright
Poprawnych kliknięć45004890
Nietrafionych kliknięć495110
Rzuconych wyjątków50

Z czego może wynikać ten wynik? Przypuszczam, że z prędkości działania, a dokładnie różnic w prędkości działania obu frameworków.

Spróbujmy ją porównać.

Java
Instant start = Instant.now();
for (int i = 0; i < 5000; i++) {
  WebElement element = driver.findElement(By.id("divToClick"));
  try {
    element.click();
  } catch (Exception e) {
    System.err.println("Click się nie udał: " + e.getMessage());
  }
}
Instant end = Instant.now();
Duration timeElapsed = Duration.between(start, end);
System.out.println("Time taken: "+ timeElapsed.toSeconds() + " seconds");
Java
Instant start = Instant.now();
for (int i = 0; i < 5000; i++) {
  page.click("#divToClick", new Page.ClickOptions().setForce(true));
}
Instant end = Instant.now();
Duration timeElapsed = Duration.between(start, end);
System.out.println("Time taken: "+ timeElapsed.toSeconds() +" seconds");

Różnica pomiędzy Selenium, a Playwright jest dość duża. 129s vs 19s na korzyść Playwrighta.

SeleniumPlaywright
Czas 5000 kliknięć129 sekund19 sekund

A jaki jest Twój wynik?

Możesz sam spróbować swoich sił i zautomatyzować klikanie w uciekający kwadracik. A sposobem na klikanie i wynikami pochwal się w komentarzu. 🙂

Podsumowanie

Klikanie w elementy za pomocą Selenium może napotykać na różnorodne trudności, z których najczęstszymi są animacje oraz asynchroniczne doładowanie elementów. Brak odpowiedniej synchronizacji może uniemożliwić kliknięcie w oczekiwany element. W takich przypadkach kluczową rolę odgrywają dobre waity, które pozwalają na odpowiednie oczekiwanie na pojawienie się i dostępność elementów w interfejsie aplikacji. Warto jednak zauważyć, że inne frameworki, jak na przykład Playwright, oferują wbudowane mechanizmy automatycznego oczekiwania, które mogą skutecznie rozwiązywać lub ograniczać opisywane problemy, co czyni je atrakcyjnymi alternatywami dla Selenium.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *


The reCAPTCHA verification period has expired. Please reload the page.