JQuery selectors
JQuery selectors are based on CSS 1-3 selectors plus a few others. They look like CSS selectors (web-developers can cheer now), and can be used if CSS selectors are not supported, for example when migrating to a new CSS version. JQuery selectors also allow you to manipulate with a single element and a list of elements.
As is well-known, Webdriver can execute JavaScript the following way:
JavascriptExecutor
ex = (JavascriptExecutor) driver;
List<WebElement> elements = (List<WebElement>)js.executeScript(“return
JQuery.find(‘:checked’)”);
This example finds all the checkboxes checked. However, to make this code work there should be a JQuery on the page. If your site is not on the list of millions that directly or indirectly use that library, you can write your own utility class, which will load JQuery to the page when you need it. If that inconvenience doesn’t stop you, and you can’t imagine NOT using JQuery, you can implement you own custom JQuery by class, to search for elements like:
driver.FindElements(By.JQuery(“a:contains(‘home’)”));
It feels slick, right? By the way, you can implement any other “custom” locator type you want (find examples of JQuery locators here.) Want to find an element by picture? Why not? Have a look at SikuliWebdriver implementation. As you see, Webdriver is easy to tune and more convenient and powerful than standard tools.
Pieces of advice:
- Thoroughly learn CSS and XPath selectors beforehand. Their role cannot be overestimated.
- In order to increase performance, use locators by id and by name whenever you can. CSS selectors work comfortably with classes, attributes and pseudo-classes like: :hover, :focus, :checked. Use XPath only when nothing else will do the job.
- Try not to use selectors, which are an absolute path to the element. Describe your code with attributes, text and different combinations.Eg: Bad manners/ unreadable
XPath =
“/html/div[5]/div[3]/ul/li[6]
CSS = “html>div>div+div+div>ul>li+li+liEg: Good manners/self-describing
XPath = “//ul[@class=’menu’]/li[text()=’home’]”
CSS = “ul.menu li.home”This kind of search is slower because your browser goes through more elements during the search – but it’s also more reliable. If you use Selenium IDE for getting selectors, please rewrite them. Otherwise, you could get unreadable and fragile selectors, which are sensitive to changes in html.
- It is best to choose the shortest, most reliable selectors you can. Use XPath Axes, operators and functions, and CSS pseudo-classes. “Write code like it will be supported by a violent psycho who knows where you live,” Martin Golding advises us.
- Use searching for one element inside another as much as you can. This approach will not improve performance but it makes it easier to find elements within a large number of look-alikes. In this case, use pattern Page Object and CSS and XPath selectors.Eg: Bad manners/unreadable
XPath = “//div[@class=’menu’]/div[15]/span/a”Eg: Good manners/ self-describing
XPath = “//div[@class=’menu’]//a[text()=’home’] - If you need to check both the presence of the tabinput and the corresponding labelheader for it, you can cheat and use XPath.XPath = “//div[@class=’logotab’ and .//h5[text()=’Logo’]]” – for tab with heading “Logo”.
XPath = “//input/parent::*//label[text()=’Name]]” – for input with label “Name”.
In summary
Webdriver is a great automation tool, having a vast number of locator types supported. In clever hands, it can find anything on the page. In addition, if there are any “blind” spots on a Webdriver map, you are always welcome to expand it to your needs. Webdriver integrates easily with every technology stack for automation of functional testing of web applications, and it works great in cooperation with other tools. Keep some things in mind, however:
- Do not place locators into the code. It’s better to make them variables and put at the “header” of the class, giving them meaningful names. This will let you easily find a broken locator and fix it in one place.
- You can go even further and choose either UI Map, or WebDriver Factory notation. UI Map will use a file for storing selectors and utility class to take a needed selector and returning By to the class asking for it. As a result, you get a package that is independent from selectors and you can change selectors in the file without rebuilding the whole project. This excludes repetition of selectors and it is easier to find the necessary selector because they are stored in one place.
- The downside is when you change an existing project to use UI Map. If there are many selectors, you will need to create separate files for each page, which makes the utility class’s work more difficult and increases the probability of repetitions. It would be easier for a manual test engineer to work with the file. For a developer, however, factory notation is more pleasant. Selectors decorate WebElements here – fields of chosen Page Object.@FindBy(name = ”login”)
private WebElement login;There is also an opportunity to remember the element with an annotation:@CacheLookup
@FindBy(name = ”login”)
private WebElement element; - Selectors are easier to find and edit when the code is clear.
It is up to you on what variant of Page Object to use. Each one has its bright and dark sides.