🟢
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.