Transcripted Summary

All right, we’ve learned about several locator types throughout this course. Let’s now talk about picking the right locator for whatever elements you are trying to find.

Let’s recap the types of locators we’ve covered so far:

  • IDs
  • Input names
  • Class names
  • CSS selectors
  • XPaths

These are all standard kinds of locators that pretty much any browser automation tool supports. There are other kinds of locators, however, depending upon the tool you use.

# Selenium WebDriver locators

For example, Selenium WebDriver supports three other kinds of locators.

Link text locators match “a” elements that equal the given text. They are equivalent to the XPath: //a[.=_’value’_].

Partial link text locators work the same as link text locators, except that they check if the text contains instead of equals the value. They are equivalent to the XPath: //a[contains(., ‘_value_’)].

Tag locators return all elements that use a given tag. For example, return all “p” elements. This locator type is not very useful because pages usually have multiple elements for each tag in different locations. It is essentially superseded by CSS selectors.

Link text locators can be helpful, but I almost never use tag locators.

# Playwright locators

If you are using Playwright for automation, Playwright offers a set of built-in locators that are friendlier for programming:

page.getByRole() can locate by explicit and implicit accessibility attributes.

await expect(page.getByRole('heading', { name: 'Sign up' })).toBeVisible();

await page.getByRole('checkbox', { name: 'Subscribe' }).check();

await page.getByRole('button', { name: /submit/i }).click();

page.getByText() can locate by text content.

await expect(page.getByText('Welcome, John')).toBeVisible();

page.getByLabel() can locate a form control by the associated label's text.

await page.getByLabel('Password').fill('secret');

page.getByPlaceholder() can locate an input by placeholder.

await page

page.getByAltText() can locate an element, usually image, by its text alternative.

await page.getByAltText('playwright logo').click();

page.getByTitle() can locate an element by its title attribute.

await expect(page.getByTitle('Issues count')).toHaveText('25 issues');

page.getByTestId() can locate an element based on its data-testid attribute (other attributes can be configured).

await page.getByTestId('directions').click();

Out of these special locators, I find the most useful ones are test ID and text values. If you’re using Playwright, check out the doc pages to learn more about these locators.

Test IDs are a bit of a clever hack. Essentially, you just add a “data-testid” attribute to the target element in the page, and then you can use the page.getByTestId() locator. You can do this same technique even if you’re not using Playwright. For example, Cypress recommends adding data-cy or data-test-id attributes to elements in the same way. Then, you can just use a CSS selector to get the desired elements.

Text value selectors are very easy to write, and they’re very easy to understand when you see them in the code. For example, you could find a login button that has the text “Login” simply by coding page.getByText("Login") rather than trying to figure out a class name or other such attribute. They represent the element more clearly than arcane CSS or XPath syntax. Just be careful with localization or other changes to text that could break these locators.

# Visual locators

There’s one more kind of locator that might blow your mind. You can even use visual locators to find elements on the page using image matching instead of text-based selectors. Essentially, you can capture a screenshot of the element, and then tests can use image matching to find that element on the page visually rather than finding it through the DOM. If you want to create visual locators, you’ll need a visual testing tool like Applitools.

# Choosing the best locator

Choices, choices, choices!

When we write locators for test automation, we should be keen to use the simplest locator possible to uniquely identify the desired element(s).

Here’s my order of preference

  1. Test ID using a data- attribute
  2. ID (if the ID is unique on the page)
  3. Input name (if the name is unique on the page)
  4. Class name
  5. Text value
  6. CSS selector
  7. XPath without text or indexing
  8. Link text or partial link text
  9. XPath with text and/or indexing

For example, we shouldn’t jump to using XPaths wherever IDs and class names will suffice. Test automation should always be as intuitive as possible.

# Tools for creating locators

There are many tools out there to help you write the right locators:

  • Chrome DevTools can generate CSS selectors and XPaths for any element on the page.
  • Playwright has a test generator that will let you record sessions in a browser and then generate a script with all your interactions.
  • SelectorsHub is a popular tool for generating CSS selectors and XPaths.
  • Many codeless automation tools provide record-and-playback functionality that will figure out locators for you. Many of them include self-healing capabilities as well, so that your tests won’t break as your pages evolve.

Be wary, though. Many times, tools like this don’t return the best locators. They may generate overly-complicated locators or locators that pinpoint an element by position rather than by content. These tools are getting better over time, but treat their output as a starting point for refinement rather than a perfect, finished product. Stick to the rules that we know will work!

# Iframes and Shadow DOMs

There’s one more point of caution that I must share. Watch out for iframes and shadow DOMs. These act like a page within a page, and they can make elements tougher to locate. Pretty much all browser automation tools provide a way to locate elements inside either of these two constructs. Usually, you need to locate the iframe or shadow DOM first, and then you need to locate the element inside of it with a regular locator. Look up how it works for the tools you are using.


© 2023 Applitools. All rights reserved. Terms and Conditions Privacy Policy GDPR