Updated recently
Last updated:
Quick Answer: The most robust Cypress locator strategy: (1) data-testid attributes (most stable), (2) cy.contains for text-based selection, (3) ARIA roles, (4) CSS selectors as last resort. Avoid XPath and dynamically generated class names.
Locator Ranking (Best to Worst)
| Rank | Strategy | Example | Stability |
|---|---|---|---|
| 1 | data-testid | cy.get(‘[data-testid=”login-btn”]’) | Excellent |
| 2 | cy.contains (text) | cy.contains(‘Login’) | Very Good |
| 3 | ARIA role | cy.get(‘[role=”button”]’) | Good |
| 4 | id attribute | cy.get(‘#login-btn’) | Good |
| 5 | CSS class | cy.get(‘.btn-primary’) | Fragile |
| 6 | XPath | cy.xpath(‘//button’) | Very Fragile |
Best Practice: Use data-testid
<button data-testid="submit-login">Login</button>
cy.get('[data-testid="submit-login"]').click();
Best Practice: Chain Selectors
cy.get('[data-testid="login-form"]').within(() => {
cy.get('[data-testid="email"]').type('[email protected]');
cy.get('[data-testid="password"]').type('password123');
cy.get('[data-testid="submit-login"]').click();
});
Avoid These Anti-Patterns
// BAD: CSS classes change with styling
cy.get('.btn.btn-primary.btn-lg').click();
// BAD: auto-generated IDs
cy.get('#ember42').click();
// BAD: brittle XPath
cy.xpath('//div[3]/div[2]/button[1]').click();
Training Resources
Master Cypress best practices with SkilBrill Cypress Training.
FAQ
Should I always use data-testid?
It is the most stable option but requires developer cooperation. Use cy.contains as the next best option.
