Take Screenshot in Selenium

Test cases may fail while executing the test suite in selenium automation. When manual tester faces any discrepancy in the verification, i.e., when there is a difference in actual and expected values, manual testers tend to take screenshots as proof for failure.

We can also take screenshots using Selenium.

Failures may occur because of below reasons:

  • Actual and Expected values are not matching
  • When there is no element
  • When the page takes more time to load
  • When an unexpected alert comes in to focus
  • When there are Assertion issues

We can take a screenshot of a webpage in selenium using getScreenshotAs() method, Webdriver interface doesn't provide a method to take a screenshot.

There is an interface called TakesScreenshot which provides the getScreenshotAs() method and which selenium uses to take a screenshot.

Our browser classes (Like ChromeDriver, FirefoxDriver) extends RemoteWebdriver, and RemoteWedriver implements TakesScreenshot Interface along with Webdriver Interface.

So we have screenshot method implementations in our driver classes. This process is called Multiple Inheritance in java, i.e., Class(browser) implementing two Interfaces(Webdriver and TakesScreenshot).

We can Take two kind of screenshots:
  1. Webpage Screenshot
  2. WebElement Screenshot

Syntax : getScreenshotAs(OutputType target)

We can store the captured screenshot in different formats; all the formats are present in the OutputType interface.

Formats available in the OutputType Interface:

  1. OutputType.BASE64
  2. OutputType.BYTES
  3. OutputType.FILE

We can convert all the above output types into png images; we will discuss those later parts of this tutorial.

Robot Class in selenium

Take Webpage Screenshot

We can take a screenshot of a webpage using the getScreenshotAs() method from the TakesScreenshot, but we cannot initialize TakesScreenshot as it is an interface

So to take a screenshot of the page, we have to cast our driver object to the TakesScreenshot interface type by adding the below code.

((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);

In the above code, we are using the getScreenShotAs method after casting the driver object to the TakesScreenshot interface type.

Selenium Webdriver tries to capture the screen in the below sequence, if first fails, webdriver tries to take second and so on..

  • Tries to take a screenshot of the Entire page
  • Tries to screenshot of the current window
  • The Visible portion of the current frame
  • The screenshot of the entire display containing the browser


Steps to take a page-level screenshot:
1. Open the browser and navigate to the application.
2. Set implicit wait to find the element time limit.

// set time limit to find the element
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);


3. Take a screenshot, using getScreenshotAs method from selenium webdriver, Store the image object as FILE.

// Take a ScreenShot and set the output as FILE type
File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);


4. Copy or Write the Image File into your local system as a png extension.

5. The file has been saved in the format, i.e., 'png'? as mentioned in the script. We can save the image in different file formats like PNG, JPEG, GIF, BMP

If we do not save, the file will be destroyed when JVM exits.

// store the screenshot to your local machine
FileUtils.copyFile(scrFile, new File("D:pageScreenshot.png"), true);


Complete program to take a screenshot in selenium webdriver with java

import java.io.File;
import java.util.concurrent.TimeUnit;
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.firefox.FirefoxDriver;

public class PageScreenShot {
	public static void main(String[] args) throws Exception {
		// set the geckodriver.exe property
		System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
		WebDriver driver =new FirefoxDriver();
		driver.manage().window().maximize();
		// set time limit to find the element
		driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
		// Go to URL
		driver.get("https://chercher.tech/selenium-webdriver-sample");
		// Take a ScreenShot
		File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
		FileUtils.copyFile(scrFile, new File("D:pageScreenshot.png"), true);

		// Close Driver
		driver.quit();
	}
}

Frames in selenium

Take Screenshot of WebElement

Let's learn how to capture the screenshot of a specific element rather than the entire page using Selenium Webdriver.

As of this month (December 2017), no browser class like FirefoxDriver, ChromeDriver, or any other browser driver supports this operation.

Selenium is nothing but a native method invoker; selenium invokes all the javascript methods present inside a browser when there is no such javascript method to take a screenshot in a browser, selenium fails to call that method and throws org.openqa.selenium.UnsupportedCommandExceptionException.

Browsers may support this method in the future, and we may able to take a screenshot of the element using the inbuilt method.

Now let us see how to take a screenshot without using element.getScreenshotAs method.

Steps to take a screenshot element:
1. Open the browser and navigate to Url:
2. Find the element and Store the element as 'element.'

//Locate Image element to capture a screenshot.
WebElement element = driver.findElement(By.xpath("//input"));


3. Take the screenshot of the full page, with output type as FILE

//Capture entire page screenshot as File.
//set OutputType Interface of selenium and File class of java
//to capture screenshot of the entire page.
File screen = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);


4. Get the location of the element using the getLocation() method in selenium from the stored element.

//Use selenium Point class to get x y coordinates of the Image element.
//get location(x y coordinates) of the element.
Point point = element.getLocation();
int xcordinate = point.getX();
int ycordinate = point.getY();

5. Get the size of the element using the getSize() method from selenium

//Use selenium getSize() method to get height and width of element.
//Retrieve width of element.
int imageWidth = element.getSize().getWidth();
//Retrieve height of element.
int imageHeight = element.getSize().getHeight();


6. Create an object for the BufferedImage class using Image.read(imageStored); this class will be helpful for image processing operations.

//Reading full image screenshot.
BufferedImage img = ImageIO.read(screen);


7. Use the getSubimage method from BufferedImage, pass coordinates, and width and height for sub-image. sub-image is nothing but our element. Store the processed image on your machine

//cut Image using height, width and x y coordinates parameters.
BufferedImage destination = img.getSubimage(xcoordinate, ycoordinate, imageWidth, imageHeight);
ImageIO.write(destination, "png", screen);

//save Image screenshot In D: drive.
FileUtils.copyFile(screen, new File("D:screenshotOfElement.png"));


Program to take a screenshot of Web Element.

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Point;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

public class GetElementSCreenShot {
	public static void main(String[] args) throws Exception {
		  // set the geckodriver.exe property
		  System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
		  WebDriver driver =new FirefoxDriver();
		  driver.manage().window().maximize();
		  driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
		  driver.get("https://chercher.tech/selenium-webdriver-sample");

		  //Locate Image element to capture a screenshot.
		  WebElement element = driver.findElement(By.xpath("//input"));

		  //Capture entire page screenshot as File.
		  //Used TakesScreenshot, OutputType Interface of selenium and File class of java to capture a screenshot of the entire page.
		  File screen = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);

		  //Used selenium Point class to get x y coordinates of Image element.
		  //get location(x y coordinates) of the element.
		  Point point = element.getLocation();
		  int xcordinate = point.getX();
		  int ycordinate = point.getY();

		  //Used selenium getSize() method to get height and width of element.
		  //Retrieve width of element.
		  int imageWidth = element.getSize().getWidth();
		  //Retrieve height of element.
		  int imageHeight = element.getSize().getHeight();

		  //Reading full image screenshot.
		  BufferedImage img = ImageIO.read(screen);

		  //cut Image using height, width and x y coordinates parameters.
		  BufferedImage destination = img.getSubimage(xcordinate, ycordinate, imageWidth, imageHeight);
		  ImageIO.write(destination, "png", screen);

		  //save Image screenshot In D: drive.
		  FileUtils.copyFile(screen, new File("D:screenshotOfElement.png"));
	}
}

screenshot-selenium-webdriver

Exceptions in selenium

Convert BASE64 to an image using convertFromBase64Png

We have inbuilt methods to convert the BASE64 string into an image, convertFromBase64Png used to convert the BASE64 string to an image file(image extension could be anything like png, jpg,tif...).

Steps to Convert BASE64 string to an image :
1. Take a screenshot as BASE64 format

// Take a ScreenShot
String scrBase64 = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);


2. Use the convertFromBase64Png method from the OutputType.FILE and pass the stored BASE64 string to the method.

File file = OutputType.FILE.convertFromBase64Png(scrBase64);


3. Write the image file to the local system

FileUtils.copyFile(file, new File("D:BASE64-Conerted-Image.png"), true);


Complete program to convert BASE64 to an image

public class BASE64toImageInbuiltMethod {
	public static void main(String[] args) throws Exception {
		// set the geckodriver.exe property
		System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
		WebDriver driver =new FirefoxDriver();
		driver.manage().window().maximize();

		// set time limit to find the element
		driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

		// Go to URL
		driver.get("https://chercher.tech/selenium-webdriver-sample");

		// Take a ScreenShot
		String scrBase64 = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);
		// convert the BASE64 to File type
		File file = OutputType.FILE.convertFromBase64Png(scrBase64);
		// store the converted file as Image on D driver
		FileUtils.copyFile(file, new File("D:BASE64-Conerted-Image.png"), true);
  }
}

Listeners in selenium

Convert BYTES screenshot to an image in selenium Webdriver

We have inbuilt methods to convert the BYTES screenshot into an image, convertFromPngBytesused to convert the BYTES string to an image file(image extension could be anything like png, jpg,tif...).

Steps to Convert BYTES string to an image :
1. Take a screenshot as BYTES format

// Take a ScreenShot
byte[] scrBytes = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);


2. Use the convertFromBase64Png method from the OutputType.FILE and pass the stored BASE64 string to the method.

// convert the Bytes to File type
File file = OutputType.FILE.convertFromPngBytes(scrBytes);


3. Write the image file to the local system

// store the converted file as Image on D driver
FileUtils.copyFile(file, new File("D:Bytes-Conerted-Image.png"), true);


Complete program to convert BYTES to an image

public class BytesToImage {
	public static void main(String[] args) throws Exception {
		// set the geckodriver.exe property
		System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
		WebDriver driver =new FirefoxDriver();
		driver.manage().window().maximize();

		// set time limit to find the element
		driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

		// Go to URL
		driver.get("https://chercher.tech/selenium-webdriver-sample");

		// Take a ScreenShot
		byte[] scrBytes = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
		// convert the Bytes to File type
		File file = OutputType.FILE.convertFromPngBytes(scrBytes);
		// store the converted file as Image on D driver
		FileUtils.copyFile(file, new File("D:Bytes-Conerted-Image.png"), true);
  }
}

Xpath in Selenium

Convert OutputType.BASE64 to an image without using in-built Methods

We cannot directly convert BASE64 into an image; we have to take the help of java image related classes to overcome this situation.

Steps to convert the BASE64 to an image:


1. Take a Screenshot as OutputType.BASE64

// Take a ScreenShot
String scrBase64 = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);


2. Convert the BASE64 data into bytes[] array using the decodeBase64 method from the BASE64 class.

// decode the base4 to bytes,
byte[] base64Val=Base64.decodeBase64(scrBase64);


3. Create a file with image extension 'png or jpg', here we are just creating a file (place holder) not the image

//create an image file in local system
File imgFile = new File("D:pageScreenshotBASE64.png");


4. Convert the bytes array into an image using ByteArrayInputStream and store it as BufferedImage type.

// convert the bytes to an image using ImageIo class
BufferedImage img = ImageIO.read(new ByteArrayInputStream(base64Val));


5. Write the image into the image file

// write the image to the image file that we have created
ImageIO.write(img, "png", imgFile);


Complete program for Converting Screenshot OutputTYpe.BASE64 to an image in selenium webdriver

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import org.apache.commons.codec.binary.Base64;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class Base64ToImage {

  public static void main(String[] args) throws Exception {
		// set the geckodriver.exe property
		System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
		WebDriver driver =new FirefoxDriver();
		driver.manage().window().maximize();

		// set time limit to find the element
		driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

		// Go to URL
		driver.get("https://chercher.tech/selenium-webdriver-sample");

		// Take a ScreenShot
		String scrBase64 = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);

		// decode the base4 to bytes,
		byte[] base64Val=Base64.decodeBase64(scrBase64);

		//create an image file in local system
		File imgFile = new File("D:pageScreenshotBase64.png");

		// convert the bytes to an image using ImageIo class
		BufferedImage img = ImageIO.read(new ByteArrayInputStream(base64Val));

		// write the image to the image file that we have created
		ImageIO.write(img, "png", imgFile);
  }
}

CSV files in selenium

Convert Bytes Screenshot to an image in Selenium Webdriver without using in-built Methods

We can convert the OutputType.BYTES to an image, selenium doesn't provide any methods to convert perform this operation too. Again we have to Depend on Java Image processing classes.

Steps to convert the BASE64 to an image:


1. Take a Screenshot as OutputType.BASE64

// Take a ScreenShot
String scrBytes = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);


2. Create a file with image extension 'png or jpg', here we are just creating a file (place holder) not the image

//create an image file in local system
File imgFile = new File("D:pageScreenshotBytes.png");


3. Convert the bytes array into an image using ByteArrayInputStream and store it as BufferedImage type.

// convert the bytes to an image using ImageIo class
BufferedImage img = ImageIO.read(new ByteArrayInputStream(scrBytes));


4. Write the image into the image file

// write the image to the image file that we have created
ImageIO.write(img, "png", imgFile);


Complete program for Converting Screenshot OutputType.Bytes to an image in selenium webdriver

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class ConvertBytesToImage {
	public static void main(String[] args) throws Exception {
		// set the geckodriver.exe property
		System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
		WebDriver driver =new FirefoxDriver();
		driver.manage().window().maximize();

		// set time limit to find the element
		driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

		// Go to URL
		driver.get("https://chercher.tech/selenium-webdriver-sample");

		// Take a ScreenShot
		byte[] scrBytes = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);

		//create an image file in local system
		File imgFile = new File("D:pageScreenshotBytes.png");

		// convert the bytes to an image using ImageIo class
		BufferedImage img = ImageIO.read(new ByteArrayInputStream(scrBytes));

		// write the image to the image file we have created
		ImageIO.write(img, "png", imgFile);
  }
}

QR Code in selenium

Highlight the Element in screenshot using Selenium webdriver

Scenario : I want to take a screenshot of my webpage, and I want to highlight the element, how to do it?

Solution :

  • Do not exactly do what asked in the question, but understand the scenario.
  • They expect a screenshot with element highlighted
  • First, highlight the element instead of taking a screenshot.
  • Once the element is been highlighted take the screenshot.

Steps to take the screenshot with a highlighted element
1. Open the browser and navigate to URL
2. Find the web element and store it

// store the webelement
WebElement element_node = driver.findElement(By.xpath("//input"));


3. Pass the webelement to javascript Executor

// pass the stored webelement to javascript executor
JavascriptExecutor jse = (JavascriptExecutor) driver;


4. Highlight the element using the style property

// highlight the element with red border 3px width
jse.executeScript("arguments[0].style.border='3px solid red'", element_node);


5. Take the screenshot of the webpage

// Take the ScreenShot
File file = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);

// store the converted file as Image on D driver
FileUtils.copyFile(file, new File("D:Element With Highlight.png"), true);


Complete the program to take a screenshot with the highlighted element.

public class HighLightElementInScreenshot {
	public static void main(String[] args) throws Exception {
		// set the geckodriver.exe property
		System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
		WebDriver driver =new FirefoxDriver();
		driver.manage().window().maximize();

		// set time limit to find the element
		driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

		// Go to URL
		driver.get("https://chercher.tech/selenium-webdriver-sample");
		// store the webelement
		WebElement element_node = driver.findElement(By.xpath("//input"));
		// pass the stored webelement to javascript executor
    JavascriptExecutor jse = (JavascriptExecutor) driver;
    // highlight the element with red border 3px width
    jse.executeScript("arguments[0].style.border='3px solid red'", element_node);
    // added sleep to give little time for browser to respond
    Thread.sleep(3000);

		// Take the ScreenShot
		File file = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);

		// store the converted file as Image on D driver
		FileUtils.copyFile(file, new File("D:Element With Highlight.png"), true);
  }
}

element-highlight-screenshot-selenium

Log4J in selenium

Compare Screenshots in Selenium

Sometimes we may have situations where we have to compare the two screenshots. We can compare the screenshot using methods present in the selenium webdriver.
We can do it in a straightforward way.

1. Take the screenshots as BASE64 outputType. Consider we have screenshot-1 and screenshot-2 namely.

2. Compare the BASE64 strings using .equals methods present in java, Similar to comparing two strings

// PLEASE DO WRITE IMPORT STATEMENTS
public class CompareScreenshots {
	public static void main(String[] args) throws Exception {
		// set the geckodriver.exe property
		System.setProperty("webdriver.gecko.driver", "C:/PATH/geckodriver.exe");
		WebDriver driver =new FirefoxDriver();
		driver.manage().window().maximize();

		// set time limit to find the element
		driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

		// Go to URL
		driver.get("https://chercher.tech/selenium-webdriver-sample");

		// Take ScreenShot
		 String screenshot_1 = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);
		 Thread.sleep(2000);
		 String screenshot_2 = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);

		if(screenshot_1.equals(screenshot_2)){
			System.out.println("Screenshots are matching");
		}
		else{
			System.out.println("Screenshots are NOT matching");
		}
  }
}

Custom Locators in Selenium

Add Screenshot to PDF File

With selenium, we can take a screenshot but only with the help of java we can store the screenshot in the format of the image file

Sometimes we may need to store the captured screenshot in a PDF file while running the selenium tests. But selenium doesn't facilitate this, so we have to take the help of libraries present in the Java language.

iText jar files provide the utility to take the screenshot and store the screenshot in PDF file.

To store the screenshot in PDF file, either we have to store it in a file system as an image after capturing the screenshot type as FILE, but that is a complex job.

So we would be storing the screenshot as bytes[] array, and we would be passing it to the iText utility classes.

Steps to store screenshot in PDF file in Selenium :

1. Capture the screenshot in the format of byte array,

byte[] input = ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);


2. We have to create an object for Document class present in the Itext package, this document serves as a place where the metadata of the image is stored before pushing into the PDF.

Document document = new Document();


3. Create an object to FileOotputStream, with which we can store the PDF file in the required location

FileOutputStream fos = new FileOutputStream(output);


4. Now create the object to the PDFWriter, this class is going to write the document which had metadata into Actual PDF file. If you notice one thing in this class; the class uses singleton pattern, that is the reason it provides the getInstance() method to create the object, rather than providing direct access of Constructor to the Users

PdfWriter writer = PdfWriter.getInstance(document, fos);
writer.open();


5. Create the Actual image by providing the image content as a parameter; in our case, image content is byte[] array. This step is useful when an image is stored in other formats than an image like bytes, URL.

Image im = Image.getInstance(input);


6. Set the image size; I am setting the image into half the size of an A4 sheet. A4 sheets are nothing but the sheets used for exams (other than graphical exams). Instead of a given value to the image size, it is always better to give the size based on the pre-existing values, like I did.

// get the half size of the A4 sheet size
im.scaleToFit(PageSize.A4.getWidth()/2, PageSize.A4.getHeight()/2);


7. Add the image into PDF file using add() method present in the document object.

8. Close the document, PDFWriter. Closing PDF writer will actually write the PDF into your local system.

The Complete code for Storing the image/screenshot in PDF file.

package test;

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 GeneratePDF {
	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("https://chercher.tech/java/index-selenium-webdriver");

		// take the screenshot and store it in byte[] array format
		byte[] input = ((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES);
		Document document = new Document();
	    String output = "C:UsersuserDesktopip" + "nameOfFile" + ".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();
    }
}

The output of the screenshot to pdf program screenshot-to-pdf-selenium-itext

POM | Featured in selenium

Implement Screenshots to PDF in Framework

I know your obvious question from the above topic that, I do not think Our framework will work only with one screenshot, Frameworks will have to handle a series of screenshots

I will give an idea about how you can achieve it :

  • Before Proceeding, you have to decide whether you are only going to follow, sequential run, or parallel run, I consider as Parallel run and We can achieve the sequential run with the parallel run.
  • In a parallel running, you cannot predict the order of execution and I am considering that Parallel run based on class (useful in case of An ArrayList variable which is used in below steps)
  • Create a method called writeScreenShotToDocument() in your framework either as static or non-static, if you have chosen Sequential running then you can implement this method without accepting the parameter but creating a Static ArrayList which accepts byte[] array.
  • If you have Chose Parallel running, then you can create the writeScreenShotToDocument(ArrayList<byte[]> byteArray), after this create a non-static variable for storing the screenshot of the class
  • writeScreenShotToDocument method should hold the code to write the images to the document, make sure you are not pushing the image into PDF writer.
  • Create @afterClass and call this writeScreenShotToDocument method
  • Create a method called writeScreenShotDocumentToPDF, and this method should push the code to PDF and then to the local file system.
  • I hope you have some logic for taking a screenshot like take a screenshot on failure, take a screenshot on change of URL so on., with that logic when you take a screenshot to push the value into the ArrayList variable
  • On @AfterSuite call writeScreenShotDocumentToPDF method, which pushes the code into PDF writer, then stores the pdf to the local system.
  • At the end of your execution, you will have the PDF file with Screenshots.

Pdf logic class GeneratePDF.java

package test;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;

public class GeneratePDF {
	static Document document = new Document();
	static PdfWriter writer ;

	static {
		FileOutputStream fos;
		try {
			fos = new FileOutputStream("C:PATHip" + "series of screenshots" + ".pdf");
			writer = PdfWriter.getInstance(document, fos);

			// open the pdf for writing
			writer.open();
			document.open();
		} catch (Exception e) {
			System.out.println("Exception occured");
			e.printStackTrace();
		}
	}

	public static void writeScreenShotToDocument(ArrayList byteArray) throws Exception {
		System.out.println("writeScreenShotToDocument started########## : "+byteArray.size());
		Image im = null;
		for (byte[] bytes : byteArray) {

			// process content into an image
			im = Image.getInstance(bytes);
			//set the size of the image
			im.scaleToFit(PageSize.A4.getWidth()/2, PageSize.A4.getHeight()/2);

			document.add(new Paragraph(" "));
			document.add(new Paragraph("Chercher Tech website"));

			// add the image to PDF
			document.add(im);
			System.out.println("added");
		}
	}

	public static void writeScreenShotDocumentToPDF() throws Exception {
		System.out.println("writeScreenShotDocumentToPDF started@@@@@@@@@ ");

		//close the files and write to the local system
		document.close();
		writer.close();
	}
}

Out testing class Sample.java

package test;

import java.util.ArrayList;
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 org.testng.annotations.AfterClass;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

public class Sample {
	// keep it as non static only
	ArrayList screenshots;
	@BeforeClass
	public void beforeClass() {
		System.out.println("Before Method++++++++++++++++++");
	}

	@Test
	public void OpenGoogleCherchertech() {
		screenshots = new ArrayList();
		System.setProperty("webdriver.chrome.driver", "D:PATHchromedriver.exe");
		WebDriver driver = new ChromeDriver();
		driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
		driver.get("https://google.com");

		// take the screenshot 1 and store it
		screenshots.add(((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES));

		driver.get("https://chercher.tech/java/index-selenium-webdriver");
		// take the screenshot 2 and store it
		screenshots.add(((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES));
	}

	@AfterClass
	public void AfterClass() throws Exception {
		System.out.println("AfterClass^^^^^^^^^^^^^^^^^^");
		GeneratePDF.writeScreenShotToDocument(screenshots);
	}

	@AfterSuite
	public void AfterSuite() throws Exception {
		System.out.println("AfterSuite************************");
		GeneratePDF.writeScreenShotDocumentToPDF();
	}

}

The Output of the program multiple-screenshots-selenium-itext

document.add(new Paragraph(" "));  // adds new line
document.add(new Paragraph("Chercher Tech website"));	// adds text content to the pdf

Explicitly Wait

Comment / Suggestion Section
Point our Mistakes and Post Your Suggestions
  • Yasser Khalil
    Thank you very much for this awesome tutorial. I didn't face any problems except in the last section "Implement Screenshots to PDF in Framework" .. Can you give steps as I am newbie at Java ..?
    Reply
  • Hi,
    
    
    Is there any by which we can update the name of the file or give any dynamic name to the file.
    
    
    
    Reply
  • Hari
    Reply
  • Rudragouda Desai
    Awesome... A big salute to your knowledge on selenium and the way you put that into words is impeccable. Thank you so much for all your posts so far and request you to keep posting new topics. 
    Reply