Hello, i’ll try to describe how to write asynchronous “watch dog” to check if some element appears
Situation:
our application is quite an asynchronous that means, that from time to time an Error can be shown on UI that actually does not directly belong to Test case i’m executing. However it will be good to catch such error and present it in reports.
prereq.:
I have TC that is responsible for Opening browser from this TC i will store actual driver into Global variable (type null)
I have my own reporting that allows me to store steps in way i need.
Solution:
in Test liseners i have following functions:
import org.openqa.selenium.By
import org.openqa.selenium.WebDriver
import org.openqa.selenium.WebElement
import com.kms.katalon.core.annotation.AfterTestCase
import com.kms.katalon.core.annotation.AfterTestSuite
import com.kms.katalon.core.annotation.BeforeTestCase
import com.kms.katalon.core.annotation.BeforeTestSuite
import com.kms.katalon.core.context.TestCaseContext
import com.kms.katalon.core.context.TestSuiteContext
import com.swre.report as Report
import internal.GlobalVariable as GlobalVariable
class PrepareTestDOC {
Report r = new Report()
private static TestCaseContext testCaseContext
private static TestSuiteContext testSuiteContext
private static Date start = new Date()
def runThread = true
def guard = new Thread({
sleep(5000) // dont need to start early
while(runThread){
try{
// this is where i try to get driver stored by OpenBrowser TC
def d = (WebDriver)GlobalVariable.webDriver
//My element that i want to watch
WebElement e = d.findElement(By.xpath("//div[contains(@class,'noty_type_error')]//span"))
if(e != null ){
println "*** Found an ERROR bar!"
def txt = e.text
r.addStep("<center><b>UI Error!</b><br>${txt}</center>", false) //call to my reporting solution with information on UI error
runThread = false
}
} catch (a){
println a
}
println "*** from Guard ${new Date()}"
sleep(3000)
}
} as Runnable)
/**
* Executes before every test case starts.
* @param testCaseContext related information of the executed test case.
*/
@BeforeTestCase
def prepareTestCase(TestCaseContext testCaseContext) {
GlobalVariable.testCaseContext = testCaseContext
// waking up guard
r.setStartTest()
println "*** Setting up guard"
guard.start()
}
@AfterTestCase
def printStatus(TestCaseContext testCaseContext){
r.addTestCase()
r.setEndTest()
r.flush()
// thread.close() is deprecated so i use semafor to gracefully end it
runThread = false
println "*** Guard dissmissed"
}
}
and when error appears it looks like this in reports: