Web tables are commonly used for reporting dashboards, product listings, user management systems, and transactional data. However, automating interactions with web tables is often complex because they can vary from simple static tables to highly dynamic tables with multiple levels, pagination, or embedded interactive elements.
In Selenium, testers need to locate tables accurately, read data efficiently, and perform actions like clicking buttons, selecting checkboxes, or handling dropdowns within table cells.
This guide explains the different types of web tables, techniques to access and manipulate their data, and strategies to validate dynamic updates and nested structures.
Web tables are HTML elements that organize information in a structured format with rows and columns. They are used wherever tabular data needs to be presented clearly.
Examples include inventory lists, financial reports, user management panels, and analytics dashboards. Each table cell can contain plain text, links, buttons, checkboxes, or even nested tables, which makes handling them in automation more challenging than standard page elements.
Here are the common aspects of web tables in real-world applications:
Automation should be applied when tables are large, frequently updated, or contain interactive elements that need validation across multiple scenarios. Manual testing may work for static or small tables, but automation becomes essential when efficiency, accuracy, and repeatability are required.
Below are scenarios where automating web table actions in Selenium provides significant value:
Web tables can be static with fixed content or dynamic with data that changes based on user actions or server responses. Choosing the right approach depends on how the table behaves during testing.
Locating web tables correctly is crucial before performing any actions or validations in Selenium. Using the right locator reduces errors, improves script reliability, and makes maintenance easier. Different locators work better depending on whether the table is static, dynamic, or nested.
Here’s how
Locating web tables using IDs, class names, or CSS selectors is the most straightforward method when the table has identifiable attributes. These locators are faster and more stable than XPath in many cases, especially for static tables. Using these locators reduces maintenance overhead and improves test reliability.
Below are practical approaches for Selenium automation:
Dynamic web tables often change in structure or content, making CSS selectors or IDs less reliable. In such cases, XPath provides flexibility by locating elements based on text, attributes, or relative positions. This is especially useful for tables that load data asynchronously, have variable row counts, or include nested elements.
Below are common XPath strategies for handling dynamic tables:
Reading table data is one of the most common operations testers perform in Selenium. It helps in verifying values displayed on the UI against expected data from a database or API.
When you want to count or list all the rows in a table, you can target the <tr> elements. This is useful for validating whether the table is displaying the expected number of records. For example:
List<WebElement> rows = driver.findElements(By.xpath("//table[@id='employeeTable']//tr"));
System.out.println("Total rows: " + rows.size());
This prints the total number of rows in the employeeTable.
Sometimes you only need to extract the values of a single row, for instance when checking details of a specific employee or order. You can do this by fetching all <td> elements for that row. For example:
List<WebElement> cols = driver.findElements(By.xpath("//table[@id='employeeTable']//tr[2]/td"));
for(WebElement col : cols) {
System.out.println(col.getText());
}
This retrieves all the column values from the second row.
In cases where only one value matters, such as a price or status field, it is more efficient to directly locate that cell using a combination of row and column indexes. For example:
String cell = driver.findElement(By.xpath("//table[@id='employeeTable']//tr[3]/td[2]")).getText();
System.out.println("Cell value: " + cell);
This gets the text from the second column of the third row.
To loop through all rows and cells in a table, you can use nested iterations. This is often required for data-driven validations, where every record displayed on the UI needs to be compared with a source of truth.
For example:
List<WebElement> allRows = driver.findElements(By.xpath("//table[@id='employeeTable']//tr"));
for(WebElement row : allRows) {
List<WebElement> cells = row.findElements(By.tagName("td"));
for(WebElement cell : cells) {
System.out.print(cell.getText() + " | ");
}
System.out.println();
}
This prints the entire table row by row and cell by cell.
Reading data is only one part of working with tables. In real test scenarios, testers often need to interact with elements inside table cells. These could be action buttons, hyperlinks, checkboxes, or input fields that trigger workflows such as editing, deleting, or selecting records. Selenium allows direct interaction with these elements once they are located properly.
Below are the most frequent cases.
Tables often contain buttons for actions like “Edit” or “Delete,” links to navigate to a details page, or checkboxes for record selection. The key is to first locate the row of interest and then drill down to the cell containing the interactive element. For example:
WebElement deleteBtn = driver.findElement(
By.xpath("//table[@id='userTable']//tr[td[text()='John']]//button[text()='Delete']")
);
deleteBtn.click();
This finds the row where the cell value is “John” and clicks the Delete button in that row.
Similarly, a checkbox in a particular row can be selected like this:
WebElement checkbox = driver.findElement(
By.xpath("//table[@id='userTable']//tr[td[text()='Alice']]//input[@type='checkbox']")
);
checkbox.click();
This selects the checkbox in the row where the name is “Alice.”
Some applications embed dropdowns or text fields inside tables to allow inline editing or status changes. Testers need to first locate the specific row and column, and then interact with the input element. For example:
WebElement statusDropdown = driver.findElement(
By.xpath("//table[@id='orderTable']//tr[td[text()='Order123']]//select")
);
Select select = new Select(statusDropdown);
select.selectByVisibleText("Shipped");
This locates the dropdown in the row where the order ID is Order123 and changes its value to “Shipped.”
For text input fields:
WebElement inputField = driver.findElement(
By.xpath("//table[@id='orderTable']//tr[td[text()='Order123']]//input[@type='text']")
);
inputField.clear();
inputField.sendKeys("Updated Notes");
This edits the text field for the same row.
Not all web tables are flat structures. Many modern applications use nested or multi-level tables to group related information. A common example is a parent table that lists orders, with each order row expanding into a child table showing item details. Working with such structures requires testers to handle multiple <table> elements inside a single parent row.
The first step is to identify whether the application uses true nested <table> tags or relies on hidden rows that become visible on expansion. Once confirmed, you can chain locators to reach the right table. For example:
WebElement nestedCell = driver.findElement(
By.xpath("//table[@id='mainTable']//tr[td[text()='Order123']]//table[@class='nested']//td[2]")
);
System.out.println(nestedCell.getText());
This locates the nested child table inside the row for Order123 and extracts the value of its second column.
If the nested table appears only after clicking an expand icon, you need to add an interaction step:
driver.findElement(
By.xpath("//table[@id='mainTable']//tr[td[text()='Order123']]//button[@class='expand']")
).click();
WebElement detailTable = driver.findElement(
By.xpath("//table[@id='mainTable']//tr[@class='expanded']//table[@class='nested']")
);
Here, the expand button is clicked first, and then Selenium locates the child table within the expanded row.
Dealing with multi-level structures often requires synchronization because nested content may load asynchronously. In such cases, explicit waits should be used before interacting with the child table.
Large datasets are often split across multiple pages, or updated dynamically as users interact with filters or sorting. For testers, this adds complexity because the required data might not be present in the current view. Verification in such cases means handling both navigation and synchronization.
When a table spans multiple pages, you must iterate through each page until the required data is found. This usually involves clicking a Next button or selecting a page number from pagination controls.
For example:
boolean recordFound = false;
while (!recordFound) {
List<WebElement> rows = driver.findElements(By.xpath("//table[@id='employeeTable']//tr"));
for (WebElement row : rows) {
if (row.getText().contains("Alice")) {
System.out.println("Record found: " + row.getText());
recordFound = true;
break;
}
}
if (!recordFound) {
WebElement nextBtn = driver.findElement(By.id("nextPage"));
if (nextBtn.isEnabled()) {
nextBtn.click();
} else {
break;
}
}
}
This loop searches all pages until the row with “Alice” is found or pagination ends.
Some tables update automatically when filters are applied or when new data is pushed from the backend. These updates may not reload the entire page, so you need to wait for the table contents to change before validating. For example:
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.textToBePresentInElementLocated(
By.xpath("//table[@id='orderTable']//tr[1]/td[2]"), "Shipped")
);
This waits until the first row in the orderTable reflects the updated status “Shipped.”
Dynamic tables may also regenerate their DOM structure, which invalidates old WebElement references. To avoid StaleElementReferenceException, always locate rows or cells after the update has occurred rather than reusing previously stored elements.
Web tables are widely used in applications, and testers need clear methods to read data, interact with elements, and manage cases like nested tables or pagination. Selenium supports these tasks when locators are chosen carefully and updates are handled properly.
To ensure accuracy across environments, tests should also run on real browsers and devices. BrowserStack provides this through instant access to a wide range of browsers, devices, and versions, along with features like parallel execution and local testing. This helps testers validate table interactions in conditions that match real user environments.
Run Selenium Tests on Cloud
Get visual proof, steps to reproduce and technical logs with one click
Continue reading
Try Bird on your next bug - you’ll love it
“Game changer”
Julie, Head of QA
Try Bird later, from your desktop