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:
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.
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.
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
.getByPlaceholder("name@example.com")
.fill("playwright@microsoft.com");
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.
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.
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
data-
attributeFor example, we shouldnât jump to using XPaths wherever IDs and class names will suffice. Test automation should always be as intuitive as possible.
There are many tools out there to help you write the right locators:
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!
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.