Katalon studio screen shot comparation

In this article I will compare the two screenshots in Katalon Studio. In Test Cases that we create in Katalon Stduio, sometimes we need to see if there is a difference between the two screenshots. If there are differences between the screenshots, the points that make the difference are also important for the test case. I have defined a special keyword on Katalon Studio that determines if there are differences between the two screenshots and shows the differences between these screenshots. In this article, I will try to explain this keyword and its usage through an example. So let’s start …

I’d like to start with keyword codes first.

The PixelGrabber class is applied to an Image or Image object to get a subset of the pixels in that image.

With the grabPixels () method; Image or Image allows the object to start sending pixels from and wait until all pixels in the corresponding rectangle are sent.

Thanks to this class and method, two visuals are compared. And if there are differences between the two images, the ImageDiffer class is used to determine these differences. These differences are also written to the image with the write method of the ImageIO class.

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
import java.awt.image.BufferedImage
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter

import javax.imageio.ImageIO

import org.openqa.selenium.WebDriver
import org.openqa.selenium.WebElement
import com.kms.katalon.core.configuration.RunConfiguration

import com.kms.katalon.core.webui.driver.DriverFactory

import com.kms.katalon.core.webui.common.WebUiCommonHelper
import ru.yandex.qatools.ashot.AShot
import ru.yandex.qatools.ashot.Screenshot
import ru.yandex.qatools.ashot.coordinates.WebDriverCoordsProvider
import ru.yandex.qatools.ashot.shooting.ShootingStrategies
import ru.yandex.qatools.ashot.comparison.ImageDiff
import ru.yandex.qatools.ashot.comparison.ImageDiffer

import java.awt.Image
import java.awt.Toolkit

import java.awt.image.PixelGrabber

import org.openqa.selenium.By;
import com.kms.katalon.core.logging.KeywordLogger

public class test {

@Keyword

def  compareImages2 (String test, String test1){

Image image1 = Toolkit.getDefaultToolkit().getImage(test);

Image image2 = Toolkit.getDefaultToolkit().getImage(test1);

PixelGrabber grab1 = new PixelGrabber (image1 , 0 ,0,-1,-1,false);

PixelGrabber grab2 = new PixelGrabber (image2 , 0 ,0,-1,-1,false);

int [] data1 =  null ;

if(grab1.grabPixels()) {

int width = grab1.getWidth();

int height = grab1.getHeight();

data1 = new int[width*height];

data1 = (int[]) grab1.getPixels();

}

int [] data2 =  null ;

if(grab2.grabPixels()){

int width = grab2.getWidth();

int height = grab2.getHeight();

data2 = new int[width*height];

data2 = (int[]) grab2.getPixels();

}

KeywordLogger logger = new KeywordLogger();

if (java.util.Arrays.equals(data1,data2)==true){

logger.logPassed(‘aynı’)

}

else {

BufferedImage expectedImage3 = ImageIO.read(new File(System.getProperty(“user.dir”) +”\\res\\test1.png”));

BufferedImage expectedImage4 = ImageIO.read(new File(System.getProperty(“user.dir”) +”\\res\\test2.png”));

ImageDiffer imgDiff = new ImageDiffer();

ImageDiff diff = imgDiff.makeDiff(expectedImage4, expectedImage3);

BufferedImage diffImage = diff.getDiffImage();

ImageIO.write(diff.getMarkedImage(),”PNG”, new File(System.getProperty(“user.dir”)+”\\res\\Difference(test1_test2.png”));

System.out.println(“\n diffImage= “+diffImage.getColorModel());

logger.logFailed(‘farklı’)

}

}

}

For the test, first open the page at https://katalon-demo-cura.herokuapp.com/ and take a screenshot and save it to the local. Then the same process is applied at http://demoaut-mimic.kazurayam.com/. Webuı.takescreenshot up in order to provide a link to this page with location area code ( ‘ImagePath’) of the image read in step ImageIO method given in the description of the path must be the same path information.
I encode for the Test Case are listed below:

 WebUI.openBrowser(”)

WebUI.navigateToUrl(‘https://katalon-demo-cura.herokuapp.com/’)

WebUI.maximizeWindow()

String img1 = WebUI.takeScreenshot(‘C:\\Users\\Katalon Studio\\Example \\res\\test1.png’)

WebUI.navigateToUrl(‘http://demoaut-mimic.kazurayam.com/’)

String img1 = WebUI.takeScreenshot(‘C:\\Users\\Katalon Studio\\Example \\res\\test2.png’)

CustomKeywords.’test.compareImages2′(img1, img2)

https://katalon-demo-cura.herokuapp.com/ url for screenshot:

test1.png

http://demoaut-mimic.kazurayam.com/ url for screenshot :

test2.png

The visual representation of the differences between these two images by the custom keyword created in Katalon Studio is as follows:

I hope it has been a useful post.

2 Likes

Hi @emine

It would be useful if you can highlight what is the difference between your approach and @kazurayam’s approach.

hi @ThanhTo
I have defined a keyword that pixelates the differences between the 2 screenshots taken instantaneously. Furthermore, if desired, a screen shot previously taken can be compared with the present screen shot. I did not use the AShot () class to take a screenshot. I used the takeScreenShot () key.
Yours truly…

2 Likes

hello @emine
can u help me solve this case, i cant get that pixels, for compare with another picture, the result from the array is null.
can u tell where’s my wrong?

Thanks.

this eror notification.
Please use “KeywordUtil.logInfo()” instead of “new KeywordLogger()” constructor. “KeywordLogger” is an internal API and might be changed in the future.
2019-12-30 16:18:34.296 ERROR k.k.c.m.CustomKeywordDelegatingMetaClass - :x: Ambiguous method overloading for method java.util.Arrays#equals.
Cannot resolve which method to invoke for [null, null] due to overlapping prototypes between:
[class [B, class [B]
[class [C, class [C]
[class [D, class [D]
[class [F, class [F]
[class [I, class [I]
[class [J, class [J]
[class [Ljava.lang.Object;, class [Ljava.lang.Object;]
[class [S, class [S]
[class [Z, class [Z]
2019-12-30 16:18:34.300 ERROR c.k.katalon.core.main.TestCaseExecutor - :x: Test Cases/Case coba FAILED.
Reason:
groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method java.util.Arrays#equals.
Cannot resolve which method to invoke for [null, null] due to overlapping prototypes between:
[class [B, class [B]
[class [C, class [C]
[class [D, class [D]
[class [F, class [F]
[class [I, class [I]
[class [J, class [J]
[class [Ljava.lang.Object;, class [Ljava.lang.Object;]
[class [S, class [S]
[class [Z, class [Z]
at test.compareImages2(test.groovy:89)
at test.invokeMethod(test.groovy)
at com.kms.katalon.core.main.CustomKeywordDelegatingMetaClass.invokeStaticMethod(CustomKeywordDelegatingMetaClass.java:50)
at Case coba.run(Case coba:30)
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 TempTestCase1577697491617.run(TempTestCase1577697491617.groovy:23)

1 Like

Hello @wijayantorivaldi
Please save the images you want to compare in the same folder as the project folder.
Please make sure the image path is correct in both the keyword and the test case.

1 Like

hi @emine

i place my image same path, but i always get the same result after running script.
can u tell me, what the meaning “com.kms.katalon.core.util.KeywordUtil - null**” ?

2019-12-30 17:19:05.298 INFO c.k.katalon.core.main.TestCaseExecutor - --------------------
2019-12-30 17:19:05.306 INFO c.k.katalon.core.main.TestCaseExecutor - START Test Cases/Case coba
2019-12-30 17:19:06.835 DEBUG testcase.Case coba - 1: openBrowser(“”)
2019-12-30 17:19:07.529 INFO c.k.k.core.webui.driver.DriverFactory - Starting ‘Chrome’ driver
Dec 30, 2019 5:19:07 PM org.openqa.selenium.remote.DesiredCapabilities chrome
INFO: Using new ChromeOptions() is preferred to DesiredCapabilities.chrome()
2019-12-30 17:19:07.712 INFO c.k.k.core.webui.driver.DriverFactory - Action delay is set to 0 seconds
Starting ChromeDriver 77.0.3865.40 (f484704e052e0b556f8030b65b953dce96503217-refs/branch-heads/3865@{#442}) on port 18983
Only local connections are allowed.
Please protect ports used by ChromeDriver and related test frameworks to prevent access by malicious code.
Dec 30, 2019 5:19:13 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
2019-12-30 17:19:14.057 INFO c.k.k.core.webui.driver.DriverFactory - sessionId = 4905db882b348cd9a06233bba981cb0d
2019-12-30 17:19:14.096 INFO c.k.k.core.webui.driver.DriverFactory - browser = Chrome 77.0.3865.75
2019-12-30 17:19:14.097 INFO c.k.k.core.webui.driver.DriverFactory - platform = Windows 10
2019-12-30 17:19:14.100 INFO c.k.k.core.webui.driver.DriverFactory - seleniumVersion = 3.141.59
2019-12-30 17:19:14.101 INFO c.k.k.core.webui.driver.DriverFactory - proxyInformation = ProxyInformation{proxyOption=NO_PROXY, proxyServerType=HTTP, password=, proxyServerAddress=, proxyServerPort=0}
2019-12-30 17:19:14.119 DEBUG testcase.Case coba - 2: img1 = “\C:\Users\xsirival1814\Katalon Studio\Test Beneran\tmp\test1.png”
2019-12-30 17:19:14.123 DEBUG testcase.Case coba - 3: img2 = “\C:\Users\xsirival1814\Katalon Studio\Test Beneran\tmp\test2.png”
2019-12-30 17:19:14.123 DEBUG testcase.Case coba - 4: test.compareImages2(“img1”, “img2”)
2019-12-30 17:19:14.538 INFO com.kms.katalon.core.util.KeywordUtil - null
2019-12-30 17:19:14.540 INFO com.kms.katalon.core.util.KeywordUtil - null
2019-12-30 17:19:14.556 INFO com.kms.katalon.core.util.KeywordUtil - Image Match
2019-12-30 17:19:14.556 INFO k.k.c.m.CustomKeywordDelegatingMetaClass - test.compareImages2 is PASSED
2019-12-30 17:19:14.560 DEBUG testcase.Case coba - 5: closeBrowser()
2019-12-30 17:19:15.452 INFO c.k.katalon.core.main.TestCaseExecutor - END Test Cases/Case coba

im attach my test case script.

thanks

Hello @wijayantorivaldi

WebUI.takeScreenshot(‘C:\\Users\\Katalon Studio\Example\ \res\\test1.png’)

Your Code :
WebUI.takeScreenshot(‘\\C:\Users\\…g’)

1 Like

Hello

already change, that still same response.
thanks.

I was able to download and add the ashot library and call this function, but it always returns that there is a difference between the two files even though they are copies ? There should be no difference… !

1 Like

hi @emine
I got error with the Keyword
groovy.lang.MissingPropertyException: No such property: CustomeKeywords for class: Script1637814107354
at Test01.run(Test01:32)
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:442)
at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:433)
at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:412)
at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:404)
at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:281)
at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:138)
at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:129)
at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
at TempTestCase1637816718166.run(TempTestCase1637816718166.groovy:25)

I check my keyword and the package is not declared (??)

what could possibly wrong. The package is there.

hi @wijayantorivaldi
Are you finally able to run Test Case successfully?

You have a typo.

wrong

CustomeKeywords."   "

right

CustomKeywords."   "

unnecessary “e”

1 Like

Damn my typo.

After correcting the spelling, I got another issue:
Test Cases/PIXEL GRABBER/Test01 FAILED.
Reason:
java.lang.ClassNotFoundException: pixelgrabber
at com.kms.katalon.core.main.CustomKeywordDelegatingMetaClass.getCustomKeywordClassAndSetMetaClass(CustomKeywordDelegatingMetaClass.java:100)
at com.kms.katalon.core.main.CustomKeywordDelegatingMetaClass.invokeStaticMethod(CustomKeywordDelegatingMetaClass.java:45)
at Test01.run(Test01:16)
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:442)
at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:433)
at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:412)
at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:404)
at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:281)
at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:138)
at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:129)
at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
at TempTestCase1637894869985.run(TempTestCase1637894869985.groovy:25)

In the Test01, do you have an import statement for pixelgrabber?

I have added import java.awt.image.PixelGrabber as PixelGrabber but still have teh same error

Somewhere you wrote pixelgrrabber, not PixelGrabber.

Case of every character matters in any program. p and P are distinguished.

OK I made mistake to pick the correct keyword. I have fixed it, make sure the file repository and file name are correct but still another issue occurred:

Test Cases/PIXEL GRABBER/Test01 FAILED.
Reason:
org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack: No signature of method: test.compareImages2() is applicable for argument types: (java.lang.String, java.lang.String) values: [C:\Users\sugiarto\MITRAIS\INFOCARE PROJECT\KATALON\Katalon Studio\INFOCARE\Screenshots\test1.png, …]

The message is clearly telling you what you wrote wrong.

method: test.compareImages2() is applicable for argument types (java.lang.String, java.lang.String)

but you actually gave

[C:\Users\sugiarto\MITRAIS\INFOCARE PROJECT\KATALON\Katalon Studio\INFOCARE\Screenshots\test1.png, …]

Possibly you specified a variable of type java.io.File or java.nio.file.Path.

You have to change your code to make the types to match.

But how?

I don’t know, as you haven’t showed us the necessary source code.

This is my Keyword:
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
import java.awt.image.BufferedImage
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter

import javax.imageio.ImageIO

import org.openqa.selenium.WebDriver
import org.openqa.selenium.WebElement
import com.kms.katalon.core.configuration.RunConfiguration

import com.kms.katalon.core.webui.driver.DriverFactory

import com.kms.katalon.core.webui.common.WebUiCommonHelper
import ru.yandex.qatools.ashot.AShot
import ru.yandex.qatools.ashot.Screenshot
import ru.yandex.qatools.ashot.coordinates.WebDriverCoordsProvider
import ru.yandex.qatools.ashot.shooting.ShootingStrategies
import ru.yandex.qatools.ashot.comparison.ImageDiff
import ru.yandex.qatools.ashot.comparison.ImageDiffer

import java.awt.Image
import java.awt.Toolkit

import java.awt.image.PixelGrabber

import org.openqa.selenium.By;
import com.kms.katalon.core.logging.KeywordLogger

import internal.GlobalVariable

public class test {

@Keyword

def  compareImages2 (String test, String test1){

	Image image1 = Toolkit.getDefaultToolkit().getImage(test);

	Image image2 = Toolkit.getDefaultToolkit().getImage(test1);

	PixelGrabber grab1 = new PixelGrabber (image1 , 0 ,0,-1,-1,false);

	PixelGrabber grab2 = new PixelGrabber (image2 , 0 ,0,-1,-1,false);

	int [] data1 =  null ;

	if(grab1.grabPixels()) {

		int width = grab1.getWidth();

		int height = grab1.getHeight();

		data1 = new int[width*height];

		data1 = (int[]) grab1.getPixels();
	}

	int [] data2 =  null ;

	if(grab2.grabPixels()){

		int width = grab2.getWidth();

		int height = grab2.getHeight();

		data2 = new int[width*height];

		data2 = (int[]) grab2.getPixels();
	}

	KeywordLogger logger = new KeywordLogger();

	if (java.util.Arrays.equals(data1,data2)==true){

		logger.logPassed(‘aynı’)
	}

	else {

		BufferedImage expectedImage3 = ImageIO.read(new File(System.getProperty("user.dir")+"\\Screenshots\\test1.png"));

		BufferedImage expectedImage4 = ImageIO.read(new File(System.getProperty("user.dir")+"\\Screenshots\\test2.png"));

		ImageDiffer imgDiff = new ImageDiffer();

		ImageDiff diff = imgDiff.makeDiff(expectedImage4, expectedImage3);

		BufferedImage diffImage = diff.getDiffImage();

		ImageIO.write(diff.getMarkedImage(),”PNG”, new File(System.getProperty("user.dir")+"\\Screenshot\\Difference(test1_test2.png”));
	
	System.out.println(“\n diffImage= “+diffImage.getColorModel());
	
	logger.logFailed(‘farklı’)

}
}
}

This is my test case:
WebUI.openBrowser(’’)

WebUI.navigateToUrl(‘https://katalon-demo-cura.herokuapp.com/’)

WebUI.maximizeWindow()

String img1 = WebUI.takeScreenshot(‘C:\Users\sugiarto\MITRAIS\INFOCARE PROJECT\KATALON\Katalon Studio\INFOCARE\Screenshots\test1.png’)

WebUI.navigateToUrl(‘http://demoaut-mimic.kazurayam.com/’)

String img2 = WebUI.takeScreenshot(‘C:\Users\sugiarto\MITRAIS\INFOCARE PROJECT\KATALON\Katalon Studio\INFOCARE\Screenshots\test2.png’)

CustomKeywords.‘test.compareImages2’(img1,img2)
WebUI.closeBrowser()

Your keyword does not compile for me.

Wrong:

ImageIO.write(diff.getMarkedImage(),”PNG”, 
    new File(System.getProperty("user.dir")+
        "\\Screenshot\\Difference(test1_test2.png”));

corrected:

ImageIO.write(diff.getMarkedImage(),”PNG”, 
    new File(System.getProperty("user.dir")+
        "\\Screenshot\\Difference(test1_test2.png)");

Do you find a difference?

") -> )"

at the end.