I read following in cypress's best practices.

Anti-Pattern: Using highly brittle selectors that are subject to change.
Best Practice: Use data-* attributes to provide context to your selectors and isolate them from CSS or JS changes. enter image description here

But I also came across following points:

  1. The reason using the actual text/role is better is because that's what the user sees and how they know to navigate the app. e.g. the user clicks the "Home" button. If you rename "Home" to "Dashboard" then the user will have friction, not knowing where their "Home" button went, and so it's OK for that same friction to appear in the test, because the test is supposed to capture the breaking change from the user's perspective

  2. data-cy sounds like binding UI tests to implementation detail, rather than actual content and behavior. Theoretically, the only time your UI tests should have to change is when content or behavior changes.

  3. The id attribute is made to be unique. So why not use it?

The argument in favor of data-cy is:

data-cy gives developers sense that they shouldn't touch their value unnecessarily. The values may be made to simply duplicate something describing content or behavior. Now, developers may think of changing data-cy values only when content or behavior changes. So, at least DOM restructuring or change in CSS wont break the tests (if they were written using DOM or CSS based element selectors). To tightly bind data-cy to content or behavior, we may opt to programmatically set to something capturing content or behavior, so that they wont be left unchanged if content or behavior changes.

But I dont know how much this argument fair against the earlier ones. What is correct among these?

2 Answers 2


The best practices are a good guide but implementation always "depends"

Generally you want to use ID and data- attributes. It's that simple.

The complications arise from real world implementation where its rarely ideal and compromise has to be made.

That said...

The example that 'button' as a locator needs context. Maybe the page in question is intended to be a one button page. The text might be dynamic and the ID different for different purposes and so the HTML element is the most stable. It depends.

The other consideration is who you 'share' the page with. If you use IDs and classes that are shared with the application and front end developer and designers then sometimes those ID's will change. However if you go with the data- or data-cy you are scoping the usage down to just your automation. It depends on what sort of team and organization you have.

Good news however, there is a great solution to ' i want a stable identifier but I also want the test to reflect what the user sees in terms of the business domain. Welcome to

Page Objects

These provide that interface between implementation and description. By extracting the identifier into a variable such as

home_page: #div#title.span

you have a human readable identifier - "home_page" which can be used in your test scripts. If it is no longer called 'home page' you can update the page object mapping with a better name than home_page so that tests that use it read correctly. If the identifier itself changes, then you can update the page object identifier.

There is also an 'elephant in the room'...
Can you change (or request a change) to the application code?
If you can, then by all means charge ahead with good and best practices. If you can't - and that is common - then you may often need to have quite different strategies becuase you have to use what is before you, no matter how 'bad' the practice you use to select it is. This can mean selecting the element given the structure and format of the HTML as is without change.


Here are 2 quick principles:

(1) Besides the Data Attribute, a highly recommended principle is to always search for Unique IDs.

Example of a Place Order button: cy.get('#placeOrderBtn').click();

If an element does not have unique IDs, you may be able to ask your colleagues/developers on the team to add them. Or even open a pull request if you manage to add IDs by yourself (but make sure you agree on the Git process with the front-end team)

(2) Element Attributes

If an element does not have a unique ID or class, then look for other attributes of the element that might be unique. These can include the element name, or for certain kinds of elements, the text or link text, and any other attributes that an element might have.

Example of a Sign Out link: cy.get('a[href="/logout"]').click();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.