take Screenshot in selenium
take Screenshot in selenium

Table of Contents

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.

  1. Using Selenium WebDriver
  2. Using Robot Class-Java
  3. 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:

  1. Convert the WebDriver to TakesScreenshot object.
  2. use getScreenshotAs() method to provide the type of picture.
  3. copy the file from temp to the destination location.
READ  How To Start And Stop Selenium Server From Eclipse

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.

READ  How To Start With Web Testing With 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.

READ  How To Resolve UnhandledAlertException While working with Alert Box in WebDriver in Selenium

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.

2 COMMENTS

  1. Hi! Someone in my Myspace group shared this site with us so I came to give it a look.

    I’m definitely enjoying the information. I’m bookmarking and will be tweeting this to
    my followers! Superb blog and terrific style and
    design.

LEAVE A REPLY

Please enter your comment!
Please enter your name here