Hello all, I’ve been trying out Katalon for a while and stumbled on @kazurayam scripts which seemed like a great starting point for my needs. (GitHub - kazurayam/VisualInspectionInKatalonStudio_Reborn: A Katalon Studio project. This project performs automated Web UI testing with screenshot comparison and HTML source comparison.)
I had made a question on github but i’ll paste it here for visibility. Seems it’s more appropriate to ask here.
the scripts i’m trying are part of the " VisualInspectionTwins" sets. The instructions are for one link (one page) per environment. But my test/website has multiple urls for both Prod and Dev environments (around 50 urls for one website on Prod, and the same for the website version on Dev)
I’ve modified the code to use data files and tried to make it work for this “multiple urls per website” scenario. But I have a strange behaviour now. After my test finishes, it passes but shouldn’t. As a trial, I purposely made the scripts compare 2 sets of completely different websites so that it fails when checking the visual comparison. But it ends in a “test pass”!
I had to split the “visitMyAdminTopPage” testcase into 2 scripts tho. Actually, i’ll paste all scripts that I modified below:
“VisualInspectionTwins”
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import com.kazurayam.ks.globalvariable.ExecutionProfilesLoader
import com.kazurayam.materialstore.DiffArtifacts
import com.kazurayam.materialstore.JobName
import com.kazurayam.materialstore.JobTimestamp
import com.kazurayam.materialstore.MaterialList
import com.kazurayam.materialstore.IgnoringMetadataKeys
import com.kazurayam.materialstore.MetadataPattern
import com.kazurayam.materialstore.Store
import com.kazurayam.materialstore.Stores
import com.kms.katalon.core.configuration.RunConfiguration
import com.kms.katalon.core.util.KeywordUtil
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import internal.GlobalVariable
Path projectDir = Paths.get(RunConfiguration.getProjectDir())
Path root = projectDir.resolve("store")
Store store = Stores.newInstance(root)
JobName jobName = new JobName("MyAdmin_VisualInspectionTwins")
ExecutionProfilesLoader profilesLoader = new ExecutionProfilesLoader()
// --------------------------------------------------------------------
// visit the Production environment
String profile1 = "ProdEnv"
profilesLoader.loadProfile(profile1)
WebUI.comment("Execution Profile ${profile1} was loaded")
JobTimestamp timestampP = JobTimestamp.now()
WebUI.callTestCase(
findTestCase("utils/goto_ProdSite"),
["profile": profile1, "store": store, "jobName": jobName, "jobTimestamp": timestampP]
)
// visit the Development environment
String profile2 = "DevEnv"
profilesLoader.loadProfile(profile2)
WebUI.comment("Execution Profile ${profile2} was loaded")
JobTimestamp timestampD = JobTimestamp.now()
WebUI.callTestCase(
findTestCase("utils/goto_DevSite"),
["profile": profile2, "store": store, "jobName": jobName, "jobTimestamp": timestampD]
)
// --------------------------------------------------------------------
// compare the materials obtained from the 2 sites, compile a diff report
// pickup the materials that belongs to the 2 "profiles"
MaterialList left = store.select(jobName, timestampP,
MetadataPattern.builderWithMap([ "profile": profile1 ]).build()
)
MaterialList right = store.select(jobName, timestampD,
MetadataPattern.builderWithMap([ "profile": profile2 ]).build()
)
// difference greater than the criteria should be warned
double criteria = 0.0d
// make DiffArtifacts
DiffArtifacts stuffedDiffArtifacts = store.makeDiff(left, right, IgnoringMetadataKeys.of("profile", "URL.host"))
int warnings = stuffedDiffArtifacts.countWarnings(criteria)
// compile HTML report
Path reportFile = store.reportDiffs(jobName, stuffedDiffArtifacts, criteria, jobName.toString() + "-index.html")
assert Files.exists(reportFile)
WebUI.comment("The report can be found ${reportFile.toString()}")
if (warnings > 0) {
KeywordUtil.markFailed("found ${warnings} differences.")
}
“visitMyAdminTopPage1” renamed to “goto_ProdSite”
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.kazurayam.materialstore.Metadata
import com.kms.katalon.core.testobject.ConditionType
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import internal.GlobalVariable
// def linksDataDev = findTestData("dev")
def linksDataProd = findTestData("prod")
def dbDevProd_data = [('urlprod') : '',('username') : '', ('password') : '']
def rows = findTestData("prod").getRowNumbers()
// check params which should be passed as the arguments of WebUI.callTestCases() call
Objects.requireNonNull(profile)
Objects.requireNonNull(store)
Objects.requireNonNull(jobName)
Objects.requireNonNull(jobTimestamp)
// check the GlobalVariables
// assert GlobalVariable.URL != null, "GlobalVariable.URL is not defined"
WebUI.openBrowser(null)
WebUI.setViewPortSize(1024, 800)
for (def rowNumIndex = 1; rowNumIndex <= rows; rowNumIndex++) {
dbDevProd_data.urlprod = linksDataProd.getValue(1, rowNumIndex)
WebUI.navigateToUrl(dbDevProd_data.urlprod)
WebUI.waitForPageLoad(10)
URL url = new URL(WebUI.getUrl())
WebUI.callTestCase(findTestCase("utils/takeScreenshotAndPageSource"),
[
"store": store,
"jobName": jobName,
"jobTimestamp": jobTimestamp,
"metadata": Metadata.builderWithUrl(url)
.put("profile", profile)
.put("selector", "body")
.build()
]
)
}
WebUI.closeBrowser()
“visitMyAdminTopPage2” renamed to “goto_DevSite”
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.kazurayam.materialstore.Metadata
import com.kms.katalon.core.testobject.ConditionType
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import internal.GlobalVariable
def linksDataDev = findTestData("dev")
// def linksDataProd = findTestData("prod")
def dbDevProd_data = [('urldev') : '',('username') : '', ('password') : '']
def rows = findTestData("dev").getRowNumbers()
// check params which should be passed as the arguments of WebUI.callTestCases() call
Objects.requireNonNull(profile)
Objects.requireNonNull(store)
Objects.requireNonNull(jobName)
Objects.requireNonNull(jobTimestamp)
// check the GlobalVariables
// assert GlobalVariable.URL != null, "GlobalVariable.URL is not defined"
WebUI.openBrowser(null)
WebUI.setViewPortSize(1024, 800)
for (def rowNumIndex = 1; rowNumIndex <= rows; rowNumIndex++) {
dbDevProd_data.urldev = linksDataDev.getValue(1, rowNumIndex)
WebUI.navigateToUrl(dbDevProd_data.urldev)
WebUI.waitForPageLoad(10)
URL url = new URL(WebUI.getUrl())
WebUI.callTestCase(findTestCase("utils/takeScreenshotAndPageSource"),
[
"store": store,
"jobName": jobName,
"jobTimestamp": jobTimestamp,
"metadata": Metadata.builderWithUrl(url)
.put("profile", profile)
.put("selector", "body")
.build()
]
)
}
WebUI.closeBrowser()
And the “takeScreenshotAndPageSource” did not change so i guess pasting it here is not needed. But I will just in case:
import java.nio.file.Files
import java.nio.file.Path
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.openqa.selenium.WebDriver
import com.kazurayam.materialstore.FileType
import com.kazurayam.materialstore.Material
import com.kazurayam.materialstore.Metadata
import com.kms.katalon.core.webui.driver.DriverFactory
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
Objects.requireNonNull(store)
Objects.requireNonNull(jobName)
Objects.requireNonNull(jobTimestamp)
Objects.requireNonNull(metadata)
assert metadata instanceof Metadata
// take a screenshot and save the image into a temporary file using Katalon's built-in keyword
Path tempFile = Files.createTempFile(null, null);
WebUI.takeFullPageScreenshot(tempFile.toAbsolutePath().toFile().toString(), [])
// copy the image file into the materialstore
Material image = store.write(jobName, jobTimestamp, FileType.PNG, metadata, tempFile)
assert image != null
// save the page source HTML into the materialstore
WebDriver driver = DriverFactory.getWebDriver()
Document doc = Jsoup.parse(driver.getPageSource())
Material html = store.write(jobName, jobTimestamp, FileType.HTML, metadata, doc.toString())
assert html != null
Not sure why this passes, I can see the test going to the correct webpages, using the proper data files, like so:
set1
WebUI.navigateToUrl(dbDevProd_data.urlprod) goes to (bogus websites just for explanation’s sake)
1- www.testprod01.com
2- www.testprod02.com
3- www.testprod03.com
4- www.testprod04.com
set2
WebUI.navigateToUrl(dbDevProd_data.urldev) goes to:
1- www.testdev01.com
2- www.testdev02.com
3- www.testdev03.com
4- www.testdev04.com
of course i’m using other links in the data files but set1 and set2 are completely different websites and could not possibly result in a “pass”. Is there a kind soul that could help me out to see what I’m doing wrong ? I’m just starting to learn and I’m stuck on this problem.