Custom Keywords with dynamic objects

Hello,

Is there any reference or could help me with my concern. So here, I created a custom keywords where I can reuse for my repeated test case which is to validate the values of the dropdown, and all of my test objects are dynamic or Parameterize Web Test Objects. My goal is I have one script in the custom keywords to validate the values of dropdown and it will call on my different test cases. My problem now is I don’t know how can I write my script.

This is my code now.

Custom keywords
@Keyword
def validateDdown (List list, String object) {

	for (int count = 0 ; count<list.size(); count++) {
		
		WebUI.verifyElementPresent(findTestObject('object'), 5)
		System.out.println("Filter Field " + list.get(count) + " is diplayed")
		
	}	
	
} 

Test Case

def validateWorkflowValues(){

	WebUI.click(findTestObject('Test Ddown1/ddown_Workflow'))
	CustomKeywords.'validateDropDown.validateDdown'(["Test 1","Test 2","Test 3"],findTestObject('Test and Ddown1/ddown_workFlowSelect',['selected']))

This is the xpath of my dropdown object:
(//div[contains(text(),‘${selected}’)])[1]

This is my original script before I switch it into custom keywords, and I have this 5 script into my test case just validate 5 dropdown.

Test Case 1: Workflow dropdown
/*List workfFlowList = [
“Test 1”,
“Test 2”,
“Test 3”
]

	for (int i=0; i<workfFlowList.size(); i++) {

		WebUI.verifyElementPresent(findTestObject('Test Object /ddown_workFlowSelect',[ 'selected' : workfFlowList.get(i)]), 5)

		System.out.println("Filter Field " + workfFlowList.get(i) + " is diplayed")
	}*/

Test Case 2 Type List Dropdown
List testTypeList = [
“Type List 1”,
“Type List 2”
]

	WebUI.click(findTestObject('Test Typelist/ddown_TestType'))


	for (int count=0; count<testTypeList.size(); count++) {
		WebUI.verifyElementPresent(findTestObject('Test Typelist/ddown_testTypeSelect',[ 'selectTest' : testTypeList.get(count)]), 5)
		System.out.println("Filter Field " + testTypeList.get(count) + " is diplayed")
	}

Please use the Code Formatting syntax in your post to make it better readable.

1 Like

We (guys in the forum) can’t find how you can write your script because you did not told us (or neglected) the full package name and the class name of your Keyword.

Hi @kazurayam apologize, here is my screenshots. Hope this helps.

Custom Keyword script

Groovy Test Case

This is my groovy test case before I switch it to custom keywords.

In your “validateDdown” method (Keyword), you have parameters of List<String> list and String, however, you are sending the method a List<String> list and a TestObject. You will have to change the parameter of the calling statement otherwise you will get a “MissingMethodException”?

And, if you are sending the TestObject, you may not need the List<String> list reference in your parameters. You will have to decide which way to set up your method.

This code fragment looks strange.

A Custom Keyword MUST be a Groovy class in the Keywords folder. You must create a package, and a Groovy class in which you would locat a method. Possibly you would want to annotated it with @Keyword.

Are you aware of this? Review the manual https://docs.katalon.com/docs/legacy/katalon-studio-enterprise/extend-katalon-studio/custom-keywords/introduction-to-custom-keywords

I guess you have the def validateDdown() method coded somewhere in the Test Cases folder, don’t you? If it is the case, then the function def validateDdown() is a Groovy function in a Groovy Script (=Test Case). The function would work fine. But it is NOT called as a Keyword in Katalon term. You should not annotate the function with a @Keyword.

Your “Test Case” has a def like:

def someFunctionName() {
   ...
}

This looks strange to me. A usual Katalon Test case is a Groovy Script; it does not usually starts with a def statement. You seem to be using Katalon Studio in a unusual way.

In which folder do you have the Test Case? How is the file named?

Or, it could be a case that you showed us partial code fragments which were trancated from a large source code set. Can you share the whole lines of the script without trimming at all?

Anyway, it seems you haven’t showed a overall picture of your project. I still do not understand what you are doing.

Hi @kazurayam Sorry for the confusion, I created my custom keywords code in the keywords folder, which I forgot to include into my screenshot.

Then my script for my test case, I created in the Include > Scripts > Groovy folders, see screenshot below. Yup I only shown on my partial code on my specific test cases.

This is my full source code on my script groovy folders

import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject

import com.kms.katalon.core.annotation.Keyword
import com.kms.katalon.core.checkpoint.Checkpoint
import com.kms.katalon.core.checkpoint.CheckpointFactory
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import com.kms.katalon.core.model.FailureHandling
import com.kms.katalon.core.testcase.TestCase
import com.kms.katalon.core.testcase.TestCaseFactory
import com.kms.katalon.core.testdata.TestData
import com.kms.katalon.core.testdata.TestDataFactory
import com.kms.katalon.core.testobject.ObjectRepository
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI

import internal.GlobalVariable

import org.openqa.selenium.WebElement
import org.openqa.selenium.WebDriver
import org.openqa.selenium.By

import com.kms.katalon.core.mobile.keyword.internal.MobileDriverFactory
import com.kms.katalon.core.webui.driver.DriverFactory

import com.kms.katalon.core.testobject.RequestObject
import com.kms.katalon.core.testobject.ResponseObject
import com.kms.katalon.core.testobject.ConditionType
import com.kms.katalon.core.testobject.TestObjectProperty

import com.kms.katalon.core.mobile.helper.MobileElementCommonHelper
import com.kms.katalon.core.util.KeywordUtil

import com.kms.katalon.core.webui.exception.WebElementNotFoundException

import cucumber.api.java.en.And
import cucumber.api.java.en.Given
import cucumber.api.java.en.Then
import cucumber.api.java.en.When



class addNewTest {

	@And ("User clicks the Admin")
	def clicksAdmin () {
		if (WebUI.verifyElementPresent(findTestObject('Object Repository/homePage/ituroLogo'), 10)==true) {
			WebUI.click(findTestObject('Object Repository/homePage/btn_Admin'))
			println 'Succesffully click the Admin'
		}
		else {
			println 'Unable to click Admin'
		}
	}

	@And ("Click Test & Diagnostics")
	def clickTestandDiagnostics(){

		if (WebUI.verifyElementPresent(findTestObject('Object Repository/Admin Sub Menu/header_DataManagement'), 10)==true) {
			WebUI.click(findTestObject('Object Repository/Admin Sub Menu/btn_TestDiagnostics'))
		}
		else {
			println 'Unable to click Test & Diagnostics'
		}
	}

	


	@And ("Click Add new and validate worklist dropdown")


	def validateWorkflowValues(){

		WebUI.click(findTestObject('Test and Diagnostics/ddown_Workflow'))
		CustomKeywords.'validateDropDown.validateDdown'(["Test 1","Test 2","Test 3"],findTestObject('Test and Diagnostics/ddown_workFlowSelect',['selected']))
		


		WebUI.click(findTestObject('Test and Diagnostics/ddown_workFlowSelect', ['selected' : 'Test 1']))

		List <String>testTypeList = [
			"Type List 1",
			"Type List 2"
		]

		WebUI.click(findTestObject('Test and Diagnostics/ddown_TestType'))


		for (int count=0; count<testTypeList.size(); count++) {
			WebUI.verifyElementPresent(findTestObject('Test and Diagnostics/ddown_testTypeSelect',[ 'selectTest' : testTypeList.get(count)]), 5)
			System.out.println("Filter Field " + testTypeList.get(count) + " is diplayed")
		}
		WebUI.click(findTestObject('Test and Diagnostics/ddown_testTypeSelect', [ 'selectTest' : 'Type List 1']))

		List <String> testRecipient = [
			"Male",
			"Female",
			"Both"
		]
		WebUI.click(findTestObject('Test and Diagnostics/ddown_testRecipient'))


		for (int j = 0; j<testRecipient.size(); j++) {

			WebUI.verifyElementPresent(findTestObject('Test and Diagnostics/ddown_testRecipientSelect',[ 'testRecipient' : testRecipient.get(j)]), 5)
			System.out.println("Filter Field " + testRecipient.get(j) + " is diplayed")
		}
		WebUI.click(findTestObject('Test and Diagnostics/ddown_testRecipientSelect', ['testRecipient': 'Male']))
	}
}

Source code for my Custom Keywords
import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import static com.kms.katalon.core.testobject.ObjectRepository.findWindowsObject

import com.kms.katalon.core.annotation.Keyword
import com.kms.katalon.core.checkpoint.Checkpoint
import com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords as CucumberKW
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import com.kms.katalon.core.model.FailureHandling
import com.kms.katalon.core.testcase.TestCase
import com.kms.katalon.core.testdata.TestData
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.windows.keyword.WindowsBuiltinKeywords as Windows

import internal.GlobalVariable

public class validateDropDown {

	@Keyword
	def validateDdown (List <String> list, String object) {

		for (int count = 0 ; count<list.size(); count++) {


			WebUI.verifyElementPresent(findTestObject('object'), 5)
			System.out.println("Filter Field " + list.get(count) + " is diplayed")
		}
	}
}

My Goal is I have 1 code in the custom keywords to validate the values of the dropdown, then I will reuse it on my repeated script.

This sentence confuses me. I do not understand this.

We do not call the code in the Include > Scripts > Groovy folder as “Test Case”. The code in the Include > Scripts > Groovy folder is just a Groovy class. You have no way in Katalon Studio GUI to run it immediately.

If you want to create a “Test Case”, you must make it in the “Test Cases” folder. The code must NOT be a Groovy class. A Test Case must be a Groovy script. No class keyword should be there.

By the green righ arrow button
スクリーンショット 2022-12-21 17.12.39 in Katalon Studio GUI, you can run a Test Case. But you can NOT immediately run a class in the Keywords folder and Include folder.

You can create a Test Case script in the “Test Cases” folder, which calls a Groovy class located either in Keywords folder or Include/scripts/groovy folder.

Hi @kazurayam I can run my Groovy script using the Gherkins method, but I am encountering an issue when I reach the Click Add new and validate worklist dropdown step, and it’s because of some code issue in my custom keyword and groovy script. I will try to figure out my concern. Thank you for the assistance!

You should have stated this first.

If you are writing Ghekins code, you do not need to place your code in the Keywords folder at all.
You can place all your classess in the Include/scripts/groovy folder if you like.

1 Like

Ahh I see, do you have any reference where I can use as my reference on how to write a code properly using the Gherkins method?

No, I do not have good Gherkins experience.
I do not think that there is any good documetation in the Katalon docs either.
It seems that there aren’t many people who use Gherkins in Katalon.

Sorry one more thing, What is the best approach for when I reuse existing keywords for the multiple test cases for example every scenario has Login? Most of my research for this case, it’s recommended to use custom keywords.

Example here, I tried ask chatopen ai and this is the response about custom keywords hehe. That’s why I want to create custom keywords, so I can reuse it into my mulitple test case. But I’ll try with other approach

Yes, you should create some custom Groovy classes. You have 2 options where to locate your classes.

It can be a class located in Keywords folder. If you want to use the methods in the Manual mode, you should annotate the method with @Keyword. If you do not use the Manua mode, you do not need @Keyword annotation at all.

It can also be a class located in Includes/scripts/groovy foler.

The classes in the Keywords are usually called as Keyword. The classes in the Include folder are not called Keyword. But the fact is, the classes of both folders are loaded in the runtime classpath for Test Cases and Gherkins scripts. There aren’t big differences at runtime.

Possibly, the only practical difference is that the Manual mode of Test Case editor will look into the Keywords folder to lookup “custom keywords” to show in the GUI. The Manual mode of Test Case editor will not look into the Includes/scripts/groovy folder at all.

1 Like

Thank you @kazurayam !