Review AI generated Playwright selectors before you trust them in a real test suite. AI coding assistants can draft useful Playwright tests quickly, but selectors are one of the easiest places for a generated test to look correct while becoming flaky, too broad, or disconnected from the way a user actually interacts with the page.
This tutorial gives QA engineers and SDETs a step-by-step review process. The goal is not to reject every AI suggestion. The goal is to turn a generated selector into a stable locator strategy, pair it with a meaningful assertion, and validate the test by running it against realistic UI states.
Why Selector Review Matters
Playwright encourages locators that reflect how users and assistive technology perceive the page. That includes roles, labels, visible text, placeholders, alt text, titles, and explicit test ids when a user-facing signal is not stable enough. AI-generated tests often mix good ideas with risky shortcuts: copied CSS chains, first-match locators, vague text selectors, or assertions that only prove an element exists.
A selector review should answer four questions:
- Does the locator target the same thing a user would identify?
- Will it survive normal layout, styling, and copy changes?
- Does the assertion prove the behavior the test claims to verify?
- Could the test pass while the feature is still broken?
Step 1: Read the Test Intent First
Before editing a selector, write down the behavior being tested. For example: “A signed-in user can add one item to the cart and see the cart count increase.” That intent tells you whether the locator should target a product card, an Add to cart button, a cart badge, or a success message.
If the generated test has no clear intent, ask the AI assistant to summarize it before you accept the code. Keep the summary short and concrete. A test with unclear intent usually produces unclear selectors.
Step 2: Classify Each Locator
Go through the generated test line by line and classify each locator. This makes weak selectors easier to spot.
- Preferred: role, label, placeholder, alt text, or visible text that represents real user intent.
- Acceptable contract: test id for controls or states that do not have a stable user-facing name.
- Needs review: CSS classes, long XPath, nth-child, or broad text that could match multiple elements.
- High risk: first matching element, hidden implementation detail, or selector tied to styling.
Step 3: Replace Brittle Selectors with User-Facing Locators
When a generated test uses a CSS path or layout-dependent selector, prefer a user-facing locator when the page supports it. Playwright’s locator model is designed around finding elements by role, label, text, and other signals that match user behavior.
Starter Snippet
// Risky: tied to layout and CSS naming
await page.locator('.product-card:nth-child(2) .btn-primary').click();
// Better: scoped to a visible product and a user-facing button name
const product = page.getByRole('article').filter({ hasText: 'Wireless Mouse' });
await product.getByRole('button', { name: 'Add to cart' }).click();
// Better assertion: verify the user-visible outcome
await expect(page.getByRole('status')).toContainText('Added to cart');
await expect(page.getByLabel('Cart items')).toHaveText('1');
The improved version explains the user journey: find the product, click the button, and verify the visible result. It also reduces the chance that a style-only change breaks the test.
Step 4: Check Scope and Uniqueness
A good locator should be specific enough to express the behavior, but not so specific that it mirrors the DOM tree. When there are repeated cards, rows, dialogs, or menus, scope the locator to the parent region first. Then find the target element inside that region.
For example, do not click the first “Edit” button on the page unless the test truly does not care which record is edited. Find the row for the user, order, product, or issue first, then click the Edit button inside that row. This prevents false positives when new rows or cards appear above the target.
Step 5: Review Waits and Actionability
Playwright automatically waits for many actionability conditions before it clicks, fills, checks, or asserts. That does not mean every generated test is safe. Review whether the test waits for the right user-visible state. A test that waits for a spinner to disappear may still be weaker than a test that waits for the result table, success message, or enabled action button.
Avoid arbitrary sleep-style waits. They slow the suite and hide timing problems. Prefer web-first assertions such as checking visibility, enabled state, URL, count, or text when those checks match the behavior under test.
Step 6: Pair Selectors with Strong Assertions
Selector review is incomplete if the assertion is weak. AI-generated tests often stop after a click or check that a generic element is visible. That proves very little. Ask what regression the test should catch.
- For navigation, assert the destination page, route, or heading.
- For form submission, assert validation messages, saved values, or success state.
- For filtering, assert both included and excluded results.
- For permissions, assert allowed and blocked actions.
- For cart or checkout flows, assert item name, quantity, price behavior, and user-visible status.
Try This AI Review Prompt
Use this prompt after an assistant generates or edits a Playwright test. It forces the review into QA-friendly categories.
You are reviewing a Playwright test for selector stability.
Test intent:
[paste the behavior being tested]
Generated test:
[paste the test]
Return a table with:
1. Selector line
2. Current risk: low, medium, or high
3. Why it may be brittle or too broad
4. Better Playwright locator, if needed
5. Assertion that should prove the behavior
Rules:
- Prefer user-facing locators when possible.
- Use test ids only when user-facing signals are unstable or unavailable.
- Do not add arbitrary waits.
- Do not invent page labels that are not shown in the provided test or HTML.
Step 7: Validate Against Real UI States
Run the reviewed test against more than one realistic state. A selector that works on a clean seed dataset may fail when there are multiple matching rows, localized labels, disabled buttons, empty states, or permission differences.
At minimum, validate the happy path and one confusing state. For a product card, that might mean a page with several products and one out-of-stock item. For an admin table, it might mean several rows with similar names. For a modal, it might mean opening and closing the modal twice to catch stale assumptions.
Screenshot Checklist
Capture these screens while following the workflow:
- The AI-generated Playwright test before selector review.
- The target page with the element highlighted or visually identified.
- The revised locator and assertion in the editor.
- The Playwright test run passing locally.
- A second run against a confusing state, such as repeated rows or similar buttons.
Common Mistakes
Accepting CSS because it passes once. A CSS selector can be valid and still be a poor contract. If the class exists only for styling, it is likely to change.
Using visible text without scope. Text locators can be good, but broad text on a busy page can match the wrong element. Scope to a row, card, region, or dialog when needed.
Replacing every selector with a test id. Test ids are useful contracts, but overusing them can disconnect the test from accessibility and user-facing behavior. Use them deliberately.
Reviewing selectors without reviewing assertions. A stable selector with a weak assertion still gives weak coverage.
References
- Playwright docs: Locators
- Playwright docs: Best practices
- Playwright docs: Auto-waiting and actionability
- Playwright docs: Assertions
- OpenAI docs: Prompt engineering
- GitHub Docs: Copilot best practices
FAQ
Should QA teams always replace CSS selectors in Playwright tests?
No. CSS can be acceptable for a stable technical contract, but user-facing locators and explicit test ids are usually better for long-term maintainability.
Are test ids bad in Playwright?
No. Test ids are useful when role, label, or text locators are not stable enough. Treat them as a deliberate contract between developers and test automation.
Can AI safely generate Playwright selectors?
AI can draft useful selectors, but QA engineers should review scope, uniqueness, assertions, and false-positive risk before committing generated tests.
What is the biggest warning sign in an AI-generated selector?
Long DOM paths, nth-child selectors, unscoped first matches, and style-only classes are strong signals that the test may become flaky or misleading.
Conclusion
When you review AI generated Playwright selectors, focus on intent, user-facing signals, scope, actionability, and assertions. A generated test is only useful after a QA engineer confirms that it targets the right behavior and would fail for the right reason.
