June 27, 2017
Selenium Identifying Elements: Text Version
To work with a page under test using Selenium you will need to first be able to identify different elements on the page. Only after an element has been identified successfully it is possible to interact with it (e.g. clicking, text input …).
Finding Elements
Before you can interact with any element on the webpage you need to help Selenium find the correct element. This is relatively easy if we are talking about static elements but can get complex rather fast with elements that change dynamically. Let us tackle the easy ones first and then move on to a more complex example.
Finding Static Elements
Let us imagine that we have simple search engine page with just a text input and button as possible elements. The HTML for this could look something like this:
<form> <input name="searchQuery" type="text" /> <input name="submitSearch" type="submit" /> </form>
As one would expect finding these static elements is a rather easy task using Selenium. You could simply search them by their unique name attribute.
-
[java]
WebDriver driver = new ChromeDriver();driver.navigate().to("http://www.selenium.academy/Examples/StaticElements.html");
WebElement searchQuery = driver.findElement(By.name("searchQuery"));
WebElement submitSearch = driver.findElement(By.name("submitSearch"));// …
driver.quit();
[/java] -
[csharp]
IWebDriver driver = new ChromeDriver();driver.Navigate().GoToUrl("http://www.selenium.academy/Examples/StaticElements.html");
IWebElement searchQuery = driver.FindElement(By.Name("searchQuery"));
IWebElement submitSearch = driver.FindElement(By.Name("submitSearch"));// …
driver.Quit();
[/csharp]
-
[ruby]
require ‘selenium-webdriver’
require ‘test/unit’class SeleniumTest < Test::Unit::TestCase
def setup
# Start a new instance of Google Chrome
@driver = Selenium::WebDriver.for :chrome
enddef testChrome
@driver.navigate.to ‘http://www.selenium.academy/Examples/StaticElements.html’
searchQuery = @driver.find_element(:name => ‘searchQuery’)
submitSearch = @driver.find_element(:name => ‘submitSearch’)
enddef teardown
@driver.quit
end
end[/ruby]
-
[python]
import unittest
from selenium import webdriverclass TestChrome(unittest.TestCase):
def setUp(self):
# Start a new instance of Google Chrome
self.driver = webdriver.Chrome()def tearDown(self):
# close the Chrome instance
self.driver.quit()def testChrome(self):
self.driver.get(‘http://www.selenium.academy/Examples/StaticElements.html’)searchQuery = self.driver.find_element_by_name(‘searchQuery’)
submitSearch = self.driver.find_element_by_name(‘submitSearch’)if __name__ == "__main__":
unittest.main() # run all tests[/python]
-
[javascript]
var assert = require(‘assert’),
test = require(‘selenium-webdriver/testing’),
webdriver = require(‘selenium-webdriver’);test.describe(‘Selenium Academy’, async function() {
test.it(‘should work in Chrome’, async function() {this.timeout(5000);
var driver = new webdriver.Builder().withCapabilities(webdriver.Capabilities.chrome()).build();
await driver.get(‘http://www.selenium.academy/Examples/StaticElements.html’);var searchQuery = await driver.findElement(webdriver.By.name(‘searchQuery’));
// …var searchSubmit = await driver.findElement(webdriver.By.name(‘submitSearch’));
// …await driver.quit();
});
});
[/javascript]
Of course, the name attribute will not always be unique or the best option. Other search possibilities are:
- ClassName
- LinkText
- PartialLinkText
- TagName
- CSS
- XCode
Finding Dynamic Elements
Unfortunately, in many cases, the elements will not have a static unique identifier you can use. For our next example, we take a look at a category list in a web shop implementation. As categories are added or removed the links and their attributes will change so we cannot just target one of the visible ids.
<ul> <li><a href="#software" id="14_category">Software</a></li> <li><a href="#hardware" id="33_category">Hardware</a></li> <li><a href="#printer" id="19_category">Printer</a></li> </ul>
So how can we write test code that is able to identify the Hardware category regardless of id and position in the list? Firstly we will identify all category links by using a CSS selector. Then we can iterate all found links until we find the one which has ‘Hardware’ as a link text.
-
[java]
WebDriver driver = new ChromeDriver();driver.navigate().to("http://www.selenium.academy/Examples/DynamicElements.html");
List<WebElement> links = driver.findElements(By.cssSelector("a[id$=’_category’]"));
for (int i = 0; i< links.size(); i++)
{
WebElement link = links.get(i);
if ("Hardware".equals(link.getText()))
{
// …
}
}driver.quit();
[/java] -
[csharp]
IWebDriver driver = new ChromeDriver();driver.Navigate().GoToUrl("http://www.selenium.academy/Examples/DynamicElements.html");
IReadOnlyCollection<IWebElement> links = driver.FindElements(By.CssSelector("a[id$=’_category’]"));
foreach (IWebElement link in links)
{
if (link.Text.Equals("Hardware"))
{
// …
}
}driver.Quit();
[/csharp] -
[ruby]
require ‘selenium-webdriver’
require ‘test/unit’class SeleniumTest < Test::Unit::TestCase
def setup
# Start a new instance of Google Chrome
@driver = Selenium::WebDriver.for :chrome
enddef testChrome
@driver.navigate.to ‘http://www.selenium.academy/Examples/DynamicElements.html’links = @driver.find_elements(:css => "a[id$=’_category’]")
links.each do |link|
if link.text.eql? ‘Hardware’
# …
end
end
enddef teardown
@driver.quit
end
end
[/ruby] -
[python]
import unittest
from selenium import webdriverclass TestChrome(unittest.TestCase):
def setUp(self):
# Start a new instance of Google Chrome
self.driver = webdriver.Chrome()def tearDown(self):
# close the Chrome instance
self.driver.quit()def testChrome(self):
self.driver.get(‘http://www.selenium.academy/Examples/DynamicElements.html’)links = self.driver.find_elements_by_css_selector("a[id$=’_category’]")
for link in links:
if link.text == ‘Hardware’:
print link.textif __name__ == "__main__":
unittest.main() # run all tests[/python]
-
[javascript]
var assert = require(‘assert’),
test = require(‘selenium-webdriver/testing’),
webdriver = require(‘selenium-webdriver’);test.describe(‘Selenium Academy’, async function() {
test.it(‘should work in Chrome’, async function() {this.timeout(5000);
var driver = new webdriver.Builder().withCapabilities(webdriver.Capabilities.chrome()).build();
await driver.get(‘http://www.selenium.academy/Examples/DynamicElements.html’);var links = await driver.findElements(webdriver.By.css("a[id$=’_category’]"));
links.forEach(function(link) {
if (link.text === ‘Hardware’) {
// …
}
}, this);await driver.quit();
});
});
[/javascript]
This way you can find elements which are dynamically placed on the page and do not have a unique page-wide identifier.
Next Steps
In our next lesson we will cover how you can interact with the elements you just identified.