How can we define array in katalon to save values in for loop

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() + ';'

1 Like

Awesome! Got the expected results. I am curious to know why certain things were done in the code.

  1. Another def method was created inside the def columnNames method. Why did we do that and why did we assign its value = ’ ’
  2. 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?
  3. 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.

1 Like

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() + ';'
}
1 Like

Ah, my bad.
retvalue += headers[i].getText() was my mistake.
retvalue += e.getText() is correct.

1 Like

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?