Hi tried to get the values from table and getting successfully. Now i want to store these values in variable during for loop. Please share with me array syntax to use in my script.
Have a look at this sample code:
kazurayam said:
Have a look at this sample code:
https://www.katalon.com/resources-center/tutorials/handle-web-tables/
This is for List… any possibility to maintain the array?
You want array rather than List. OK. It is just possible.
I rewrote the Example.1 of https://www.katalon.com/resources-center/tutorials/handle-web-tables/ .
At first, just a rewrite the Example1. I did rewriting because the coding style of the original code in the URL looks a bit odd to me.
import org.openqa.selenium.By as By
import org.openqa.selenium.WebDriver as WebDriver
import org.openqa.selenium.WebElement as WebElement
import com.kms.katalon.core.webui.driver.DriverFactory as DriverFactory
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
/**
* reproducing the Example.1 in
* https://www.katalon.com/resources-center/tutorials/handle-web-tables/
*
*/
WebUI.openBrowser('')
WebUI.setViewPortSize(703, 347)
WebUI.navigateToUrl('http://demoaut-mimic.kazurayam.com/18107_testbed.html')
WebDriver driver = DriverFactory.getWebDriver()
// To locate table
WebElement table = driver.findElement(By.xpath('//table/tbody'))
// To locate rows of table it will capture all the rows available in the table
List<WebElement> rowsInTable = table.findElements(By.tagName('tr'))
// To calculate number of rows in the table
int rowsCount = rowsInTable.size()
WebUI.comment("rowsCount=${rowsCount}")
// Iterate over all the rows of the table
for (int r = 0; r < rowsCount; r++) {
// To locate columns(cells) of that specific row
List<WebElement> columnsInRow = rowsInTable.get(r).findElements(By.tagName('td'))
// To calculate number of columns in that specific row
int columnsCount = columnsInRow.size()
WebUI.comment("Number of cells in row ${r} are ${columnsCount}")
// Iterate over the cells of that specifc row
for (int c = 0; c < columnsCount; c++) {
// Retrieve text from each cell
String cellText = columnsInRow.get(c).getText()
WebUI.comment("Cell value of (${r},${c}) is '${cellText}'")
}
}
WebUI.closeBrowser()
Then a rewrite with arrays.
import org.openqa.selenium.By as By
import org.openqa.selenium.WebDriver as WebDriver
import org.openqa.selenium.WebElement as WebElement
import com.kms.katalon.core.webui.driver.DriverFactory as DriverFactory
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
/**
* reproducing the Example.1 in
* https://www.katalon.com/resources-center/tutorials/handle-web-tables/
*
* using arrays rather than List
*/
WebUI.openBrowser('')
WebUI.setViewPortSize(703, 347)
WebUI.navigateToUrl('http://demoaut-mimic.kazurayam.com/18107_testbed.html')
WebDriver driver = DriverFactory.getWebDriver()
// To locate table
WebElement table = driver.findElement(By.xpath('//table/tbody'))
// To locate rows of table it will capture all the rows available in the table
WebElement[] rowsInTable = table.findElements(By.tagName('tr')) as WebElement[]
// To calculate number of rows in the table
int rowsCount = rowsInTable.length
WebUI.comment("rowsCount=${rowsCount}")
// Iterate over all the rows of the table
for (int r = 0; r < rowsCount; r++) {
// To locate columns(cells) of that specific row
WebElement[] columnsInRow = rowsInTable[r].findElements(By.tagName('td')) as WebElement[]
// To calculate number of columns in that specific row
int columnsCount = columnsInRow.length
WebUI.comment("Number of cells in row ${r} are ${columnsCount}")
// Iterate over the cells of that specifc row
for (int c = 0; c < columnsCount; c++) {
// Retrieve text from each cell
String cellText = columnsInRow[c].getText()
WebUI.comment("Cell value of (${r},${c}) is '${cellText}'")
}
}
WebUI.closeBrowser()
Difference of List and array comes up only when you want to add/delete an entry. With List, adding an entry is a breeze. With array, adding an entry is a cumbersome task. In the above code we are not adding entries so that you would find very little difference between the two. Almost all of Java/Groovy APIs prefer List to array, so that you need to learn the List anyway.
In Groovy, a List is converted into an array by “as Type[]” syntax. See the following article:
Hi there,
I am also trying to store the values in a list or an array and then would like to print those stored values from the test case. The following is my example:
class FavoritesKeywords {
// Printing all the headers of the Favorites table assuming first row as a header
@Keyword
def allHeadersFavorites(){
// creating a variable 'driver' and assigning its value
WebDriver driver = DriverFactory.getWebDriver()
// get the first row in the headers from the table and store this in a variable ‘th’ of type web element.
WebElement th = driver.findElement(By.xpath("//table[@class='cart']//thead"))
//Get all the headers with tag name ‘th’ and store all the elements in a list of web elements.
//Now all the elements with tag ‘th’ are stored in ‘headers’ list.
List<WebElement> headers = th.findElements(By.tagName('th'))
//storing the header size so that it can be used in the test for printing
return headers.size()
}
@Keyword
def columnNames(){
WebDriver driver = DriverFactory.getWebDriver()
WebElement th = driver.findElement(By.xpath("//table[@class='cart']//thead"))
List<WebElement> headers = th.findElements(By.tagName('th'))
//traversing through the column headers, index 0 will be the first column name and so on
for (int i = 0; (i < headers.size); i++) {
return = headers[i].getText()
}
}
This is the test case I am using to print the number of headers and the names of the headers using the Keywords above:
int numheaders
String columns
WebUI.callTestCase(findTestCase('Smoke Testing/Login'), [:], FailureHandling.STOP_ON_FAILURE)
WebUI.click(findTestObject('Master Object Repository/B2B - My_CES Dropdown/My CES - B2B'))
WebUI.click(findTestObject('Master Object Repository/B2B - My_CES Dropdown/Favorites - B2B'))
numheaders = CustomKeywords.'com.ces.cesonline.favorites.FavoritesKeywords.allHeadersFavorites'()
columns = CustomKeywords.'com.ces.cesonline.favorites.FavoritesKeywords.columnNames'()
if (numheaders > 0){
println ('No. of Headers: ' + numheaders)
println (columns)
}
else
println('Favorites is empty!')
WebUI.closeBrowser()
After running the test, it correctly prints out ‘No.of Headers: 9’, it only prints one header/column name instead of all the 9 names. Could you tell me what is wrong with my code?
Thanks.
This one line looks erroneous.
How about this?
def retvalue = ''
for (WebElement e : headers) {
retvalue += e.getText() + '; '
}
return retvalue
I tried your suggestion but got the following error for the for loop
Multiple markers at this line
- Groovy:expecting EOF, found ‘for’ @ line 85,
column 3.
- Groovy:unexpected token: for @ line 85,
column 3.
This is what my code looks like:
@Keyword
def retvalue = ''
WebDriver driver = DriverFactory.getWebDriver()
WebElement th = driver.findElement(By.xpath("//table[@class='cart']//thead"))
List<WebElement> headers = th.findElements(By.tagName('th'))
//traversing through the column headers, index 0 will be the first column name and so on
for (WebElement e : headers){
retvalue += e.getText() + ';'
}
return retvalue
class FavoritesKeywords {
@Keyword
def columnNames(){
WebDriver driver = DriverFactory.getWebDriver()
WebElement th = driver.findElement(By.xpath("//table[@class='cart']//thead"))
List<WebElement> headers = th.findElements(By.tagName('th'))
def retValue = ''
for (WebElement e : headers) {
retValue += e.getText() + ';'
}
return retValue
}
7 Aug 2019 I corrected my bad:
retvalue += headers[i].getText() + ';'
=> retvalue += e.getText() + ';'
Awesome! Got the expected results. I am curious to know why certain things were done in the code.
- Another def method was created inside the def columnNames method. Why did we do that and why did we assign its value = ’ ’
- I did not understand your for loop since I was used to the standard for loop which I had in my original code. What does (WebElement e : headers) do?
- I got the results with retvalue += e.getText() + ‘;’ instead of retvalue += headers[i].getText() + ‘;’
What is the difference between the two?
Thanks
The def
keyword in Groovy language does not specifically mean “defining a method”. It defines some identifier of certain data type.
Have a look at the Groovy language document
https://groovy-lang.org/syntax.html#_identifiers
Here are a few examples of valid identifiers (here, variable names):
def name
def item3
def with_underscore
def $dollarStart
I can safely rewrite the above snippet as follows:
class FavoritesKeywords {
@Keyword
String columnNames() {
WebDriver driver = DriverFactory.getWebDriver()
WebElement th = driver.findElement(By.xpath("//table[@class='cart']//thead"))
List<WebElement> headers = th.findElements(By.tagName('th'))
String retValue = ''
for (WebElement e : headers) {
retValue += e.getText() + ';'
}
return retValue
}
}
Please note, here I refrained from def
keyword of Groovy. The above code explicitly declares that the method columnNames
returns a value of type java.lang.String
.
This is a valid Groovy class, and at the same time, is a valid Java class.
As for for (WebElement e : headers)
syntax, have a look at the Groovy language document:
https://groovy-lang.org/semantics.html#_for_in_loop
Groovy also supports the Java colon variation with colons:
for (char c : text) {}
, where the type of the variable is mandatory.
Yes, I carelessly used Java 5 syntax here. See also
https://www.cis.upenn.edu/~matuszek/General/JavaSyntax/enhanced-for-loops.html
If I want to be Groovy native, I can safely rewrite it to:
def retValue = ''
for (e in headers) {
retValue += e.getText() + ';'
}
Ah, my bad.
retvalue += headers[i].getText()
was my mistake.
retvalue += e.getText()
is correct.
Thanks for the explanation. Suppose I do not want to use def or String and want to store all the column names in a list or an array and then print those out. Is it possible to do that?