-2

So our QA guy came by today to get me to put id's on items in our html so he could automate stuff using watir.

I don't know much about it, so I tried to see if we could use the class names instead, but that's a total crapshow.

I was just wondering why something like

link(:item, :id => 'save-btn')

works when you set it up in watir, but you can't do something like

links(:item, :class => 'save-btn')[0] 

I also tried using the browser.links calls, but we would consistently get

element not visible errors

I was just wondering why this was so difficult, to where using ids on everything seems to be the recommended way to go with everything? Is there a way to use class names with watir or is that just the way things are done?

concept47
  • 30,257
  • 12
  • 52
  • 74

2 Answers2

2

CSS class attributes are quite normal way of accessing elements with Watir. As is id.

For class attributes, however you have to specify usually the context where you're searching from because there might be more than one element with the same class as opposed to id attribute, which has to be unique for the whole page.

I'm not sure what framework you're using in your examples, but this is how i would do it in plain old watir if the save button is in some container element:

browser.div(id: "container").span(class: "save-btn")

The code above will find first span with class "save-btn" in the container element as expected.

Also, do not use xpath or css locators ever as suggested by another answer in here. Why? Because they are really fragile and make your tests too hard to read/maintain.

Jarmo Pertman
  • 1,905
  • 1
  • 12
  • 19
1

Short answer: Adding class names to source code is the correct direction and should be considered as good practice, however, after that, using :class locator isn't good enough in most of the case, try use :xpath or :css. Therefore, you, as a developer, go ahead and add the class names, but you need make sure your QA people know how to use Watir, don't simply use :id or :class for all locators.

Long answer: If the site is simple enough, adding IDs would be easiest and the best one. However, nowadays, many JavaScript frameworks like ExtJS, create dynamic IDs, so in that case adding class names to source code would be better.

After adding the class names, for example in your case, using :class locator is a bad choice, which might be even worse than :id, as IDs are supposed to be unique. For complex pages, :class locator is pretty much useless, which will find unwanted elements.

Here, your error message means you might have more than one elements with class save-btn, the first one isn't visible to be interacted with.

Selenium WebDriver or Watir WebDriver, both support XPath and CssSelector, so you should use :xpath or :css when necessary, instead of :id, :class etc.

For example, something like:

links(:item, :css=> '.save-btn:not([style*='display:none'])')[0]

Jarmo Pertman suggests using ID/Class is in favor of XPath/Css Selectors, which is not completely correct. ID/Class are just subsets of XPath/Css Selectors, if it's easy enough, use ID/Class, however unnecessary chaining is not a good practice, in the example he gave,

browser.div(id: "container").span(class: "save-btn")

is equivalent to CSS selector div#container span.save-btn, therefore, there are no fragile or maintenance issues for CSS selector, because they are identical.

XPath/CSS selectors are powerful tools, everyone should be learning, but only use them if really needed. Bad XPath/Css Selector are fragile, try find the good ones. (But bear in mind that XPath is slow, should be considered as last option)

Yi Zeng
  • 32,020
  • 13
  • 97
  • 125
  • Using class attributes is pretty normal and recommending xpath or css locators is bad practice. See my answer. – Jarmo Pertman Sep 17 '13 at 20:02
  • @JarmoPertman: In real world, nope, if you take a look at how StackOverflow questions, most people consider XPath or CssSelector. Imagine `browser.div(id: "container").div(class: 'something1').div(class: 'something2').div(class: 'something3').span(class: "save-btn")` and `#container .something1 .something2 .something3 .save-btn`, which would you choose? Bad XPath/Css Selector are fragile, because they are the bad ones, try find the good ones.Maybe you have a point, but your example is far from convincing. By ID/Class are just subset of XPath/CSS Selector,so use them only if they can handle it. – Yi Zeng Sep 17 '13 at 20:16
  • Well, i myself am a developer (also coincidentally a core developer for watir-classic and a little for watir-webdriver) and have never seen anything like you've just shown in the real world. It would make semantically good sense to add some id attribute in the chain because usually pages have meaningful sections. For example, there's a user edit form where the button "save-btn" is. This is how it would look: `browser.div(id: "user-form").span(class: "save-btn")`. I have never used more than one context element. Also, being a developer, the quality of SO answers have been decreasing... – Jarmo Pertman Sep 17 '13 at 20:23
  • Also, at least in watir-classic (not so sure about watir-webdriver), searching by `xpath` or `css` is much-much slower. – Jarmo Pertman Sep 17 '13 at 20:24
  • @JarmoPertman: Two valid points, 1.the quality of SO answers have been decreasing, 2. XPath/CSS are slower. But nowadays, things are not that easy, have a look at frameworks like [ExtJS](http://docs.sencha.com/extjs/4.2.1/extjs-build/examples/build/KitchenSink/ext-theme-neptune/), easy approaches won't work elegantly. – Yi Zeng Sep 17 '13 at 20:34