Death to visible content as locators in automated tests
Alister Scott has a post up called Death to xpath (and css) selectors in automated tests which started well but then went over-the-top webdriver vs. watir. Which I suppose makes some sense, but doesn’t matter. What does matter is something I see in scripts all the time and is a trap that Alister just fell into when writing his webdriver examples[1].
Do not use user visible strings in/as locators
I would argue that things like link locator strategy (which uses the user visible part of an anchor tag) or alt attribute and event tricks like contains(text(), ‘foo) [in xpath] should be avoided at all costs.
Why?
Because the world is not all <whatever your language is> and it is very rare for a site to not need another visible language at some point. And trust me, when they do ‘magically’ add Spanish or Korean or whatever, your scripts are expected to work. Rightly or wrongly, fairly or unfairly. If you are using ids and/or classes as your structural hooks, you have a far greater chance of that happening rather than Hello, ¡Hola or ?????.
It also means you are tied to the content of the site, which to me isn’t the point of automation. The point is to go through the the functionality of the site to ensure that it behaves the same way it did previously — and reports any deviances. I’ve worked at/for a number of sites which allow the marketing department the ability to change the content of the site when the need (want) without affecting the functionality of the site. Which is great; pushing to production for a grammar change is dumb. But if you tied to the content to make your scripts work you are going to end up with ‘brittle’ scripts[2].
Sometimes though, you have no choice but to just clench your jaw and use a visible string in a locator. But that should only be after exhausting the option of getting ids put on elements of interest.
Oh. And apparently you can chain your element discovery in webdriver along these lines
<pre lang="python">driver.find_element(by.TAG_NAME, "div").find_element(by.CLASS_NAME, 'chaining')
or if you are using the Page Factory stuff there is the FindBys annotation
<pre lang="java">@FindBys({@FindBy(how = How.ID, using = "foo"),
@FindBy(how = How.CLASS_NAME, using = "bar")})
[1] Now, these are as throw-away examples as ever there was any and in production scripts I’ve no doubt he would have done some sort of Page Object implementation with well named locator abstraction, etc.
[2] There is no such thing as an inherently brittle scripts; you, the author of the script are the one who made it brittle.