There is a calculator app calculatoria.com. The task was to create test automation suite for the app. All calculator buttons have unique ids which were used to interact with them.

A button element looks like this

<div class="btnmar btn2" id="btn104" onclick="btnDown(this);">
<a href="#c" class="abtn2 zabtn" onclick="enter(8);blur(this)">8</a>

Where id="btnXXX" is always unique value for each element

Locator example

public By digit8Button = By.id("btn104");

When my code is reviewed I got a feedback that I should have used element text (digit) or CSS instead of element id. The argument was that ids can be easily changed but number text is more reliable. This doesn't correspond to many articles I've read while studying test automation about element unique id as the first option to create a good locator.

  • @PeterMasiar my question related to this specific case, while the linked question is asking for pros and cons generally Apr 6, 2018 at 17:49

7 Answers 7


First off you should not choose a method based on the performance, but based on the maintenability. Executing UI tests is cheap compaired to maintening them.

Why choose a CSS selector over by id ?

  • Easier to evaluate in the console via $(...) or with Ctrl + F in the inspector with Chrome.
  • There's not really a difference it terms of performance since it will end-up calling the same engine.
  • Some frameworks even convert By.id("btn104") to By.cssSelector("[id='btn104']") under the hood to ensure uniqueness.

Why choose by text over by id here ?

  • There's no meaningful attribute which can be associated with the button. The id seems to be automatically generated and thus could change without notice. It would have been all right if the id was btn_8.
  • Though be aware that selecting an element by text can become an issue if the application supports multiple languages.
  • 100%, I never follow a practice of selecting locator based on performance, because it doesn't make much sense. Why I chose ID here is because it's more reliable IMO Apr 6, 2018 at 20:05
  • @inmydelorean, what makes a locator reliable is it's ability to be unaffected by changes. The id here is auto-generated or from an unknown source and might change if another button is inserted. On the other hand the text of the buttons is unlikely to change. Thus in this case, locating an element by text (xpath or link text) is going to be more reliable than by id and easier to write and maintain. XPath is not evil, it even used internally by Selenium to select an option.
    – Florent B.
    Apr 6, 2018 at 20:50
  • how do you see the correct XPath locator here? Apr 9, 2018 at 7:29
  • @inmydelorean, //a[normalize-space()='8'] will get you the first link with text 8.
    – Florent B.
    Apr 9, 2018 at 13:04
  • or //*[@onclick][normalize-space()='8'] to get the container representing the button.
    – Florent B.
    Apr 9, 2018 at 13:07

Finding elements by ID is fastest option, because it eventually calls document.getElementById(), which is optimized by most browsers.

One can make the same argument about text being changed, same with CSS selectors, if you are working on a product that is under development; you can not guarantee that things won't change.

CSS selectors/Name are second fastest, then comes XPath. CSS selectors are awesome but not as flexible as XPath.


You are both correct in your own way.

As Moe Ghafari pointed out, finding elements by id is the fastest way to do so.

On the other hand, this is a calculator, it has static values on the buttons. This means that if, for whatever reason, they decide to change the layout of the calculator, your ids would have to be changed or your test would have to be corrected.


From my experience, id's can be wonderful, but application engineers tend to wipe them away when they are no longer useful to them, and are not interested in maintaining them for automation engineers.

Text, however, is a bit more stable and when it changes, there's usually a discussion about it.

If you use some encapsulation, you can set it up so that the text is passed as an argument and your code will be a lot cleaner.

  • It's context dependent, I agree. If that was an app in development I would think about other possible options. But why would someone wipe IDs in an app on production? As for me, this is a very rare case to take it into consideration. Will you consider it yourself if you have a similar task? Apr 5, 2018 at 20:38
  • I would not, but I'm not an application engineer. I've had application engineers wipe them out without ceremony on several occasions, simply because they did not want to maintain them.
    – LeLetter
    Apr 5, 2018 at 20:40

It's all variable

Yes, using IDs are fastest, followed by CSS, then XPath (with using text as an offshoot).

However, IDs are only really great if used correctly. I've seen cases of:

  • developer removes IDs for some reason.
  • developer uses the same ID for multiple of the same thing, where they are only shown one at a time. So all the "Close" buttons for multiple modals all have the same ID. But since there is only ever one modal (and one Close button) shown at a time, they think it's okay to reuse.
  • With the wave of Angular, Vue, React, and other frameworks, the devs don't assign an ID, but the framework assigns them randomly as needed. So it's "Button-104" this time, but refresh and it becomes "Button-017".
  • developers change IDs to match some new sorting method (They inserted a new option to the middle of the navigation so all the navigation ID's were adjusted).

So in reality, IDs can be just as flaky as using CSS or XPath. Any change to the code can invalidate identification methods.

With the calculator, it may be more reasonable to use text as regardless of anything else, an 8 is an 8 is an 8. So even if they completely rewrite the layout and the markup, looking for a button with just the text "8" should almost always work.

NOW, that only works for the buttons themselves. You still would need to use some other method for reading the display. So while text would work for the buttons, it's not not an end-all/be-all answer.

So in the end, use the method that you deem will give the correct pointer with the least chance of needing to be updated next week.

  • 1
    Yes, changes are possible, no doubt. They are possible in both ways, either id or text. What if developers replace buttons with images with no text? Then IDs are going to be the right choice. How often do you expect to see a complete redesign of a released product? Probably, not often, moreover, that's a quite rare case. As you say it's all variable and I agree with you. That's why I was surprised when it was interpreted as a flaw in my test. Apr 5, 2018 at 20:24
  • 1
    these frameworks are going to cause a lot of accesibility issues with this approach
    – Amias
    Apr 6, 2018 at 9:59
  • The first, second, and fourth bullets are all reasons that automated testing is valuable in highlighting not following best practices or the introduction of possible breaking changes. The third is is a tooling issue that indicates that a re-evaluation might be valuable. Apr 6, 2018 at 12:35
  • Generated ID is not "flaky". Flaky means intermittently failing. I often use generated ID, if I can find some logic (like all items in a generated grid row have ID based on the same number, with specific prefix). XPath locator can break after small design change, CSS is more robust because it is used for styles (so changes has other visible consequences). Apr 6, 2018 at 13:27
  • @Peter Masiar, don't you mean efficient instead of robust? In my experience, what makes an expression robust is the way you design it. For instance By.cssSelector("#mybutton") is as much robust as By.xpath("id('mybutton')"), just like By.cssSelector("#container > div:nth-child(1) > div:nth-child(3) > input") would be an poor choice for a CSS selector.
    – Florent B.
    Apr 6, 2018 at 14:22

In your concrete situation, I would:

  • ask developers to add names, or
  • locate by CSS class.

Locate all elements with same name/class (regardless of the generated id) and select desired one by checking other attributes (like text), which will likely remain constant even after future redesign.

This approach is much more robust than XPath, IMHO. Your programming language of choice (which you supposedly mastered) gives you more power and more flexibility than wasting time crafting unique Xpath locators (which will break after simple redesign).

  • Yeah, XPath for this element is definitely not an option, that was not even considered as a possibility with unique IDs available. If I had an opportunity to ask developers to change smth I would go for unique meaningful IDs like btn_8 like Florent B. suggested. But names are good as well Apr 6, 2018 at 19:47

You are right to use IDs , they are specifically chosen to be unique identifiers for this purpose. They can point to things that change without needing to be changed.

Web browsers use these IDs and ensure they are unique , so you get a smoke test for free. At least that is the theory, we've extended this paradigm so far beyond where it started.

For any non-trivial application you will need to stick to IDs to cope with the the rate of change and its a problem that a lot of frameworks don't see the clear value in using determinate ID's instead of ephemeral ones.

Ephemeral ID's just push the problem into somewhere else by requiring some kind of mapping layer between them and the real ones, i can guarantee someone at every org that uses these will spend an inordinate and painful amount of time navigating and debugging these abstractions. As a tester its important you can connect that time to the original decision to use the framework. If you are not careful that can end up happening on every test failure , keep tests and apps as simple possible.

There are other uses for IDs , if you want your app to be accessible to people who might not be able to see, might use different input methods or might want to use your website on unusual devices then these ID's become very important.

The worst argument for not using persistent ID's is security , you are only adding obscurity and hackers will know how to reverse your framework's obfuscation. Your backend should be secure enough that knowing these IDs will not compromise it.

Having a standard name for a thing across the whole of a project is an important ingredient for software quality , it reflects a common understanding which even if wrong is of more use than multiple competing definitions because you can fix it in a predictable amount of time.

  • Thanks for your thoughts. What would you use in the described case, IDs or button text? Apr 6, 2018 at 13:20
  • I would still use ID's , they are faster and test the application in a far more meaningful and extensible way than checking for specific button text. I would have the button text stored in data file that the test would load and look up for validation.
    – Amias
    Apr 6, 2018 at 13:47
  • 1
    I question your answer. Browsers do absolutely no validation on the ID uniqueness so I don't see how you "get a smoke test for free". IDs also have no baring on ADA or WCAG, so how do you reason IDs make websites "accessible to people who might not be able to see". They can assist, but generally you rely on the aria-* attributes to create accessible wesbites. And I have never heard of a website being more hackable, or more likely to be scraped, due to IDs. So how does static versus ephemeral IDs change a websites security?
    – MivaScott
    Apr 6, 2018 at 15:51
  • @MivaScott the browser doesn't throw errors but it can enable various quirks modes if the parser shows errors and you requested strict. the javascript engine should also be usable in this way as well , i was flippant to say it was free because these are not default options
    – Amias
    Apr 6, 2018 at 16:19
  • @Amias thanks, then we think in the same way :) do you have a link to a code example of that? I would really appreciate it Apr 6, 2018 at 17:53

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