Java – Selenium Testing w/ dynamically generated element id’s: XPATH or CSS selectors

cssjavajsfseleniumxhtml

Background: I'm an intern tasked with learning Selenium; my organization plans on having QA/Testing use it to simplify testing. We use JSF and WebSphere Application Server.

One of the persistent issues I (and other users) have had with using Selenium is identifying input elements that have dynamically generated ID attributes. Simply put, I don't know how the ID's are generated or when they change, so hard-coding the ID's into the test case is right out.

Fortunately, I figured out two solutions to the problem. I'm not sure which is better, and as a result I'm not sure which I should recommend.

1) I could use XPATH to locate the element. The devs almost always use the ID attribute when they write up the html, and while JSF will re-assign it on the rendered page, the dev-assigned substring is always (AFAIK) a part of the JSF-generated id. For example:

<input id="name"...>

will be rendered as something like:

<input id="j_id1234567:name"...>

However, a search using XPATH can yield false positives. It also might not stay stable if a dev changes the ID, or if the id-generation algorithm changes.

2.(Recommended by friend who actually works with Selenium) Create empty CSS classes for the input elements, as CSS selectors can be used to locate an element in Selenium., e.g.

<input id = "name"... class="... qa_name">

where .qa_name is empty, and then use driver.findElement.(By.cssSelector(".qa_name")) to locate.

If you create one class per tested element, you have a deterministic way to identify the desired element. What concerns me about this is that

  • I don't know if this will create any overhead while loading the page.
  • The webapp this would be used for has a LOT of input fields.
  • Dev will probably not be thrilled about having to create a bunch of custom CSS for each page.
  • This doesn't seem like a proper use of CSS. I was under the impression that CSS was purely for styling, not giving information about an element.

Are one of these methods more valid than the other, or are these both valid? Also, are my concerns about these methods valid?

Best Answer

I would focus on looking for the stable portion of the ID. You can use CSS selectors to do this.

driver.findElement(By.cssSelector("input[id^='j_id']");

This is read find an INPUT tag that has an ID that starts with (^) j_id. You can also look for ends with ($) or contains (*).

Read more on CSS Selectors

Related Topic