Introduction to take Screenshot in selenium
To take Screenshot in Selenium is a very important aspect of Automation testing using Selenium tool. This blog post will tell you more details on how to take a screenshot in selenium web driver.
No doubt, Software Testing heavily depends on the screenshots for references during QA check.
It helps to understand what exactly happened during a failure. Bug analysis is heavily dependant on screenshots.
How Screenshot helps the software industry?
Screenshots help to determine the following:
- If the application has some errors, defects and issues.
- If the application failed during execution.
- If the automation tool is unable to find out objects.
- If the automation script reached timed out value while detecting an object.
- Screenshots allow us to understand and determine the flow. They will further help us to see if the application is working as expected.
- Screenshots are major evidence and behavioural check in the cross-browser testing.
Why does Failure happen in Software Industry?
Failure may occur due to one of the following reasons:
- Assertion mismatch.
- Due to the presence of unexpected popup or alerts.
- Sync issue or page loads forever.
- The page may not have the expected element.
- Mismatch in expected or actual values.
Three methods for taking Screenshots
The below details will cover code for taking a screenshot in selenium in the below ways.
- Using Selenium WebDriver
- Using Robot Class-Java
- Using 3rd party APIs
Using Selenium WebDriver
Selenium WebDriver has a simple yet powerful screenshot capturing mechanism. Selenium’s takesScreenshot() method can return one of the following
- The whole page
- The current window(opened)
- A-frame segment (visible)
- The HTML content of a page.
- The whole display with a browser.
WebDriver and Screenshot
WebDriver supports the following formats:
- OutputType.BASE64
- OutputType.BYTES
- OutputType.FILE
Using TakesScreenshot OutputType.BASE64
If we have taken an image in BASE64 format, we have to convert the same to an image. The code for that as follows:
String myPicBase64=((TakesScreenshot)driver).getScreenshotAs(OutputType.BASE64);
File mySreenshot=OutputType.FILE.ConvertFromBase64png(myPicBase64);
//Now copy the file to the correct destination
FileUtils.copyFile(mySreenshot,new File("D:\\Test\\Report\\abc.png"),true);
Using TakesScreenshot OutputType.BYTES
If we have taken an image in BYTES format, we have to convert the same to an image. The code for that as follows:
bytes[] myBytes=((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
File mySreenshot=OutputType.FILE.ConvertFrompngBytes(myBytes);
//Now copy the file to the correct destination
FileUtils.copyFile(mySreenshot,new File("D:\\Test\\Report\\abc.png"),true);
Using TakesScreenshot OutputType.FILE
The first approach: Here we need to use typecasting for the WebDriver to take a screenshot.
public void getscreenshot() throws Exception
{
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("<<path with name of the file>>"));
}
The steps are as follows:
- Convert the WebDriver to TakesScreenshot object.
- use getScreenshotAs() method to provide the type of picture.
- copy the file from temp to the destination location.
overloaded method of takingscreenshot
The Second Approach: We will have an overloaded method of takingscreenshot where it takes no parameter or one parameter which is the element. Also, there are two ways to implement it. One is to give your element name and get the screenshot file as element name or set the file name with timestamp
public void takeSceenshot() throws IOException
{
TakesScreenshot oscn=(TakesScreenshot)driver;
File oscnShot= oscn.getScreenshotAs(OutputType.FILE);
File destfile=new File("D:\My_projects\Projects\TestBase\src\Base\Test.jpg");
FileUtils.copyFile(oscnShot, destfile);
}
public void takeSceenshot(String elementType) throws IOException
{
TakesScreenshot oscn=(TakesScreenshot)driver;
File oscnShot= oscn.getScreenshotAs(OutputType.FILE);
File destfile=new File("D:\My_projects\Projects\TestBase\src\Base\Test"+elementType+".jpg");
File destfile1=new File("D:\My_projects\Projects\TestBase\src\Base\Test"+GetTimeStampValue()+".jpg");
FileUtils.copyFile(oscnShot, destfile);
FileUtils.copyFile(oscnShot, destfile1);
}
public String GetTimeStampValue()throws IOException{
Calendar cal = Calendar.getInstance();
Date time=cal.getTime();
String timestamp=time.toString();
System.out.println(timestamp);
String systime=timestamp.replace(":", "-");
System.out.println(systime);
return systime;
}
How to trigger the screenshot capturing method?
We simply can take the else part(based on requirements though) of any verification process to trigger the screenshot capturing method. like-
if(condition){
//statements
}
else{
//statements
captureScreenshot();
}
This is the basic type of condition checking. This can be put after the Assert statements as well.
But this method can not capture screenshot of other types of test failure. It is always better to use onTestFailure() method of a class which is implemented TestListener interface. Like iTestListener of TestNG. Here iTestContext passes the driver object to the screenshot capturing method. However, we need to set up the same in the base class first.
Take a screenshot using FileUtils Class in Selenium
Older Selenium(version <3.6.0 ) used to provide FileUtils class to work with screenshots. Actually FileUtils is part of org.apache.commons.io. In the initial day, Selenium used to bundles this class along with the download.
FileUtil class provides File manipulation command. They are very generic in nature. It helps in the following way:
- deleting files and directories
- converting to and from a URL
- listing files and directories by filter and extension
- comparing file content
- file last changed the date
- calculating a checksum
- writing to a file
- reading from a file
- make a directory including parent directories
- copying files and directories
Many legacy frameworks may have this jar available and work fine. Below is a code example on FileUtils to capture screenshot in Selenium
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class Screen {
public static void main(String[] args) throws Exception {
System.setProperty("webdriver.chrome.driver", path of chrome driver.exe);
WebDriver driver = new ChromeDriver();
driver.get("www.google.com");
TakesScreenshot myScreen= (TakesScreenshot)driver;
File sourceFolder = myScreen.getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(sourceFolder , new File("./Screenshots/MyScreen.png"));
System.out.println("the Screenshot is taken");
driver.quit();
}
}
Take a screenshot using FileHandler Class in Selenium
Selenium(3.6.0 onwards) does not provide FileUtils class anymore. Instead, Selenium provides a FileHandler class to capture screenshots. The FileHandler class will also help to move from the source folder to the destination folder.
For FileHandler class, we need to follow the following steps:
- Import org.openqa.selenium.io.FileHandler to our project code.
- The code is as follows
FileHandler.copy(mytTs.getScreenshotAs(outputType.FILE),new File("D:\\Test\\Report\\Screenshots\\myScreen.png"));
The final code looks like:
import java.io.File;
import java.io.IOException;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.io.FileHandler;
import org.testng.annotations.Test;
public class ChromeHeadlessBrowser {
@Test
public void myTest()
{
// Set the chrome driver
System.setProperty("webdriver.chrome.driver","./chromedriver.exe");
// pass the option object in ChromeDriver constructor
WebDriver driver=new ChromeDriver();
// Provide any url
driver.get("www.google.com");
System.out.println("Title is "+driver.getTitle());
TakesScreenshot myts=(TakesScreenshot)driver;
try {
FileHandler.copy(myts.getScreenshotAs(OutputType.FILE),
new File("D\\Test\\Report\\Screenshot.png"));
}
catch (WebDriverException e) {
}
catch (IOException e) {
}
// Close the instance
driver.quit();
}
}
Take Screenshot in Selenium in a python way
Every WebDriver provides a .save_screenshot(filename) method. So for Firefox, it can be used like this:
from selenium
import webdriver
browser = webdriver.Firefox()
browser.get('http://www.google.com/')
browser.save_screenshot('screenie.png')
Take Screenshot in Selenium in a C# way
public void TakeScreenshot()
{
try
{
Screenshot myScreenshot= ((ITakesScreenshot)driver).GetScreenshot();
myScreenshot= .SaveAsFile(@"D:\Screenshots\SeleniumTestingScreenshot.jpg",
System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
throw;
}
}
Take Screenshot in Selenium in a C# way
public Bitmap TakeScreenshot(By by) {
// 1. Make screenshot of all screen
var screenshotDriver = _selenium as ITakesScreenshot;
Screenshot myScreenshot = screenshotDriver.GetScreenshot();
var myBmpScreen = new Bitmap(new MemoryStream(myScreenshot.AsByteArray));
// 2. Get screenshot of specific element
IWebElement myElement = FindElement(by);
var cropArea = new Rectangle(myElement.Location, myElement .Size);
return bmpScreen.Clone(cropArea, myBmpScreen.PixelFormat);
}
Take Screenshot in Selenium in a C# way using PhantomJS
using System;
using OpenQA.Selenium.PhantomJS;
using System.Drawing.Imaging;
namespace example.com {
class Program {
public static PhantomJSDriver driver;
public static void Main(string[] args) {
driver = new PhantomJSDriver();
driver.Manage().Window.Size = new System.Drawing.Size(1280, 1024);
driver.Navigate().GoToUrl("http://www.google.com/");
driver.GetScreenshot().SaveAsFile("screenshot.png", ImageFormat.Png);
driver.Quit();
}
}
}
Take Screenshot in Selenium in a JavaScript way
driver.takeScreenshot().then(function(data){
var base64Data = data.replace(/^data:image\/png;base64,/,"")
fs.writeFile("out.png", base64Data, 'base64', function(err) {
if(err) console.log(err);
});
});
Take Screenshot in Selenium in a Catalon- Cucumber way
WebUI.takeScreenshot()
Take Screenshot in Selenium in a PowerShell way
Set-Location PATH:\to\selenium Add-Type -Path "Selenium.WebDriverBackedSelenium.dll"
Add-Type -Path "ThoughtWorks.Selenium.Core.dll" Add-Type -Path "WebDriver.dll"
Add-Type -Path "WebDriver.Support.dll"
$driver = New-Object OpenQA.Selenium.PhantomJS.PhantomJSDriver
$driver.Navigate().GoToUrl("https://www.google.co.uk/")
# Take a screenshot and save it to filename
$filename = Join-Path (Get-Location).Path "01_GoogleLandingPage.png"
$screenshot = $driver.GetScreenshot()
$screenshot.SaveAsFile($filename, [System.Drawing.Imaging.ImageFormat]::Png)
Take Screenshot in Selenium in a Ruby- Cucumber way
After do |scenario| if(scenario.failed?)
puts "after step is executed" end time = Time.now.strftime('%a_%e_%Y_%l_%m_%p_%M')
file_path = File.expand_path(File.dirname(__FILE__)
+ '/../../../../../mlife_screens_shot')+'/'+time
+'.png' page.driver.browser.save_screenshot file_path end
Given /^snapshot$/ do time = Time.now.strftime('%a_%e_%Y_%l_%m_%p_%M')
file_path = File.expand_path(File.dirname(__FILE__) +
'/../../../../../mlife_screens_shot')+'/'+time +'.png'
page.driver.browser.save_screenshot file_path
end
Take Screenshot in Selenium in a Ruby way
require 'rubygems'
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :ie driver.get "https://www.google.com"
driver.save_screenshot("./screen.png")
Take Screenshot in Selenium in a PHP- PHPUnit way
class MyTestClass extends PHPUnit_Extensions_Selenium2TestCase {
...
public function screenshot($filepath) {
$filedata = $this->currentScreenshot();
file_put_contents($filepath, $filedata);
}
public function testSomething() {
$this->screenshot('/path/to/screenshot.png');
}
...
}
Take Screenshot in Selenium in a Jython way
import org.openqa.selenium.OutputType as OutputType
import org.apache.commons.io.FileUtils as FileUtils
import java.io.File as File
import org.openqa.selenium.firefox.FirefoxDriver as FirefoxDriver
self.driver = FirefoxDriver()
tempfile = self.driver.getScreenshotAs(OutputType.FILE)
FileUtils.copyFile(tempfile, File("C:\\screenshot.png"))
Using Java robot class
The third Option could be -This using pure java with robot class.
protected void takeScreenShotMethod(){
try{
Thread.sleep(10000);
long id = Thread.currentThread().getId();
BufferedImage image = new Robot().createScreenCapture(new Rectangle(
Toolkit.getDefaultToolkit().getScreenSize()));
ImageIO.write(image, "jpg", new File("./"
+ id + "screenshot.jpg"));
}
catch( Exception e ) {
e.printStackTrace();
}
}
Take Screenshot in Selenium in a Java way
void takeScreenShotMethod(){
try{
Thread.sleep(10000)
BufferedImage image = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
ImageIO.write(image, "jpg", new File("./target/surefire-reports/screenshot.jpg"));
}
catch(Exception e){
e.printStackTrace();
}
}
Take a screenshot in Selenium using third party tool
AShot API
AShot API is provided by Yandex that supports a Selenium WebDriver to capture a Screenshot in Selenium.
AShot API has the following capabilities:
- It can capture individual WebElement
- It can capture full page Screenshot.
AShot API Configuration
AShot API can be configured in two ways:
- With Maven or any other build tools
- By setting up Manually.
Configuration AShot using Maven
To setup AShot with Maven, we need to follow the following steps:
- Open the maven repository
- Check for the latest version
- Copy the dependency code from the Maven tab.
- Paste to your POM.xml
- Save POM.xml.
Now the framework can AShot without any issue. Also, note that AShot can work with Maven, Gradle, SBT, Ivy, Grape, Leiningen, Buildr tools seamless.
Configuration AShot Manually
To setup AShot manually, we need to follow the following steps:
- Open the maven repository
- Check for the latest version
- Click on the corresponding jar and download the same to the local computer.
- Open your editor(Eclipse)
- Open your project.
- Right-click on the project and navigate properties->buildpath->libraries->add external jars->select AShot jar
- Apply and close.
How to configure AShot API to capture a fullscreen screenshot?
AShot provides one method called takeScreenshot(). Using this method we can capture fullscreen screenshot in selenium.
The code is as follows:
Screenshot myScreen=new AShot().takeScreenshot(driver);
In case the page size is greater than the screen size, you need to use shootingStrategy() method to set up the policy.
This policy setup has to be done before taking the screenshot.
Screenshot myScreen=new AShot().shootingStrategy(ShootingStrategies.viewportPasting(N).takeScreenshot(driver));
Here N is scrolled out time in terms of milliseconds like-2000. So to take a screenshot, the code will scroll for 2000 milliseconds.
Now we need to save the screenshot. The corresponding code for that:
ImageIO.write(myScreen.getImage(),"jpg",new File(".\\testReport\\Screenshots\\newScreen.jpg"));
How to take a screenshot in Selenium for an element?
To capture a screenshot of the element, we need to use the overridden version of the takeScreenshot() method. This method accepts the driver along with the element.
Step-1- Create/ find the element
WebElement myElement=driver.findElement(By.id("xyz"));
Step-2- take the screenshot
Screenshot myScreenElement=new AShot().shootingStrategy(ShootingStrategies.viewportpasting(500))takeScreenshot(driver,myElement);
Step-3- Create an image
ImageIO.write(myScreenElement.getImage(),"jpg",new File("".\\testReport\\Screenshots\\newScreen.jpg")");
How to compare image using AShot API?
AShot provides ImageDiffer class to compare two images. Assume a scenario where we have to compare two images(like a logo). So the one will be coming from the application and the other one will be coming from the saved location like test data.
Step-1– take one from application
WebElement myElement=driver.findElement(By.id("logo"));
Step-2– take one from test data
BufferedImage myExpectedLogo=ImageIO.read(new File("D:\\Test\\TestData\\logo.jpg""));
Step-3- Extract image from element
BufferedImage actualLogo=myElement.getImage();
Step-3- Now compare both the image and print message accordingly.
ImageDiffer isImageDiffer=new ImageDiffer();
ImageDiff isDiff=isImageDiffer.makeDiff(actualLogo,myExpectedLogo);
if(isDiff.hasDiff()==true){
System.out.println("Images are equal");
}
else{
System.out.println("Images are equal");
}
Using Apache Commons Library
Screenshot automation can also be achieved using Apache Commons Library via FileUtils class. For that, we need to follow the below steps:
- Download the commons library.
- Add manually to your IDE or project.
- If you are using Maven, then go to the Maven tab and copy the dependency codes to your POM.xml file.
How to compare two screens using Selenium?
This is applicable mostly when we compare the same page in two different Time stamps like before the event and after the event. In this case, we will take help WebDriver’s BASE64 type
The corresponding code is as follows:
String screen1=((TakesScreenshot)driver).getScreenshotAs(OutputType.BASE64);
//event code
Thread.sleep(5000);
String screen2=((TakesScreenshot)driver).getScreenshotAs(OutputType.BASE64);
if(screen1.equals(screen2)){
System.out.println("screens are equal");
}
else{
System.out.println("screens are not equal");
}
How to add screenshots to PDF file?
There may be times, when a customer may ask to convert these screenshots to a PDF file. Just to make these screens as a single file. This will also help to upload to a repository.
In that case, the raw selenium will not be able to convert the screens to PDF. We need to take help of any PDF-related jars.
The below section is written based on the iText jar that helps to convert the screens to PDF. So to use this jar, we need to down the jar and attach to the project.
The code is as follows:
byte[] screen=((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
//takes the screenshot as byte array
Document doc=new Document();
//Document is the placeholder present in the iText class
//to create a place for the screens
FileOutputStream fos=new FileOutputStream(output);
//FileOutputStream will store PDF data.
PdfWriter pw=PdfWriter.getInstance(doc,fos);
pw.open();
//PdfWriter is going to add screenshot to the PDF file.Being singleton,it provides
//getInstance() method to create object.
Image img=Image.getInstance(screen);
//Create and store the actual image even if it is in different format.
img.scaleToFit(pageSize.A4.getWidth()/2,pageSize.A4.getHeight()/2);
//This is just to provide width and height criteria
The whole code looks like:
import java.io.FileOutputStream;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
public class MyPDFGenerator{
public static void main(String[] args) throws Exception {
System.setProperty("webdriver.chrome.driver", "D:Eclipse progsdriverserverchromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
driver.get("www.google.com");
// take the screenshot and store it in byte[] array format
byte[] input = ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
Document document = new Document();
String output = "C:\\Test\\"+ nameOfPDF+ ".pdf";
FileOutputStream fos = new FileOutputStream(output);
// Instantiate the PDF writer
PdfWriter writer = PdfWriter.getInstance(document, fos);
// open the pdf for writing
writer.open();
document.open();
// process content into an image
Image im = Image.getInstance(input);
//set the size of the image
im.scaleToFit(PageSize.A4.getWidth()/2, PageSize.A4.getHeight()/2);
// add the image to PDF
document.add(im);
document.add(new Paragraph(" "));
//close the files and write to local system
document.close();
writer.close();
}
}
Best Practises while selenium takes a screenshot
This section will explain in details what are the right ways to take screenshots in selenium. Depending on the need screenshot in selenium can be taken with full screen and without a full screen, with a background screen or a full page.
- Start browser with full-screen mode.
- Always highlight the element before taking the screenshot. Once the element is high lighted, then take the screenshot.
WebElement ele=driver.findElement(By.id("logo"));
//now use javascript executor to high light the screen
JavascriptExecutor je=(JavascriptExecutor)driver;
je.executeScript("arguments[0].style.border=5px solid red",ele);
//now take the screenshot
- Start browser in a headless way.
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--headless");
ChromeDriver driver = new ChromeDriver(chromeOptions);
Conclusion
In today’s world, a bug is not considered for fixing, if it is not having a screenshot or video attached to it. Apart from this, a screenshot also helps the development team to understand the underlying issue. So it is extremely important to take a screenshot while executing scripts via automation.
Hey! Would you mind if I share your blog with my myspace group? There’s a lot of folks that I think would really appreciate your content. Please let me know. Thank you
A person necessarily assist to make severely posts I might state. This is the very first time I frequented your website page and so far? I amazed with the research you made to make this actual post extraordinary. Magnificent job!
It’s exhausting to seek out educated individuals on this topic, but you sound like you already know what you’re speaking about! Thanks
Aw, this was an exceptionally good post. Taking a few minutes and
actual effort to generate a superb article… but what can I say…
I put things off a lot and don’t manage to get nearly anything done.
Excellent web site. A lot of useful information here. I am sending it to some buddies ans also sharing in delicious. And obviously, thank you for your effort!