• Background Image

    Selenium Identifying Elements: Text Version

    June 27, 2017

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]

    Run Example Online

  • [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]

    Run Example Online

  • [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
    end

    def testChrome
    @driver.navigate.to ‘http://www.selenium.academy/Examples/StaticElements.html’
    searchQuery = @driver.find_element(:name => ‘searchQuery’)
    submitSearch = @driver.find_element(:name => ‘submitSearch’)
    end

    def teardown
    @driver.quit
    end
    end

    [/ruby]

    Run Example Online

  • [python]

    import unittest
    from selenium import webdriver

    class 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]

    Run Example Online

  • [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]

    Run Example Online

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]

    Run Example Online

  • [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]

    Run Example Online

  • [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
    end

    def 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
    end

    def teardown
    @driver.quit
    end
    end
    [/ruby]

    Run Example Online

  • [python]

    import unittest
    from selenium import webdriver

    class 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.text

    if __name__ == "__main__":
    unittest.main() # run all tests

    [/python]

    Run Example Online

  • [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]

    Run Example Online

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.