takeWebElementScreenshot customkeyword from aShot plugin is not working as expected

Hi,

I installed ’ Image Comparison using aShot Keywords’ plugin to play with screenshots. I tried to use method ‘takeWebElementScreenshot’ which require the repository object name to take screenshot of and filename to save the screenshot. This is how i am doing it

CustomKeywords.'kms.turing.katalon.plugins.visualtesting.ScreenCapture.takeWebElementScreenshot'(findTestObject('Unified_Agent_Objects/AgentMenuOptions/CustomerConversationView/ChatNotifications/WebChannelImage'), 
    'test.png', 5, FailureHandling.CONTINUE_ON_FAILURE)

This method is taking blank screenshot of given web element. Before taking screenshot of web element, I am sure the web element is visible because

WebUI.waitForElementVisible(findTestObject('Unified_Agent_Objects/AgentMenuOptions/CustomerConversationView/ChatNotifications/WebChannelImage'), 
    3)

is executing successfully.

This is reference from documentation to use this keyword

Blockquote
@com.kms.katalon.core.annotation.Keyword static void takeWebElementScreenshot(com.kms.katalon.core.testobject.TestObject object, java.lang.String filename, int timeout = 10, com.kms.katalon.core.model.FailureHandling flowControl = FailureHandling.OPTIONAL)
Take the picture of a specific web element using AShot and save to screenshots folder in current working project
Parameters:
object - the web element need to take picture
filename - the image will be save with the name

Not sure what I am doing wrong which is generating blank screenshots???

Thanks,

Possibly, the targeted web element IS NOT visible or it IS visible and IS blank after 3 seconds. Therefore you got a blank screenshot.

The WebUI.waitForElementVisible(TestObject, 3) keyword will NOT throw exception when the timeout expired even if the target element IS NOT visible. The keyword will just write a single warning message. So it is likely you didn’t recognize the failure.

You had better use other keyword that throws Exception when the timeout expired. For example,

  • WebUI.verifyElementVisible(TestObject, 3)
  • WebUI.verifyElementPresent(TestObject, 10)

Timeout of 3 seconds might be too short.
You can change the timeout from 3 to 10, 20, 30 and see.

See

The “scaling of screen resolution” really matters when you take a screenshot.

What do I mean “screen resolution”? it is this:

I have ever used AShot and got troubles because I did not mange the “scaling of screen resolution” properly.

I do not know if the ‘Image Comparison using aShot Keywords’ plugin takes care of it. If the plugin does NOT mange the scaling of screen resolution properly, it is quite likely that the screeshot image taken by the plugin becomes something unexpected.

Why not you just try and the built-in keyword, rather than the custom one?

I suppose that this official Keyword should be tested better.

verifyElementVisible does not have a timeout.

Probably you were thinking of:
WebUI.verifyElementPresent(TestObject, 3)

but I agree you may want a longer timeout, like 10.

1 Like
Possibly, the targeted web element IS NOT visible or it IS visible and IS blank after 3 seconds. Therefore you got a blank screenshot.

Its not the case as I used different timeouts and it always passed ‘waitForElementVisible’ action. I also used ‘waitForElementPresent’ keyword with sucess but keeps getting balnk screenshot. The web element I am talking about displays for around 30 seconds and then disappear so I believe this duarion is enough to take a screenshot.

Why not you just try and the built-in keyword, rather than the custom one?

After some attempts with that plugin, now I used the builtin keyword for taking element screenshot but there is no builtin method available for comparison so I used custom keyword of mentioned plugin

Blockquote
@com.kms.katalon.core.annotation.Keyword static boolean areMatched(java.lang.String expectedImgPath, java.lang.String actualImgPath, com.kms.katalon.core.model.FailureHandling flowControl = FailureHandling.STOP_ON_FAILURE)
Verify two images are matched or not
Returns:
Parameters:
expectedImgPath - the location of expected image
actualImgPath - the location of actual image

which successfully compared two images but there is still one problem. If I ran my test on different screen as compared to the one where I captured my reference screenshot (expected image), it still fail due to different images resolution I guess.

Is there any method available where I can mention difference ratio (expected between images due to different screen) so that during images comparison, this ratio will be considered to avoid test failing on different screen?

Your finding proves that the “Image Comparison using AShot Keyword” does not take the device pixel ratio into account appropriately. Possibly you shouldn’t use it.


I looked at the source code of the plugin

I found this code is problematic.

See the signagure of takeScalingScreenshot keyword:

static void takeScalingScreenshot(String filename, float dpr, FailureHandling flowControl = FailureHandling.OPTIONAL){
		try{
			def screenshot = new AShot()
					.shootingStrategy(ShootingStrategies.scaling(dpr))
					.takeScreenshot(DriverFactory.getWebDriver())
			saveScreenshot(filename, screenshot)
		}catch(ex){
			handleError(ex, flowControl)
		}
	}

This has a parameter named dpr, which stands for device pixcel ratio. the dpr parameter is actually used when AShot object is to take screenshot. This is the way ALL of method should follow.

However all other Keyword methods in this plugin doesn’t take device pixcel ratio into account. The author of this program was a bit lazy, I guess. He did not test the code using 2 machines with different screen resolution settings as @zahid.asim did.

Therefore I would conclude that this plugin is incomplete. This will never work appropriately if you use the keyword on 2 machines with different scaling of screen resolution.

Short answer to @zahid.asim :

  • You can use the Katalon built-in keyword to take screenshots
  • You can use the AShot’s ImageDiffer class directly to compare 2 image files

You don’t need the faulty plugin. You can read the source of the plugin, and will find that the plugin does not do much. You don’t need it. Rather, it disturbs you.

AShot repository: GitHub - pazone/ashot: WebDriver Screenshot utility. Take screenshots, crop, prettify, compare

AShot jar: https://mvnrepository.com/artifact/ru.yandex.qatools.ashot/ashot/1.5.4

@zahid.ashim would wonder how a test script can know the value of device pixcel ratio of the machine on which the script is currently running.

There is a way.

See Window.devicePixelRatio - Web APIs | MDN

If you run a JavaScript in browser

const scale = window.devicePixelRatio;
console.log(scale)
return scale

Then you will see, 2.00 for example in the console of browser.

Your Katalon test case can call

double dpr = WebUI.executeJavaScript(script)

to execute the aforementioned JavaScript on browser, and receive the returned value. You will get the exact device pixcel ratio (or scale) by this.

The following is my wrapper library of AShot. It fully takes Device Pixcel Ratio taken into account.

My code just support taking screeenshots into images and save it into file while taking DPR into account. It does not implement a method for image comparison, because you don’t need it.

Provided that you get 2 images, then your code can directly call AShot’s image comparison method with the 2 images as params. It’s so easy.

The jar is downloadable at https://mvnrepository.com/artifact/com.kazurayam/ashotwrapper/0.1.1

Also you can download the zip of this project from here, and run

$ cd <the project dir>
$ gradle build

A typical code example: See

At line #66

        float dpr = DevicePixelRatioResolver.resolveDPR(driver);
        aswOptions = new AShotWrapper.Options.Builder().devicePixelRatio(dpr).build();

This resolves the Device Pixcel Ration of the current machine.

and line #70

@Test
    void test_takeWebElementImage() throws IOException {
        BufferedImage image = AShotWrapper.takeElementImage(driver,
                By.xpath("//body/div"),
                aswOptions);
        assertNotNull(image);
        File screenshotFile = outputDir.resolve("test_takeWebElementImage.png").toFile();
        ImageIO.write(image, "PNG", screenshotFile);
        assertTrue(screenshotFile.exists());
    }

This takes a screenshot of a web element with DPR considered.


As you can see, my AShotWrapper class is NOT designed to be used in Katalon Studio. It is designed with Selenium Java in mind.