I am performing the cross browser testing of a GWT web application on different PCs using Selenium Grid. The problem which I am facing is that the size of generated screenshots (taken during the tests) is different for different PCs and I want to make my code generic i.e. either to set some default size of the screenshots. Here is my code which I am using to take the screenshot and then to compare the generated image with the image stored locally on my PC.
Firstly I will call the CallScreenshotAndCompareImage method with arguments (canvas,className).
Here canvas is the WebElement representing the HTML5 canvas in the GWT application.
FileBase is the file stored locally in my project and fileActual is the generated screenshot image.
public class Browser {
//ThreadLocal will provide thread-safe tests
protected ThreadLocal<RemoteWebDriver> threadLocal = null;
String serverMachine = "xxx.xxx.xxx.xxx:xxx/hub"; //IP Address of hub
@BeforeTest
@Parameters("browser")
public void setup(String browser) throws MalformedURLException{
if(browser.equalsIgnoreCase("chrome")) {
System.setProperty("webdriver.chrome.driver", ".src/Drivers/chromedriver.exe");
DesiredCapabilities capability = null;
capability = DesiredCapabilities.chrome();
capability.setPlatform(Platform.WINDOWS);
capability.setBrowserName("chrome");
createRemoteWebDriver(capability);
}
else if(browser.equalsIgnoreCase("firefox")) {
System.setProperty("webdriver.gecko.driver", ".src/Drivers/geckodriver.exe");
DesiredCapabilities capability = null;
capability = DesiredCapabilities.firefox();
capability.setPlatform(Platform.WINDOWS);
capability.setBrowserName("firefox");
createRemoteWebDriver(capability);
}
}
public void createRemoteWebDriver(DesiredCapabilities capability) throws MalformedURLException {
threadLocal = new ThreadLocal<RemoteWebDriver>();
threadLocal.set(new RemoteWebDriver(new URL(serverMachine), capability));
}
public WebDriver getDriver() {
return threadLocal.get();
}
public void CallScreenshotAndCompareImage(WebElement element, String className) throws IOException, InterruptedException {
File fileBase1 = new File("./src/Images/baseDrawing"+className+"Chrome.png");
File fileBase2 = new File("./src/Images/baseDrawing"+className+"Firefox.png");
Capabilities cap = ((RemoteWebDriver) getDriver()).getCapabilities();
String browserName = cap.getBrowserName().toLowerCase();
File fileActual = new File("./src/Images/actualDrawing"+className+browserName+".png");
File elementImage = this.takeElementScreenshot(element,"png");
FileUtils.copyFile(elementImage, fileActual);
if(browserName.equalsIgnoreCase("chrome"))
this.compareImage(fileBase1,fileActual);
else if(browserName.equalsIgnoreCase("firefox"))
this.compareImage(fileBase2,fileActual);
Thread.sleep(3000);
}
public File takeElementScreenshot(WebElement element, String imageFormat) throws IOException{
Point elementXY = element.getLocation();
int elementHeight = element.getSize().getHeight();
int elementWidth = element.getSize().getWidth();
Rectangle elementRectArea = new Rectangle(elementWidth,elementHeight);
WrapsDriver wrapsDriver = (WrapsDriver) element;
File pageImage = ((TakesScreenshot)wrapsDriver.getWrappedDriver()).getScreenshotAs(OutputType.FILE);
BufferedImage bufferedImage = ImageIO.read(pageImage);
BufferedImage elementImage = bufferedImage.getSubimage(elementXY.getX(), elementXY.getY(), elementRectArea.width, elementRectArea.height);
ImageIO.write(elementImage, imageFormat, pageImage);
return pageImage;
}
public void compareImage(File fileBase, File fileActual) {
/*
STEPS:
1) For first image file, recognize the contents of the file and decodes it into a BufferedImage which can be directly used by Java 2D.
2) Get the raster from the bufferedImage object which is a copy of image data.
3) Get the DataBuffer associated with the raster.
4) Get the size of the all the banks(data arrays) for the DataBuffer object.
5) Repeat steps 1-4 for the second image file.
6) If sizes of both of the images are different, then images won't be same.
7) If sizes are same, then compare all the data array elements for both of the DataBuffer objects. If they are same. then both images will be same.
*/
try {
BufferedImage bufferedImage = ImageIO.read(fileBase);
DataBuffer dataBufferFirst = bufferedImage.getData().getDataBuffer();
int sizeFirst = dataBufferFirst.getSize();
BufferedImage bufferedImage2 = ImageIO.read(fileActual);
DataBuffer dataBufferSecond = bufferedImage2.getData().getDataBuffer();
int sizeSecond = dataBufferSecond.getSize();
int count=0;
Assert.assertEquals(sizeFirst, sizeSecond,"Size of Base Drawing and actual Drawing is not same");
if(sizeFirst == sizeSecond)
{
for(int i=0; i<sizeFirst; i++)
{
if(dataBufferFirst.getElem(i) != dataBufferSecond.getElem(i)) //getElem() returns the data array element at the specified index.
{
count++;
}
}
Assert.assertEquals(count, 0,"Both images are not same");
}
} catch (Exception e) {
Assert.fail("Failed to compare image files...!!!");
}
}
}
After running this code, when I compared the properties of both the base (local) image and the actual (generated) image, then there was a little difference between both of those images.
Base Drawing: Size -> 253 KB, Bit Depth -> 32, Dimensions -> 1570 x 873 pixels
Actual Drawing: Size -> 232 KB, Bit Depth -> 24, Dimensions -> 1570 x 873 pixels
Everything else was same in the properties of both of these images.
What should I add in my code so that the generated screenshots from different PCs will always be of the same size?