1

Disclaimer: I went through the answers here. But would like more insight on situations similar to the code below.

<div id="feedback-filter-buttons" class="ui-buttonset">
    <label class="filter-label ui-button ui-corner-top" for="feedback-all" role="button">
      <span class="ui-button-text">Very Good</span>
    </label>
    <label class="ui-button" role="button">
      <span class="ui-button-text"><span > Good </span></span>
    </label>
    <label class="ui-button" role="button">
      <span class="ui-button-text"><span > Alright </span></span>
    </label>
    <label class="ui-button ui-state-active" role="button">
      <span class="ui-button-text"><span > Bad</span></span>
    </label>
    <label class="ui-button" role="button">
      <span class="ui-button-text"><span > Very Bad</span></span>
    </label>
    <label class="ui-button ui-corner-bottom" role="button">
      <span class="ui-button-text"><span > Undefined (0)</span></span>
    </label>
</div>

Objective:
To get the text of the currently selected (ie., active) label(button).

Approaches:
a) webDriver.findElement(By.id("feedback-filter-buttons")).findElement(By.className("ui-state-active")).getText()

b) webDriver.findElement(By.xpath("//*[@id='feedback-filter-buttons']/label[contains(@class,'ui-state-active')]/span")).getText()

Question:
Which of the above approaches is better and why? At the moment, I am leaning towards xpath as I am able to specify the path till the final element I require.

Community
  • 1
  • 1
Siva
  • 186
  • 1
  • 10

1 Answers1

3

From the performance point of view, the xpath approach would be slower and I'd go with the first option.

For starters, you use * (not specifying the actual tag), which makes it traverse the tree, do a full page scan; and then you apply contains(), which is a string matching function.

Searching By.id() is definitely the fastest approach, since under-the-hood it is calling getElementById() which browsers know how to optimize. Plus, you are quickly narrowing down the search scope to the parent element and then make a search inside by the class name.

Besides, relying on these id and class attributes is not only making your testing code readable and easily understandable, but also more explicit and robust. Think about possible errors: in case of xpath approach, you would only get that it cannot find the element using the xpath you gave it - not really informative, you would not even know where to start debugging. In case of id+class approach, you would see two different kinds of errors: "could not find the parent by id" and "could not find the element by class name".

alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • Thanks for the detailed explanation. Also how does find `By.className` fare compared with `id` and `xpath`? Additionally I am dealing with many lists of items where the item(assume a case where class `'ui-state-active'` is absent) dom structure remains the same but the item div index changes. Eg: A sample code: `"//div[@id='d-view']/div[3]/div["+index+"]/div[2]/div[3]/div[2]/div[2]/span[1]"` within a for loop. Would you recommend accessing such an item `By.xpath` as above or a `By.cssSelector`? I could ask a separate question if you want me to. – Siva Aug 07 '14 at 03:46
  • 1
    @Siva well, I would not recommend relying on the element position inside it's parent too much and often. Having xpath expressions like `... div[2]/div[3]/div[2]/div[2]/span[1]` is usually a sign of a very fragile one. Usually there are certain things/anchors you can rely on isntead. `xpath` or `css selector` - I suppose the speed heavily depends on the driver/browser. You can also have other reasons to use either this or that depending on the required functionality, simplicity etc. Yeah, this can probably be a part of a separate interesting topic. Thanks. – alecxe Aug 07 '14 at 03:52