Wednesday, 16 December 2015

Screenshots For Selenium Reports In Jenkins and Remote Systems

Its well known that we can capture screen during test execution of selenium. It can be done during any moment of script execution or can be configured for failure screens using test frameworks like TestNG. These screen captures can also be made available in our automation reports. In case of TestNG, we can use the 'Reporter.log' function to add the screen to the TestNG report.

String screenshotName = getClass().getSimpleName() + "_" + testResult.getName() + "_" + getCurrentDateTimeStamp() + ".png";
File scrFile = ((TakesScreenshot)driver()).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("./build/reports/tests/screenshots/"+screenshotName)); 

Here we can see that the screen capture gets stored at a folder called 'screenshots' which in turn is located from the root folder './build/reports/tests/'

The above code will work fine as long as your scripts are running from your local machines. Now comes the tricky part.  What is we need to run these automated scripts from a remote machine or in CI tools like Jenkins? We cannot always assure the folder structure in the remote systems. It may happen that Jenkins or the Selenium Grid may insert a specific folder and thus while execution the report path may get different. So the screenshot file will not get rendered in our TestNG report.

A simple but effective solution to tackle such a scenario is to save your screenshots in BASE64 format instead of png files (by default selenium saves screen captured as '*.png' file). Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation. So you get to save your screen as a 'Text/String' format instead of a file. Now you can call this string in your report to get the very same image displayed in your report. Since it doesn't need to be stored in any folders unlike images, we can be rest assured that the report where ever is being populated will have the screenshots included and viewed.

This can be done as follows:

String screenshotBase64 = ((TakesScreenshot)driver()).getScreenshotAs(OutputType.BASE64);
setMapList("SCREEN_NAME", screenShotList);

Note the usage of 'OutputType.BASE64' in the above code snippet. This save the screen capture as a string to the variable 'screenshotBase64'. Now this can be added to a Java list and can be called during report generation.

test.log(LogStatus.INFO, "Snapshot below: " + test.addScreenCapture("data:image/jpeg;base64, "+getMapList("SCREEN_NAME").get(count)));

The above java code gets the screen captured as string from the List and adds the same to the report. Note that there is no need to mention the path of the screen as it is stored as a base64 type string. This helps to display the screen captures as is in automation reports.

Hope that was helpful. Stay tuned for more.