iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Stable Playwright tests in Python start with locators that express what a user can identify, then narrow repeated components to the intended item. For changing page state, use Playwright’s retrying assertions rather than one-time reads or fixed sleeps. Together, those choices make tests clearer and less dependent on incidental markup or timing.
How to choose a stable Playwright locator
Prefer a locator that describes the element’s user-facing role, label, or meaningful text. Playwright’s locator guidance treats locators as central to auto-waiting and retryability, and recommends user-facing attributes or deliberately maintained test contracts. A role locator is often a good first choice when its role and accessible name match how a person or assistive technology identifies the control.
| Situation | Locator direction | Why it fits |
|---|---|---|
| Interactive control with a clear role and accessible name | get_by_role(role, name=...) |
Expresses a user-facing contract. |
| Form control with a visible label | get_by_label(...) |
Targets the label users see. |
| Meaningful text identifies the target | get_by_text(...) |
Useful when the text is sufficiently specific. |
| Application-owned testing contract | get_by_test_id(...) |
Suitable when the test ID is intentionally kept stable. |
| Repeated component or card | Locate and filter the container, then locate its child | Scopes the action to the intended component. |
| Only an implementation-specific path is available | CSS or XPath, used carefully | Can work, but may couple a test to markup structure. |
Role locators can reflect ARIA roles and accessible names, but choosing one does not replace accessibility audits or conformance testing. A test ID can be a sound choice when it represents an explicit application contract; it is not automatically better than an accessible name. Playwright’s locator and best-practices guidance explains these trade-offs: Python locators and Playwright best practices.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Scope repeated elements before acting
A page may contain many buttons with the same name. Instead of choosing the first match, identify the relevant component by a distinguishing property and then find the control inside it. This makes the test’s intent visible and helps satisfy Playwright’s strictness requirement for actions that need one target.
#1 Best Overall
product = page.get_by_role("listitem").filter(has_text="Product 2")
await product.get_by_role("button", name="Add to cart").click()
Here the action is scoped to the list item containing “Product 2.” Adapt the role, text, and button name to the application’s actual accessible names and semantics. Chaining locators is also useful for dialogs, navigation regions, tables, and repeated rows.
Use retrying assertions for changing page state
An action and an assertion do different jobs. An action such as click() waits for the conditions needed to perform that action. An assertion such as expect(locator).to_be_visible() retries until the condition is true or its timeout is reached. Use assertions when the test needs to verify that a page state eventually appears, rather than checking a value only once.
Rank #2
For example, a synchronous test can assert a visible submit button, click it, and wait for a status message:
Recommended Free Tools
from playwright.sync_api import expect
submit = page.get_by_role("button", name="Submit")
expect(submit).to_be_visible()
submit.click()
expect(page.get_by_role("status")).to_have_text("Saved")
The equivalent asynchronous pattern uses the async API and await:
from playwright.async_api import expect
submit = page.get_by_role("button", name="Submit")
await expect(submit).to_be_visible()
await submit.click()
await expect(page.get_by_role("status")).to_have_text("Saved")
These examples assume the application exposes a button with the stated accessible name and a status region whose text becomes “Saved.” Assertions and actionability checks are described in the Python actionability guide; the library introduction also explains why manual waiting is usually unnecessary: Playwright Python library introduction.
Why a click can time out
For a click, Playwright checks that the locator resolves to one element and that the element is visible, stable, able to receive events, and enabled. If those conditions do not pass before the timeout, the click fails rather than silently acting on a different or unusable target.
Rank #4
- More than one match: Add an accessible name, scope to a component, or filter by a distinguishing property. Use
firstornth()only if position itself is part of the requirement. - Hidden or disabled target: Check whether the page is in the expected state and whether the intended control is actually available.
- Moving or covered target: Inspect what is changing or intercepting events instead of treating
force=Trueas a routine stability fix. - Timeout while loading: Verify a meaningful state condition with an assertion rather than adding an arbitrary sleep.
A locator is resolved when it is used, so a reused locator can target the current matching element after a page re-render. This helps with changing pages, but it does not make an ambiguous locator unique. The actionability documentation lists the checks Playwright performs for actions.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Handle dynamic lists without one-time reads
locator.all() returns the elements matched at that moment; it does not wait for a changing list to finish updating. If the list is still loading or being modified, enumerating it immediately can produce an incomplete or inconsistent result. First assert a condition that establishes the intended state, such as an expected count, and then inspect the items.
items = page.get_by_role("listitem")
expect(items).to_have_count(3)
current_items = items.all()
The count in this example is illustrative: use the count your application should display. When the intent is to wait for text or a count, Playwright’s API reference recommends retrying assertions such as to_have_text() and to_have_count() rather than relying on a one-time read. See the Python Locator API reference.
When positional selectors are appropriate
first, last, and nth() select by position. If items are inserted, sorted, or re-rendered, that position may point to a different element. Use a positional locator only when order is deliberately meaningful—for example, when the requirement specifically concerns the first entry in a ranked list. If the test means a particular product, user, or row, identify it by a stable property instead.
Diagnose selector failures at their source
- Strictness error: The action locator matched multiple elements. Narrow the scope or make the identifying role, name, text, or test ID more specific.
- Timeout on action: A required actionability condition did not pass in time. Check the target’s uniqueness, visibility, movement, event interception, enabled state, and surrounding page state.
- Flaky list check: The test read the list before it reached the intended state. Add a retrying state or count assertion before enumerating current matches.
- Selector breaks after a markup change: A CSS or XPath selector may encode structure that was never part of the behavior under test. Prefer a user-facing locator or an intentional test contract when available.
- Accessibility confidence is overstated: A role locator can target an accessible role and name, but does not by itself establish that the page is accessible.
XPath is especially likely to tie a test to implementation details when it follows a structural path through the document. Playwright’s guidance on other locators discusses XPath and alternatives.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

