Created TestObject Not Working Correctly - Can't getText From It

How do I create a usable Web Test Object through scripting that will then link to an actual web page object in such a way that I can then gather information from its other property values.
I’ve attempted the addProperty option to give a created TestObject the correct “xpath”, but that doesn’t seem to link the TestObject to the actual web page object for later use.

I know that the web page objects that I want to look through have a parent object with a unique ID. EX: “//tr[@data-message-id=’###’]/td[2]”
Using MailCatcher:
The parent object is an individual email (in a table row – tr) and it has four children objects (each in a table data – td): from address, to address, subject, & date received
The parent object is also associated to an iframe that will display the body text of the email.

I would like to get the most recently received email and confirm that its 2nd, 3rd, & 4th children each have specific text, so that I know I have the correct email.
Unfortunately, I can’t just use the date received timestamp in the search box at the top, because the time that the test case initiates the email send is not the same as when that email is received.
Also, there may be other emails sent at similar times, which is why I would need to be able to look through multiple emails to find the correct one.

After I’ve found the correct email, I will then need to get some text (a url link) from the body of the email, which is in an iframe, and use that text to navigate to another page to complete the testing in full.
The URL link will change each time the test case is executed, but it will always be surrounded by the same text.

Brief layout of the steps I’m trying to accomplish:
I’m trying to figure out how to get Katalon to create a web object on the fly, based on looking through many similar objects from an xpath derivative to get confirmation information from a few of its children.

  1. Cycle through email objects based on numbered “data-message-id”s until desired email is found.
    EX: “//tr[@data-message-id=’###’]/td[2]”
  2. Get text from three of its children to confirm it’s the correct message.
    EX: “//tr[@data-message-id=’###’]/td[2]”
    EX: “//tr[@data-message-id=’###’]/td[3]”
    EX: “//tr[@data-message-id=’###’]/td[4]”
  3. Create a usable Test Object based on the ID.
  4. Click on that created Test Object on the web page to display body text in the iframe.
  5. Use a specific substring from the text in the associated iframe message body to continue the testing process.

Error being generated at this line from the CODE below: sToAddress = WebUI.getText(findTestObject('toEmailID'))

ERROR

=============== ROOT CAUSE =====================
Caused by: java.lang.IllegalArgumentException: Object is null
================================================

08-06-2020 01:56:41 PM sToAddress = getText(findTestObject("toEmailID"))

Elapsed time: 0.157s

Unable to get text of object (Root cause: com.kms.katalon.core.exception.StepFailedException: Unable to get text of object
	at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.stepFailed(WebUIKeywordMain.groovy:64)
	at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.runKeyword(WebUIKeywordMain.groovy:26)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword.getText(GetTextKeyword.groovy:88)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword.execute(GetTextKeyword.groovy:67)
	at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:72)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.getText(WebUiBuiltInKeywords.groovy:914)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$getText$5.call(Unknown Source)
	at DeactivateUser.run(DeactivateUser:106)
	at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
	at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
	at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:337)
	at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:328)
	at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:307)
	at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:299)
	at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:233)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:114)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:105)
	at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
	at TempTestCase1596740177555.run(TempTestCase1596740177555.groovy:25)
Caused by: java.lang.IllegalArgumentException: Object is null
	at com.kms.katalon.core.helper.KeywordHelper.checkTestObjectParameter(KeywordHelper.java:33)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword$_getText_closure1.doCall(GetTextKeyword.groovy:76)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword$_getText_closure1.call(GetTextKeyword.groovy)
	at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.runKeyword(WebUIKeywordMain.groovy:20)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword.getText(GetTextKeyword.groovy:88)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword.execute(GetTextKeyword.groovy:67)
	at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:72)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.getText(WebUiBuiltInKeywords.groovy:914)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$getText$5.call(Unknown Source)
	at Script1595625123189.run(Script1595625123189.groovy:106)
	... 11 more
)

CODE

Boolean bEmailFound = false
String sToAddress
String sSubject
String sReceived
String sDesiredText = 'Something Important'

def date = new Date()
sdfDate = new SimpleDateFormat('ddddd, dd mmm yyyy')
sdfh = new SimpleDateFormat('h')
sdfm = new SimpleDateFormat('mm')

String sDate = sdfDate.format(date)
String sHour = sdfh.format(date)
String sMinute = sdfm.format(date)
int iHour = sHour.toInteger()
int iMinute = sMinute.toInteger()

TestObject tobEmail = new TestObject('toEmailID')
TestObject tobSubject = new TestObject('toSubjectID')
TestObject tobTimeStamp = new TestObject('toTimeStampID')
tobEmail.addProperty('xpath', ConditionType.EQUALS, "//tr[@data-message-id='20']/td[2]")
tobSubject.addProperty('xpath', ConditionType.EQUALS, "//tr[@data-message-id='20']/td[3]")
tobTimeStamp.addProperty('xpath', ConditionType.EQUALS, "//tr[@data-message-id='20']/td[4]")

for (int i = 20; i < 1000; i++) {
	tobEmail = WebUI.modifyObjectProperty(tobEmail, 'xpath', 'equals', "//tr[@data-message-id='" + i + "']/td[2]", false)
	tobSubject = WebUI.modifyObjectProperty(tobSubject, 'xpath', 'equals', "//tr[@data-message-id='" + i + "']/td[3]", false)
	tobTimeStamp = WebUI.modifyObjectProperty(tobTimeStamp, 'xpath', 'equals', "//tr[@data-message-id='" + i + "']/td[4]", false)


	sToAddress = WebUI.getText(findTestObject('toEmailID'))
	sSubject = WebUI.getText(findTestObject('toSubjectID'))
	sReceived = WebUI.getText(findTestObject('toTimeStampID'))
	WebUI.comment("getText with findTestObject:  $sToAddress     $sSubject     $sReceived")

	if (sToAddress.contains('email@address.com')) {
		if (sSubject.contains('Expected subject')) {
			if (sReceived.contains("$sDate $iHour:$iMinute")) {
				bEmailFound = true
			}

			iMinute++
			if (sReceived.contains("$sDate $iHour:$iMinute")) {
				bEmailFound = true
			}

			iHour++
			iMinute = 0
			if (sReceived.contains("$sDate $iHour:$iMinute")) {
				bEmailFound = true
			}
		}
	}

	if (bEmailFound == true) {
		WebUI.click(findTestObject('Page_MailCatcher/td_ToAddress'))

		WebUI.waitForElementPresent(findTestObject('Page_MailCatcher/a_Plain text Tab'), 30)
		WebUI.waitForElementClickable(findTestObject('Page_MailCatcher/a_Plain text Tab'), 30)
		WebUI.click(findTestObject('Page_MailCatcher/a_Plain text Tab'))

		WebUI.verifyTextPresent("Text To Extract URL From: $sDesiredText", true)
	}

	// Navigate to URL and finish test case

}

If you’ve created a Test Object toMyObject, you don’t need to use findTestObject to get it - you already have it (findTestObject is used to look through the Object Repository).

sToAddress = WebUI.getText(tobEmail)

Thank you. I was thinking that might be a possibility.

Unfortunately, I tried it and it didn’t work either.

CODE

	sToAddress = WebUI.getText(tobEmail)
	WebUI.comment("getText with findTestObject:  $sToAddress")

ERROR

=============== ROOT CAUSE =====================
Caused by: com.kms.katalon.core.webui.exception.WebElementNotFoundException: Web element with id: 'toEmailID' located by 'By.xpath: ' not found
================================================

08-07-2020 08:12:17 AM sToAddress = getText(tobEmail)

Elapsed time: 43.401s

Unable to get text of object 'toEmailID' (Root cause: com.kms.katalon.core.exception.StepFailedException: Unable to get text of object 'toEmailID'
	at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.stepFailed(WebUIKeywordMain.groovy:64)
	at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.runKeyword(WebUIKeywordMain.groovy:26)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword.getText(GetTextKeyword.groovy:88)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword.execute(GetTextKeyword.groovy:67)
	at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:72)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.getText(WebUiBuiltInKeywords.groovy:914)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$getText$5.call(Unknown Source)
	at DeactivateUser.run(DeactivateUser:106)
	at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
	at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
	at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:337)
	at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:328)
	at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:307)
	at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:299)
	at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:233)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:114)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:105)
	at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
	at TempTestCase1596805914393.run(TempTestCase1596805914393.groovy:25)
Caused by: com.kms.katalon.core.webui.exception.WebElementNotFoundException: Web element with id: 'toEmailID' located by 'By.xpath: ' not found
	at com.kms.katalon.core.webui.common.WebUiCommonHelper.findWebElement(WebUiCommonHelper.java:1154)
	at com.kms.katalon.core.webui.keyword.internal.WebUIAbstractKeyword.findWebElement(WebUIAbstractKeyword.groovy:27)
	at com.kms.katalon.core.webui.keyword.internal.WebUIAbstractKeyword.findWebElement(WebUIAbstractKeyword.groovy:26)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword$_getText_closure1.doCall(GetTextKeyword.groovy:78)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword$_getText_closure1.call(GetTextKeyword.groovy)
	at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.runKeyword(WebUIKeywordMain.groovy:20)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword.getText(GetTextKeyword.groovy:88)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword.execute(GetTextKeyword.groovy:67)
	at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:72)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.getText(WebUiBuiltInKeywords.groovy:914)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$getText$5.call(Unknown Source)
	at Script1595625123189.run(Script1595625123189.groovy:106)
	... 11 more
)

For the time being, start small. Put your test case aside and start a new one. Target the same page but build ONE test object and prove that works. THEN go back to the original page and fix whatever is broken.

Advice: use something like makeTO to build your Test Objects. You can change makeTO to use xpath if you prefer.

I’m sorry. I’m having a bit of trouble understanding.

Are you recommending something like the following as a proof of concept in a brand new test case before applying to the one I’m trying to get working?

@Keyword
static TestObject makeTO(String xpath) {
	TestObject to = new TestObject()
	to.addProperty("xpath", ConditionType.EQUALS, xpath)
	return to
}

If that is the creation part necessary, how then do I pass it the xpath needed and then extract the text when running?

TestObject tobEmail = new TestObject.makeTO("//tr[@data-message-id='20']/td[2]")
import static blah.blah.* // your keyword package to get makeTO

TestObject tobEmail = makeTO("//tr[@data-message-id='20']/td[2]")

WebUI.click(tobEmail) // or whatever

Thank you much for your help and patience!

I’ve made progress with your help, but am now stuck on trying to loop through the objects by changing their xpaths. The first three lines of the code below work just fine. It errors out in the for loop on the sToAddress = WebUI.getText(tobEmail) line with the error below.

CODE

TestObject tobEmail = makeTO("//tr[@data-message-id='20']/td[2]")
sToAddress = WebUI.getText(tobEmail)
WebUI.comment("getText with findTestObject:  $sToAddress")

for (int i = 20; i < 1000; i++) {
	sXPath = "//tr[@data-message-id='" + i + "']/td[2]"
	tobEmail = WebUI.modifyObjectProperty(tobEmail, 'xpath', 'equals', sXPath, false)
	sToAddress = WebUI.getText(tobEmail)
	WebUI.comment("getText with findTestObject:  $sToAddress")
}

ERROR

=============== ROOT CAUSE =====================
Caused by: com.kms.katalon.core.webui.exception.WebElementNotFoundException: Web element with id: '' located by 'By.xpath: ' not found
================================================

08-07-2020 03:28:17 PM Test Cases/DELcreateTO

Elapsed time: 58.045s

Test Cases/DELcreateTO FAILED.
Reason:
com.kms.katalon.core.exception.StepFailedException: Unable to get text of object ''
	at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.stepFailed(WebUIKeywordMain.groovy:64)
	at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.runKeyword(WebUIKeywordMain.groovy:26)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword.getText(GetTextKeyword.groovy:88)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword.execute(GetTextKeyword.groovy:67)
	at com.kms.katalon.core.keyword.internal.KeywordExecutor.executeKeywordForPlatform(KeywordExecutor.groovy:72)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords.getText(WebUiBuiltInKeywords.groovy:914)
	at com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords$getText$4.call(Unknown Source)
	at DELcreateTO.run(DELcreateTO:51)
	at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
	at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
	at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:337)
	at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:328)
	at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:307)
	at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:299)
	at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:233)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:114)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:105)
	at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
	at TempTestCase1596832095704.run(TempTestCase1596832095704.groovy:25)
Caused by: com.kms.katalon.core.webui.exception.WebElementNotFoundException: Web element with id: '' located by 'By.xpath: ' not found
	at com.kms.katalon.core.webui.common.WebUiCommonHelper.findWebElement(WebUiCommonHelper.java:1154)
	at com.kms.katalon.core.webui.keyword.internal.WebUIAbstractKeyword.findWebElement(WebUIAbstractKeyword.groovy:27)
	at com.kms.katalon.core.webui.keyword.internal.WebUIAbstractKeyword.findWebElement(WebUIAbstractKeyword.groovy:26)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword$_getText_closure1.doCall(GetTextKeyword.groovy:78)
	at com.kms.katalon.core.webui.keyword.builtin.GetTextKeyword$_getText_closure1.call(GetTextKeyword.groovy)
	at com.kms.katalon.core.webui.keyword.internal.WebUIKeywordMain.runKeyword(WebUIKeywordMain.groovy:20)
	... 17 more

It seems to me as if something with the modifyObjectProperty method is doing something incorrectly, as if I don’t have the right settings.

@jklann …My two cents

  1. In the “for loop” please comment the getText and WebUI.comment code.

// sToAddress = WebUI.getText(tobEmail)
// WebUI.comment(“getText with findTestObject: $sToAddress”)

  1. In the for loop add the below code to print the xpath generated at runtime.

// Will print the xpath
println tobEmail.getProperties().get(0).getValue()

  1. Verify manually whether tobEmail xpath created WebUI.modifyObjectProperty is correct.

Thank you, @discover.selenium.

However, I think I found a solution with the below code.
Unfortunately, it has lead me to another completely new problem that I’m not even sure how it’s getting caused.

The code (viewed in the Log viewer) seems to keep going on forever in an endless loop, even though that shouldn’t happen.
At some point, it kicks out of the loop to execute the last 9 lines of code, while at the same time continuing to execute the loop. Or so it seems from the output to the Log viewer.
At which point, I have to quickly click the Katalon stop button in time. Otherwise it just keeps going through the loop and I have to eventually kill the task in Task Manager.

CODE

	for (int i = 1; i < 200; i++) {
		// Cycle through all the emails in MailCather to match the To Address, Subject and partial Received timestamp
		// The Received timestamp can only be matched partially because of the travel time from when the email is initiated above
		//		to when it is finally received in MailCatcher queue to be verified
		sXPath = "//tr[@data-message-id='" + i + "']/td[2]"
		tobEmail = makeTO(sXPath)
		sXPath = "//tr[@data-message-id='" + i + "']/td[3]"
		tobSubject = makeTO(sXPath)
		sXPath = "//tr[@data-message-id='" + i + "']/td[4]"
		tobTimeStamp = makeTO(sXPath)

		try {
			sToAddress = WebUI.getText(tobEmail)
			sESubject = WebUI.getText(tobSubject)
			sEReceived = WebUI.getText(tobTimeStamp)

			if (sToAddress.contains("$sNonISUEmail")) {
				if (sESubject.contains("$sSubject")) {
					iHour = sHOUR.toInteger()
					iMinute = sMIN.toInteger()
				
					if (sEReceived.contains("$sTmStmp $iHour:$iMinute")) {
						bEmailFound = true
					}

					iMinute++
					if (sEReceived.contains("$sTmStmp $iHour:$iMinute")) {
						bEmailFound = true
					}

					iMinute++
					if (sEReceived.contains("$sTmStmp $iHour:$iMinute")) {
						bEmailFound = true
					}

					iMinute++
					if (sEReceived.contains("$sTmStmp $iHour:$iMinute")) {
						bEmailFound = true
					}

					iHour++
					iMinute = 0
					if (sEReceived.contains("$sTmStmp $iHour:$iMinute")) {
						bEmailFound = true
					}
				}
			}

			if (bEmailFound == true) {
				// If all three expected values have been approximately matched, exit the for loop and continue with testing
				WebUI.comment('<<<   EMAIL FOUND   >>>')
				WebUI.click(tobEmail)

				WebUI.verifyTextPresent('Attachments')
				WebUI.waitForElementPresent(findTestObject('Page_MailCatcher/a_Plain text Tab'), 30)
				WebUI.waitForElementClickable(findTestObject('Page_MailCatcher/a_Plain text Tab'), 30)
				break
			}
		}
		catch (WebElementNotFoundException) {
			i--
			WebUI.comment("Didn't find the expected values in any of the $i emails.")
			break
		}
	}

	WebUI.maximizeWindow()
	Thread.sleep(3333)
	sFileName = 'AcctActvnConf - ' + (('d' + (sdfPSWDd.format(date)) + ' t') + sdfPSWDt.format(date)) + '.png'
	WebUI.takeScreenshot("../Screenshots/$sFileName")
	WebUI.setViewPortSize(1111, 777)
	Thread.sleep(3333)

	WebUI.waitForElementPresent(findTestObject('Page_MailCatcher/a_Plain text Tab'), 30)
	WebUI.waitForElementClickable(findTestObject('Page_MailCatcher/a_Plain text Tab'), 30)
	WebUI.click(findTestObject('Page_MailCatcher/a_Plain text Tab'))

@jklann You are adjusting the loop counter within the loop. That’s not good programming (and likely your source of error).

catch (WebElementNotFoundException) {
i-- <-- remove this line
WebUI.comment(“Didn’t find the expected values in any of the $i emails.”)
break;
}

Thank you, @grylion54.
I thought that would be an acceptable option because it breaks out of the for loop right after that subtraction.
I have made the change below to the code above.

CODE

		catch (WebElementNotFoundException) {
			int iEmails = i - 1
			WebUI.comment("Didn't find the expected values in any of the $iEmails emails.")
			break
		}

I also thought that I fixed the issue with the code above, but it seems that the Katalon Log Viewer cannot keep up with the code execution and cannot handle displaying all that has been executed.

It seems this way to me because:

  1. The Log Viewer only shows partially processing through 139 emails of the 145 that currently exist in MailCatcher, but in the open window, email 145 is clicked, with the email body displayed, and the last 9 lines of code have successfully executed, as there is a correct screenshot in the specified location.

  2. About half way through processing, the last 9 nine lines of code are executed, as evidenced by the browser changing with the executed actions. After the screenshot is taken, the browser then just sits there as the Log Viewer keeps displaying “new” lines of executed code, still cycling through the emails, eventually stopping half way through email 139 (creating xpath for tobTimeStamp, but not the first line of the try).

I’m not sure how to address or even fix this issue.

I’m not sure if this setting has any influence here…

image

Perhaps you could create a video and post a new topic (we’re now beyond the scope of your original question).

Thank you, @Russ_Thomas, for all your help!
You are correct.
I will try to make a video and a new post.

The last run I just did had a similar lag, but Log Viewer now showed everything.

1 Like