Introduction
Learning and mastering a powerful location strategy is a must in Selenium test automation. CSS and XPath are the most powerful location strategies as compared to the other location strategies available such as ID, name, class name, tag-name, link text and partial link text. Most of the test automation engineers are familiar with above location strategies.
Selenium 4 will have Relative locators. It is a friendly way to locate the elements with friendly terms (methods) like ‘near’, ‘above’ , ‘below’, ‘toLeftOf’ and ‘toRightOf’.
The intent of this blog post is to help Selenium test automation engineers, especially the beginners to understand the importance of mastering location strategies and set a path to master the CSS location strategy.
We have discussed XPath in detail in a separate blog post already and this blog post will limit to CSS location strategy.
At the beginning you will see the comparison of CSS and XPath in the context of Selenium test automation, practical usage of CSS and few pain points are shared in the next section. Number of CSS options available with syntax, HTML snippet and examples are discussed in the middle of the post. XPath to CSS conversion tools, CSS generating tools, validation tools, a game for practicing CSS are discussed at the later part of this blog post. A cheatsheet and a glossary are added to the end of the post.
We have referred a wide range of online resources, included lessons learned from our training programs and experience through test automation projects into this blog post.
We will continue to improve and update this post and share with the testing community. [ last updated on 05 Jan 2021]
Happy test automation!
What is CSS?
Cascading Style Sheets, fondly referred to as CSS, is a simple design language intended to simplify the process of making web pages presentable.
CSS handles the look and feel part of a web page. Using CSS, you can control the colour of the text, the style of fonts, the spacing between paragraphs, how columns are sized and laid out, what background images or colors are used, as well as a variety of other effects.
CSS is
CSS or XPath
CSS and XPath are the most popular, widely used and powerful location strategies within the Selenium test automation community. CSS has gained wider acceptance due to following reasons. (People in favor of CSS says)
- CSS more readable ( simpler )
- CSS is faster (especially in IE)
Those who are in favor of XPath says about its ability to transverse around the page where CSS cannot. XPath can traverse up and down the document tree. CSS can traverse only down to the DOM.
These claims may be already outdated. Some research demonstrates that there is no significant difference in speed of CSS and XPath executions.
Following is from Mozilla Developer Network Documentation
Mastering XPath and CSS is a good investments for the Selenium test automation engineers who wish to build their career around Selenium. It is better to a use a single location strategy within a project for consistency. Some gurus advice a hybrid approach. They use ID, name first and moving to CSS. XPath is used only when it is required. In this section, we will discuss characteristics of a good location strategy. We shall select a best possible CSS from available options/syntax. A good location strategy should be Your CCS locator should have only one candidate element (Unique) when you want to target a single element using findElement method. It is easy to identify the element in the script easily when the CSS is descriptive. It should be possible to locate the element with given CSS when a test is run repeatedly in subsequent releases. CSS should be selected in such a way that it is valid even after the changes to the DOM. You will have multiple CSS options when you master CSS. A shorter CSS shall be selected to make it more readable in your test scripts. We will use the following HTML , a simple login form to explain the CSS syntax in most of the cases. This is extracted from our demo site. Let’s get familiar with mostly used terms in CSS syntax. Following syntax can be used for locating elements with a known attribute value. Syntax : Examples : Let’s see how to locate the username field using the syntax. The third option should not be used if you want a select an element uniquely even though it is a valid syntax. There could be many such elements and Selenium will not be able to locate target element uniquely. Selenium will return the first element with the given CSS when findElement method is called. As you know in real life we use unique names (or IDs) to locate a person in a group. As you know it is not possible to locate a person distinctly by name Mohammed in a muslim community. You will have to use some other name to locate a person uniquely. If you are interested in all the elements with the common attribute you may use the syntax with findElements method and iterate through the elements. The following can be used for locating elements with a known tag-name and their attributes’ value. Syntax: Examples : Note In CSS # sign is used for locating the elements by the value of attribute-name ID. Syntax : Examples : You can locate target elements by one of the class name (value) in class attribute. Syntax : Examples : Multiple classes can be separated by dots as in the following syntax Syntax : Examples : It is not required to provide all the class names. Ensure element is uniquely selected with minimum number of classes if you decide to use class names. Syntax : Examples : Sometimes it may not be possible to locate an element with a single attribute. In the real world, we have a similar issue. We cannot locate a person with just the first name or last name. We will have to use a combination of first name and last name to locate a person to locate a person without making any confusion. Syntax : Examples : It is not necessary to use multiple attributes if one attribute can be used for locating the target element(s) uniquely. You may not have to use more than two attributes to locate the target element(s) uniquely. We can locate direct child element(s) with respect to a known parent element using > character. An element could have zero, one or many child elements. Syntax : Example : In the first example we input element is selected. All children (input and span) will be selected when universal character * is used. When space is given descendant elements of context elements are selected. It will select all elements inside a context element when universal character * is used. Syntax : Examples : Three(3) input elements inside the form element will be selected in the first example . All elements inside the form element will be selected in the second example. Sometimes there will be more than one element for a given CSS. When you use findElement(By by) method , first element is selected by Selenium. findElement method should not be used to look for non-present elements, use findElements(By) and assert zero-length response instead. The findElement method will return a matching element or try again repeatedly until the timeout is reached. findElement method will select the first element when there are multiple candidate elements for a given CSS. It will not wait for other possible elements with given CSS. Use findElements(By by) method to get the ALL elements with given CSS. This syntax can be used for selecting an element from a list of sibling elements by their position. Syntax : Examples : Following can be used for locating the first element from list of siblings. Syntax: Examples : In following examples we select username input field distinctly from available three candidate elements. You can use :last-child to locate a last element from a list of siblings. Syntax : Examples : Third input element will be selected in first example as shown in the figure. Last div element will be selected in second and third example. You can use :nth-child(n) to locate an element from its first sibling and :nth-last-child(n) locate an element from the last sibling. Syntax : Examples : Third input element will be selected in first and second examples as shown in the figure. Following can be used when you have dynamic attribute values, but they begin with a fixed string. Syntax : Examples : Following can be used when you know the dynamic attributes have fixed ending attribute value (suffix). Syntax : Example : Following can be used when you know a substring of the attribute value is fixed. Syntax : Examples : Following can be used when your attribute value has more than one word separated by spaces. Syntax : Example : [attribute-name|=’value’] can be used for locating element whose attribute value is exactly equal to value or attribute-value begin with value immediatelyfollowed by – (hyphen)
Following can be used for locating immediate next sibling appear after a context element. Syntax : Examples : Second input element will be selected in first example. No element will be selected in second example. Second input element will be selected in third example Following syntax can be used for locating elements after the context element who has same patent. It will not select the descendants. Syntax : Examples : Two input elements after the context element will be selected in first example. Five div elements will be selected in second example. All seven elements after the context element will be selected in the third example. Following cannot be used for locating elements with their visible text available between opening and end tags. This is a limitation of CSS. Use Xpath for locating elements by their innerText. You may use linkText or partialLinkText location strategies if the context element is an anchor tag <a>. XPath Syntax : It is possible to locate the element ignoring the case sensitivity of the attribute values using the character i or I after the value. Syntax : Examples : This will be useful when you need to ensure specific attribute value is not available in an element. The negation :not() can be used for selecting elements that are not represented by its arguments. Syntax : Example : Let’s say you want to select all the input elements which are not hidden. input:not([type=’hidden‘]) Following can be used for locating selected (unselected) , checked radios, check boxes and options. Syntax : Examples : Let’s say you want to select all the selected options and not selected. option:checked option:not(:checked) You can evaluate two or more CSS selectors by separating them with a comma. Syntax : Example : Let’s say you need to select all input element with type text, password and submit. [type=’text‘],[type=’password‘],[type=’submit‘] Now it’s time to practice CSS selectors. Lets use this fun game CSS Diner game. In this demo, we show selecting the pickle on the fancy plate (Level 5 of 32) using CSS plate[id=’fancy’]>pickle It is important to ensure CSS used in your automation script is validated before running the script. Fixing the CSS errors after running the test is expensive. There are a number of tools available to validate the correctness of the XPaths. Lets see how to use Chrome DevTools to validate CSS selectors. If you have decided use CSS and want to convert existing XPaths into CSS following program can be used. ccsify by Santiago Suarez Ordoñez Css Vs. X Path. [ONLINE] developer.mozilla.org : CSS Selectors | MDN Web Docs. [ONLINE] jquery – CSS selector case insensitive for attributes – Stack Overflow. [ONLINE] Sauce Labs. 2016. Selenium Tips: CSS Selectors | Sauce Labs . [ONLINE] Selenium Easy. 2016. CSS selectors for Selenium with example. [ONLINE] W3C Recommendation 06 November 2018 [ONLINE] Saurabh Gupta. Quick Reference for Xpath and CSS locators – Selenium WebDriver. [ONLINE] Testing Excellence. CSS Selectors in Selenium WebDriver with Examples. [ONLINE]
[attribute-name='attribute-value’]
tag-name[attribute-name='attribute-value']
Javascript :: driver.findElement(By.css("input[id='txtUsername']")).sendKeys('Admin')
Java :: driver.findElement(By.cssSelector("input[id='txtUsername']")).sendKeys("Admin");
Python :: driver.find_element_by_css_selector("input[name='txtUsername']").send_keys("Admin")
tag-name#valueofID
or #valueofID
tag-name.className
or .className
tag-name.
className1.className2….classNameN
or .className1.className2….classNameN
tag-name.className[attribute-name=’attribute-value’
]
or .className[attribute-name=’attribute-value’]
tag-name[a-name1=’a-value1’][a-name2=’a-value2’] ..[a-nameN=’a-valueN’
]
or [a-name1=’a-value1’][a-name2=’a-value2’] ..[a-nameN=’a-valueN’]
CSS-of-Parent
>
Element
CSS-of-Parent
>
*
CSS-of-Context-Element<space>tag-name
CSS-of-Context-Element<space>*
WebElement txtUsername=webDriver.findElement(By.cssSelector("form input"));
webDriver.findElement(By.cssSelector("form input")).size();
List<WebElement> inputElements=webDriver.findElements(By.cssSelector("form input"));
CSS-of-Context-Element<space>tag-name:nth-of-type(N)
CSS-of-Context-Element<space>*:nth-of-type(N)
:first-of-type can be used for selecting first sibling of the candidates
:last-of-type can be used for selecting last sibling of the candidates
:only-of-type can be used for selecting an element that has no siblings with the same expanded element name.
CSS-of-Context-Element<space>Element:first-child
CSS-of-Context-Element>Element:first-child
CSS-of-Parent-Element<space>Element>:last-child
CSS-of-Parent-Element>>Element>:last-child
CSS-of-the-Siblings:nth-child(n)
CSS-of-the-Siblings:nth-last-child(n)
:only-child can be used for selecting elements with no siblings
:empty can be used for selecting elements without children
:only-of-type can be used for selecting elements with same element name
tag-name[attribute-name^=’fixed-prefix-of-value’]
or [attribute-name^=’fixed-prefix-of-value’]
tag-name[attribute-name$=’fixed-suffix’
]
or [attribute-name$=’fixed-suffix’]
tag-name[attribute-name*=’fixed-substring-of-the-value’]
tag-name[attribute-name~=’a white space separated value’]
CSS-of-context-element
+
tag-name
CSS-of-context-element
+
*
CSS-of-context-element ~ tag-name
CSS-of-context-element ~ *
tag-name:contains(‘part-of-the-text’)
tag-name[Attribute=’Value’ i]
[Attribute=’Value’ I]
css-of-context-node:not([attribute2='value2'])
css-of-the-element:checked
css-of-the-element:not(:checked)
CSS-Selector1, CSS-Selector2, ... , CSS-SelectorN
Category CSS Note
E[id=’i’] Element
[id=’i’] Element(s) with id i
E[@name=’n’] Element
[@name=’n’] Element(s) with name
E[A=’V’] Element
E[A*=’V’] Element
E[A^=’V’] Element
E[A$=’V’] Element
E1[A1=’V1’] , E2[A2=’V2’] Element
E[@A1=’V1’] , E[@A2=’V2’ ] Element
E:contains(’T’) Element
E:empty Element
E2~E1 Element
E2 + E1 Element
E:disabled Element
E:enabled Element
E:checked Checkbox or radio element(s)
CSS Cascading Style Sheets. CSS describes how HTML elements are displayed.
CSS Selector A CSS Selector is a combination of an element selector and a value which identifies the web element within a web page. They are string representations of HTML tags, attributes, Id and Class.
DOM Document Object Model.
Attribute All HTML elements can have attributes. Attributes provide additional information about an element. Attributes usually come in name/value pairs like: name="value"
Available at: http://elementalselenium.com/tips/32-xpath-vs-css.
[Accessed 03 Feb 2020].
Available at:https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors.
[Accessed 10 Feb 2020].
Available at:http://stackoverflow.com/questions/5671238/css-selector-case-insensitive-for-attributes.
[Accessed 03 Feb 2020].
Available at:https://saucelabs.com/resources/articles/selenium-tips-css-selectors.
[Accessed 03 Feb 2020].
Available at:https://www.seleniumeasy.com/selenium-tutorials/css-selectors-tutorial-for-selenium-with-examples.
[Accessed 03 Feb 2020].
Available at: https://www.w3.org/TR/css3-selectors/.
[Accessed 03 Feb 2020].
Available at: https://www.linkedin.com/pulse/quick-reference-xpath-css-locators-selenium-webdriver-saurabh-gupta.
[Accessed 02 Feb 2020].
Available at:http://www.testingexcellence.com/css-selectors-selenium-webdriver-tutorial/.
[Accessed 02 Feb 2020].
Comments
Ravi
Great post !! This is really helpful