Welcome back, Warriors! We just saw how to check if a particular data is present in a table’s specific cell with and without using XPath. Time to loop through each element and visualize the power of Selenium WebDriver. Let us go back to our Demo Site and focus on “Books & Authors” table to understand this concept.
Step 1:
Locate the table “Books & Authors” using its id, ‘BooksAuthorsTable’. The HTML code is as below,
<table id="BooksAuthorsTable" class="table table-bordered">
Code:
WebElement BooksTable = driver.findElement(By.id("BooksAuthorsTable"));
Step 2:
Calculate the total number of rows and columns using XPath.
Let us find the total number of rows using absolute XPath. Note that the XPath ends with the tag name, ‘tr’. The size() method gives the number of elements returned by findElements() using XPath.
Code:
int rowNum = driver.findElements(By.xpath("/html/body/form/div[5]/div/div/table/tbody/tr")).size();
Let us switch gears a bit and find the total number of columns using relative XPath.
Code:
int colNum = driver.findElements(By.xpath("//table[@id='BooksAuthorsTable']/tbody/tr[1]/th")).size();
This method of finding the total number of rows and columns is useful in case of tables whose rows and columns change dynamically.
Step 3:
Looping through table elements
If the table rows and column numbers are fixed, then looping through each table element becomes pretty easy. Two for() loops, one for rows and the other for accessing column values can be used.
Code:
for(int i=2; i<=6; i++){
for(int j=1; j<=4; j++){
System.out.print(driver.findElement(By.
xpath("//table[@id='BooksAuthorsTable']/tbody/tr[" + i +"]/td[" + j + "]")).getText() + "\t");
}
System.out.println("");
}
Someday, if you are lucky, you might stumble across a table that loads dynamically with each page refresh and hence the number of rows usually varies. And therefore, the row count is to be calculated every single time test is executed.
First, let us get all elements with tag name ‘tr’ and put them in a list named ‘rowVals’.
List<WebElement> rowVals = BooksTable.findElements(By.tagName("tr"));
To get the header elements from the first row, find all elements with tag name ‘th’ and put them in a list named ‘colHeader’.
List<WebElement> colHeader = rowVals.get(0).findElements(By.tagName("th"));
To print each header text to console, loop through the header values from colHeader list and use getText() method.
for(int i=0; i<colHeader.size(); i++){
System.out.println(colHeader.get(i).getText());
}
To print table contents to console, loop through the each row. For every row, traverse through each column and print the values using the same getText() method.
for(int i=1; i<rowNum; i++){
List<WebElement> colVals = rowVals.get(i).findElements(By.tagName("td"));
for(int j=0; j<colNum; j++){
System.out.println(colVals.get(j).getText());
}
}
Is your ability to focus sliding downhill? If yes, let us look at a BrainBell!
BrainBell – Visualize! Most of us know that creating a mental picture for the concept we wish to remember makes it clearer and easier to remember than words. What we don’t know or do is, visualizing it carefully for a few seconds. This will help to recall it with ease.
With that being said, let us see the overall picture of what we discussed so far!
Scenario
- Open Firefox browser
- Navigate to the demo site
- Locate ‘Books & Authors’ table using id
- Get the total number of rows using absolute XPath
- Get the total number of columns using relative XPath
- Print row and column count to console
- Get all row values by tag name ‘tr’
- Get the column header values in a list by tag name ‘th’
- Loop through the header values and print them to console
- Loop through the table contents (all columns for each row) and get its text
- Print the values to console
- Print the table contents to console using fixed row and column numbers
JUnit code for this scenario is,
package com.blog.junitTests;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class LoopingThroughTableElements {
// Declaring variables
private WebDriver driver;
private String baseUrl;
@Before
public void setUp() throws Exception {
// Selenium version 3 beta releases require system property set up
System.setProperty("webdriver.gecko.driver", "E:\\Softwares\\"Selenium\\geckodriver-v0.10.0-win64\\geckodriver.exe");
// Create a new instance for the class FirefoxDriver
// that implements WebDriver interface
driver = new FirefoxDriver();
// Implicit wait for 5 seconds
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
// Assign the URL to be invoked to a String variable
baseUrl = " https://chandanachaitanya.github.io/selenium-practice-site/";
}
@Test
public void testPageTitle() throws Exception {
// Open baseUrl in Firefox browser window
driver.get(baseUrl);
// Locate 'Books & Authors' table using id
WebElement BooksTable = driver.findElement(By.id("BooksAuthorsTable"));
//Get all web elements by tag name 'tr'
List<WebElement> rowVals = BooksTable.findElements(By.tagName("tr"));
//Get number of rows and columns
//using absoulute xpath
int rowNum = driver.findElements(By.xpath("/html/body/form/div[5]/div/div/table/tbody/tr")).size();
//using relative xpath
int colNum = driver.findElements(By.xpath("//table[@id='BooksAuthorsTable']/tbody/tr[1]/th")).size();
System.out.println("Total number of rows = " + rowNum);
System.out.println("Total number of columns = " + colNum);
//Get column header values from first row
List<WebElement> colHeader = rowVals.get(0).findElements(By.tagName("th"));
//Loop through the header values and print them to console
System.out.println("Header values:");
for(int i=0; i<colHeader.size(); i++){
System.out.println(colHeader.get(i).getText());
}
System.out.println("---------------");
//Loop through the remaining rows
for(int i=1; i<rowNum; i++){
//Get each row's column values by tag name
List<WebElement> colVals = rowVals.get(i).findElements(By.tagName("td"));
//Loop through each column
for(int j=0; j<colNum; j++){
//Print the coulumn values to console
System.out.println(colVals.get(j).getText());
}
//Just a separator for each row
System.out.println("---------------");
}
//Printing table contents to console for fixed row and column numbers
for(int i=2; i<=6; i++){
for(int j=1; j<=4; j++){
System.out.print(driver.findElement(By.
xpath("//table[@id='BooksAuthorsTable']/tbody/tr[" + i +"]/td[" + j + "]")).getText() + "\t");
}
System.out.println("");
}
} //End of @Test
@After
public void tearDown() throws Exception {
// Close the Firefox browser
driver.close();
}
}
Execution Result:
Each line of code is well explained as part of concept covered thus far.
Upon noticing eclipse IDE’s JUnit view, green bar shows that the test case is executed successfully.
Console window shows the absence of any errors. It also shows the printed table contents for both fixed and dynamically calculated row and column count as expected.
Hope I always give you something to ponder! See you soon in another post.
Have a nice day!
If I want to save the data of the table into a model (i. e. List()), to compare it with an expected value (another list with values), how can I do that?
I am new this Selenium framework and I was in a real need to find a solution, which is posted here. it really helped me very very much in my time of need. I thank you very much for my bottom of my heart.
Thanks,
Joshua Jeyaseelan Albert
Welcome Joshua. Glad to hear that it helped you. 🙂
hi , how to validate the expected table header values with actual table header values , Could you please tell
Using Tagname with tr and td takes much too long with big tables.
Create the array using javascript and use Javascript injection instead.