Strona główna > Selektory w Selenium – możliwości XPatha i CSSa na przykładach (C#)

Selektory w Selenium – możliwości XPatha i CSSa na przykładach (C#)

Podstawowe selektory w Selenium opisałam już tutaj. Omówiłam wtedy sześć prostszych, ale też bardziej ograniczonych metod na tworzenie obiektu elementu html, a były to:

  • By.ClassName(“selector”)
  • By.Id(“selector”)
  • By.Name(“selector”)
  • By.LinkText(“selector”)
  • By.PartialLinkText(“selector”)
  • By.TagName(“selector”)

Jeżeli nie znasz tych metod, rzuć okiem do postu z pierwszą częścią. Pomoże Ci to zrozumieć dlaczego nie do wszystkiego się nadają, a mi łatwiej będzie pokazać, dlaczego zamiast nich używam czegoś innego.

W tej części poruszę dwie metody, z których korzystam najczęściej, a będą to:

  • By.CssSelector(“selector”)
  • By.XpathSelector(“selector”)

W pierwszej części wspominałam, że opisane wcześniej selektory mają ograniczone możliwości i mogą nam nie wystarczyć nam w realnych projektach. Natomiast wychodzę z założenia, że wszystko jest dla ludzi a narzędzi trzeba używać z głową. Jeżeli więc w Twoim przypadku podstawowe selektory są wystarczające, to armata na muchę nam nie potrzebna. W tym wpisie podam kilka przykładów, w których armata jednak potrzebna będzie.

Szukanie przez kombinację klas

Weźmy na przykład poniższy dokument.

<div class="miecz stalowy">...</div>
<div class="miecz srebrny">...</div>
<div class="srebrny bazyliszek">...</div>

Chcemy zaznaczyć element o dwóch klasach: miecz oraz srebrny. Żadna z klas nie czyni elementu unikatowym, dopiero ich kombinacja sprawia, że możliwa jest lokalizacja obiektu. Z tym przykładem sobie poradzimy używając poprzednich metod, ale kod będzie dłuższy i mniej elegancki. Musimy to zrobić na dwa razy: najpierw znaleźć wszystkie elementy z klasą miecz, a potem wśród nich znaleźć element z klasą srebrny. Albo na odwrót. Będzie to wyglądało tak:

_driver.FindElements(By.Class("miecz")).FindElement(By.Class("srebrny"));

A tak by to mogło wyglądać przy użyciu selektorów CSS i XPath:

//CssSelector
_driver.FindElement(By.CssSelector("[class='miecz srebrny']"));
//XPath
_driver.FindElement(By.CssXPath("//div[@class='miecz srebrny']"));

Jest trochę czytelniej: widzimy od razu, że szukamy tylko jednego elementu oraz że ma on dwie klasy.

Szukanie przez specyficzne atrybuty

W poniższym przykładzie musimy się posłużyć atrybutem “title”.

<div title="miecz stalowy">...</div>
<div title="miecz srebrny">...</div>
<div title="srebrny bazyliszek">...</div>

Żadna z metod przedstawionych w części pierwszej, nie potrafi zlokalizować obiektu po takim atrybucie. Selektory CSS i XPath ogarną to na przykład tak:

//CssSelector
_driver.FindElement(By.CssSelector("[title='miecz srebrny']"));
//XPath
_driver.FindElement(By.CssXPath("//div[@title='miecz srebrny']"));

Szukanie poprzez rodzica

No i to jest dopiero zabawa. Spójrz na poniższy przykład:

<tbody>
	<tr title="ene">
		<td>Ene</td>
	</tr>
	<tr title="due">
		<td>Due</td>
	</tr>
	<tr title="rike">
		<td>Rike</td>
	</tr>
</tbody>

Rozważmy taki scenariusz: załóżmy, że piszesz test i chcesz zaznaczyć komórkę w drugim wierszu (znacznik <tr> oznacza wiersz tabeli, a <td> komórkę) ale nie możesz tego zrobić za pomocą tekstu, bo ten się generuje dynamicznie i nie będzie cały czas taki sam. W takiej sytuacji możemy się odwołać do rodzica i za jego pomocą zlokalizować wskazany obiekt.

//CssSelector
_driver.FindElement(By.CssSelector("[title='due']>td"));
//XPath
_driver.FindElement(By.CssXPath("//tr[@title='due']/td"));

Gdyby nie atrybut “title”, który nie jest obsługiwany przez selektory inne niż CSS i XPath, takie wyszukanie byłoby możliwe za pomocą omawianych wcześniej metod. Gdyby na przykład wiersze miały unikalne klasy albo id, moglibyśmy ponownie zastosować konstrukcję, w której najpierw szukamy wszystkich wierszy o danej wartości klas lub id, a potem w tym podzbiorze szukamy komórki.

Szukanie po tekście

Zostańmy przy tym przykładzie co w poprzednim punkcie, ale teraz rozważmy następujący scenariusz: dane w komórkach nie są generowane dynamicznie, więc możemy użyć tekstu pomiędzy znacznikami. Skorzystanie z tekstu jest możliwe już tylko w XPath.

//XPath
_driver.FindElement(By.CssXPath("//td[text()='Due']"));

Inne przewagi selektorów CSS i XPath

Oprócz wymienionych przykładów użycia, w których musimy się posłużyć atrybutem niedostępnym dla metod opisanych w pierwszej części cyklu o selektorach w Selenium, warto także wspomnieć o kilku innych przewagach CSS i XPatha.

  • Elementy mogą być lokalizowane w odniesieniu nie tylko do swoich rodziców ale także dowolnego przodka oraz dzieci i rodzeństwa (występują pewne różnice między XPathem a selektorami CSS).
  • Elementy mogą być lokalizowane na podstawie nie tylko wartości atrybutu, ale także jego fragmentu. Oznacza to, że można znaleźć element, który w atrybucie zawiera jakiś ciąg znaków albo rozpoczyna się od jakiegoś ciągu znaków.
  • Można łączyć lokalizatory, tzn. że można za jednym zamachem wyszukać kilka różnych elementów o różnych wartościach atrybutów robiąc z tego jeden selektor.

Mam nadzieję, że pomogłam Ci zrozumieć najważniejsze przewagi tych dwóch selektorów nad pozostałymi. Jeżeli nie – napisz, czego jeszcze według Ciebie tutaj brakuje. Jeżeli chcesz zacząć używać selektorów CSS i XPatha albo po prostu jesteś strasznym testerskim nerdem, zapraszam do kolejnych wpisów traktujących o każdym z tych selektorów z osobna (selektory CSS tu a XPath tu). Dowiesz się z nich w jaki sposób budować podstawowe ale też całkiem pokręcone selektory, żeby znaleźć to, czego będziesz potrzebować do testów. Oba tematy są obszerne więc teraz jest odpowiedni moment żeby przygotować sobie żarcie albo zrobić kawę 🙂

Możliwość komentowania została wyłączona.