Strona główna > Jak najlepiej lokalizować elementy?

Jak najlepiej lokalizować elementy?

W Selenium, gdy programujemy w Javie, elementy lokalizujemy za pomocą metod findElement() i findElements(). Dodatkowo, musimy powiedzieć Selenium jak chcemy jakiś element znaleźć. Do tego służą strategie lokalizujące. Zatem jak najlepiej lokalizować elementy? Przyjrzyjmy się temu.

Po pierwsze: unikatowy lokator

Jeżeli szukamy tylko jednego elementu, to najlepiej zbudować taki lokator (niezależnie od strategii lokalizującej), który odpowiada tylko jednemu, konkretnemu elementowi, którego szukamy. W ten sposób unikniemy różnych wesołości, które mogą się pojawić, gdy zignorujemy tę zasadę. Na przykład metoda findElement() zawsze zwróci tylko jeden element – pierwszy, jaki znajdzie w DOM (czyli w Document Object Model). Być może teraz element, którego potrzebujemy w swoich testach, rzeczywiście jest pierwszy. Jednak możliwe, że za tydzień już nie będzie, bo w procesie powstawania aplikacji dojdzie nowy element i będzie ustawiony “wyżej” w DOM. Albo zmieni się kolejność elementów. Nasz lokator powinien być precyzyjny jak laser. Dzięki temu testy będą stabilniejsze.

Strategie lokalizujące

Selenium dostarcza kilka różnych strategii lokalizujących. Znajdują się one w klasie By i są to po prostu metody statyczne:

  • By.id
  • By.className
  • By.name
  • By.tagName
  • By.linkText
  • By.partialLinkText
  • By.cssSelector
  • By.xpath

Dwie ostatnie strategie są bardziej zaawansowane, o nich za chwilę. Natomiast pierwszych sześć jest super prostych w użyciu. By.id oznacza, że będziemy szukać elementu o podanym przez nas id, np.:

Z kolei By.className odnosi się do atrybutu “class”. Co ważne, większość elementów ma więcej niż jedną klasę:

Konsola Chrome - element z kilkoma klasami

Są one oddzielone spacją. By.className potrafi szukać elementu na podstawie tylko jednej klasy, to znaczy, że nie możemy do tej metody przekazać dwóch klas albo całego kompletu klas jaki dany element zawiera. Możemy podać tylko jedną klasę i wtedy Selenium będzie szukało elementu (lub elementów), które mają tę klasę. Elementy te mogą mieć też inne klasy i również zostaną wskazane przez Selenium.

By.name odnosi się to atrybutu “name” elementu. By.tagName z kolei, odnosi się do nazwy taga, co czyni tę strategię w zasadzie bezużyteczną. Rzadko kiedy mamy sytuację, w której element o danym tagu występuje tylko raz w całym dokumencie.

By.linkText oraz By.partialLinkText zadziałają dla linków, czyli elementów o tagu <a>. Po prostu wyszukujemy w ten sposób po tekście linku albo częściowym tekście linku. Tekst linku to jest to, co użytkownik aplikacji widzi na stronie z reguły podkreślone i na niebiesko albo oznaczone w jakiś inny sposób.

Screenshot z wyświetlonym linkiem strony docelowej

Selektory CSS oraz XPath

To już nie są zabawki. O ile wcześniejsze metody były bardzo proste w użyciu, to zarówno selektory CSS jak i XPath mają swoją składnię, której musimy się nauczyć. Plusem jest to, że pozwolą nam one na wyciągnięcie naprawdę trudnych do zlokalizowania elementów, których nie damy rady namierzyć wcześniej opisanymi metodami. Zarówno selektory CSS jak i XPath są w stanie wyszukiwać po dowolnym atrybucie elementu (a nie tylko tych wspomnianych w poprzednim punkcie), połączyć to z nazwą taga, a nawet wziąć pod uwagę hierarchię. Możemy na przykład wyszukać element o tagu div, który zawiera klasę “primary-button” oraz atrybut name o wartości “Join now”, który jednocześnie znajduje się w innym divie o id “main-content”.

No to jak szukać tych elementów?

Po pierwsze, jeżeli używamy selektorów CSS albo XPatha, czyli czegoś, czego rzeczywiście trzeba się nauczyć, skupmy się na jednym albo na drugim. Starajmy się nie mieszać selektorów CSS z XPathem, bo nawet jeżeli my ogarniamy jedno i drugie bez problemu, to nasi koledzy i osoby które przyjdą do projektu po nas, wolałyby raczej nauczyć się dobrze jednej opcji.

A po drugie, to niezależnie od strategii lokalizującej, najlepsze zawsze będzie wykorzystanie id albo innego, niestandardowego atrybutu dodanego na potrzeby testów. W przypadku id chodzi o to, że z założenia jest (a przynajmniej powinno być) unikatowe. Pozwoli nam to na zbudowanie super eleganckiego i prostego, unikatowego lokatora, czyli takiego, który zaznaczy tylko jeden element. Jeżeli nie zawsze mamy dostępne id, warto przedyskutować w zespole dodanie do kluczowych elementów używanych w testach niestandardowego atrybutu (a na produkcji się tego atrybutu pozbywać. Lub nie 😜). Taki atrybut może się nazywać data-testid i pełnić rolę jaką pełniłoby w testach id, gdyby istniało dla danego elementu.

W dalszej kolejności posłużyłabym się atrybutem name (także w połączeniu z tagiem), bo z mojego doświadczenia również często pozwala zbudować unikatowy lokator. Dla wsparcia używam też nazw klas, ale raczej takich, które brzmią jakby rzeczywiście coś mówiły o moim elemencie. Czyli jeżeli mam przycisk na stronie i ten przycisk ma dwie klasy “accent” (związane z kolorem przycisku) oraz “buy-button”, to użyję tej drugiej klasy. Ta pierwsza prawdopodobnie znajdzie się w wielu innych elementach.

Komunikacja kluczem do sukcesu

Automatyzując testy regularnie mamy do czynienia z lokatorami. Ważne, żeby wiedzieć jak skutecznie i umiejętnie z nich korzystać, by nasze testy były jednocześnie stabilne, przejrzyste i spójne. Kluczem do sukcesu będzie komunikacja, nie tylko w zespole testerskim, ale również z zespołem deweloperskim. Jako testerzy, powinniśmy wybrać konkretną strategię i konsekwentnie się jej trzymać, a deweloperzy mogą znacząco ułatwić nam pracę dodając wspomniane wyżej niestandardowe atrybuty. Prócz tego, że lokator powinien być unikalny, należy pamiętać, że równocześnie powinien być prosty i w miarę możliwości opisowy – żeby było jasne, jakiego elementu dotyczy.

Na co dzień najczęściej będziemy korzystać z selektorów CSS oraz z XPatha, które zostały już fajnie opisane w podlinkowanych artykułach. O możliwościach tych dwóch metod możecie dodatkowo przeczytać tutaj. Gdyby jednak coś było niejasne, budziło Wasze wątpliwości i spędzało sen z powiek, napiszcie do mnie, a wspólnie znajdziemy rozwiązanie. 😉