Problem Statement: Dynamic Tables, wait , + Stability and Reusability
Most of the time when handling dynamic data tables, tables where the rows and columns can be dynamically populated based on some search queries or any other calculations there is a need to read a particular column value and then act based on the result. There are two challenges here
- As table rows and columns get populated dynamically we need to handle them by using some explicit wait conditions
- Over a period of time similar situations might arise in other pages or similar projects, how to start putting these functions into a common utility or wrapper method classes to increase stability and re-usability
Problem case study
The case study is taken from the following website
The page shows the following table.
On entering the minimum and maximum age it shows the data as per the age range. Or when the column is clicked it sorts the data.
So let us define two test scenarios from this case study.
- Check whether the age range is working fine or not (Use age range 37-40)
- Check whether the sorting is working fine or not (Sort on age column and see if it working or not)
Let us start building our solution.
Step 1 – Locator strategy
Few things to start with
- We are using Google Chrome as the choice of browser and its DOM inspector to locate our elements.
- We have opened the website in chrome and used the right click ->inspect on the age first column value and then copied the xpath and used ctrl-f to check the xpath in the device tool bar on chrome.
- The resulting image looks like below and the xpath provided by chrome browser is //*[@id=”example”]/tbody/tr/td
The DOM structure looks like below
The tbody/tr/td is there, table has rows and columns.
If we want to fetch all the columns, we will be using the following xpath
Or we could have also used below
Both these xpaths are able to fetch all the column 4 values.
Please look at the below screen shot, it shows that instead of single element the xpath is able to locate all the 10 column values for the 4th column.
We would also need locators for the age range input elements.
- A) //*[@id=”min”]
- B) //*[@id=”max”]
Step 2 – wait strategy and part A of our solution code
If we only have the locator and if we were to use findElement with this locator it might fail until we let the table populate with the new elements when the age range script comes into action.
One way is to use Thread.sleep() but it is not a recommended way for automation. We do not ever want to use hard coded waits. We would rather use an explicit wait with the condition that all the elements for the columns are visible, once that happens we will be able to fetch the relevant values.
Following lines of code will do the magic for us. DynamicDataTablePartA.java
The full codebase with part A of the solution can be taken from the following dropboxfolder for the file.
Step 3 – Extending the code to check if the age range is proper or not
We could get the list of columns and the values of the column printed on console in the previous code. We need to check whether the values are within the range or not.
We will extract the integer values and check whether it is in range or not.
Following piece of code will help us checkDynamicDataTablePartB.java
CODE BASE can be downloaded from the below URL
Step 4 – Click on the sort and see of the sort is working or not
Let us proceed on our task to further click on the column and see if the sorting works or not. The table looks like below. When we click on the Age, it sorts on the age.
Before click image is below
After click on the age column the image is as below
From our code perspective, we need to add the following part in our script
- Identify the locator for the Age column header element, click on it
- Store the column 4 values again into two array list, one where we will use Java sort (use Collections.sort) and one as it is. We will then compare the two lists to see if the sorting has been done properly or not.
Here is the code DynamicDataTablePartC.java
The updated file with the new code is
Step 5 – adding a Wrapper Method class
It will be a good idea to handle the common wait related issues in a common wrapper class.
- Many a times the elements when we try to click fails – if the element is not clickable
- Errors may also occur when we try to sendKeys to an element
- We are already handling our list by defining a wait for all elements to be visible, it will be better to create a common method which can be called whenever we want to get a list of elements.
This ensures that the code can be reused in other places and our automation code remains stable all across the enterprise use. This is how a strong enterprise wide framework utility classes and wrap around classes can evolve.
Here are the three sample wrapper method functions. WrapperMethods
Our code for DynamicTableHanding will now change, it will be calling the respective methods. We can refactor further – specially if we have repeated need for comparing the values or checking if the sorting is required or not. For this blog we are trying to wrap around the driver methods to make them more stable and dependable.
Here is the final code which is calling our wrapper methods FinalCode
The final code for both the files can be downloaded from the below URL’s
CP-SAT is the number 1 globally recognized selenium certificate. If you know selenium and you are not CP-SAT you are definitely missing something.
CP-SAT and Agile Testing Alliance is always looking for Selenium evangelists who can help in curating such blogs, help in curating conferences and our community initiatives like CPSATday and Meetups.
ATA is helping teams transform. If you have testing teams who do not know selenium automation, ATA will help you transform.
Please visit the CP-SAT Page below for more details
The above blog is curated base on inputs by Adi Garg and Narendra Gupta.
If you have suggestions please get in touch with us through our linkedIn page.