How to Take Screenshots with Selenium WebDriver

While performing manual testing we often take screenshots of the broken pages or bugs to use them as evidence and they are very useful in convincing the developers. Similarly, in automation Selenium provides us the commands to capture screenshots of the webpages.

In this tutorial, we will learn to take full screenshots and partial screenshots of the webpage which is currently under test. We can also write some code logic to capture screenshots on every failure screen. That's a bit advanced-level concept. But in this post, we'll learn to take screenshots whenever we want. We also have to do some file-handling operations while taking and saving screenshots with Selenium WebDriver.

Table of Contents:

1. Take a Full Screenshot with Selenium
1.1. File
1.2. TakeScreenshot
1.3. FileUtils
1.4. Example Program to take Full Screenshot with Selenium WebDriver

2. Take a Partial Screenshot with Selenium
2.1. Take a Partial Screenshot of the Element using other image libraries
2.2. Take the Partial Screenshot of the Element using Selenium Command

3. Take a Screenshot When a Test fails using TestNG Listener
3.1. Create a Custom TestNG Listener
3.2. Add the listener to the test class using the Listener annotation

1. Take a Full Screenshot with Selenium

'TakeScreenshot' is the interface that is used to capture screenshots in Selenium WebDriver. Let's discuss the code to take screenshot step by step:

1.1. File

It is one of the inbuilt Java classes which is used for File handling operations, like opening a new file, reading/writing a file, etc. For taking screenshot first thing is to create an object of the File class so that we can save the screenshot in that object.


/* Create object of File class of Java */

File screenshot = some selenium code


1.2. TakeScreenshot

It is a Selenium interface that is used to take screenshots. 
  • Pass the WebDriver object to the TakeScreenshot interface constructor, which we create at the beginning of every script. 
  • Then we'll call the getScreenshotAs() method from TakeScreenshot.
  • Pass the parameter OutputType.FILE which will return the screenshot as a file.
  • That's why we created a File object in step 1 to save this screenshot.
So, let's complete the syntax from Step 1


/* Capture screenshot using getScreenshotAs() method of Webdriver
 * Set Output type of screenshot as 'FILE'
*/

File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);


1.3. FileUtils

It is the inbuilt utility of Java that is used to perform operations like copying a file, moving a file, etc.
  • We'll call copyFile() method of FileUtils class, simply using '.' dot operator. 
  • You must have observed that we have not created the object of FileUtils for calling copyFile() because it's a static method. And static methods can be called by simply using the dot (.) operator with a class name in Java. You do not need to create an object for it.\
  • Now we'll pass two parameters to copyFile() method.
    • Screenshot object which we created in the first step.
    • Path of your local system where you want to save the screenshot.

/* Use FileUtils class of Java 
 * Call it's copyFile method
 * Copy screenshot file to a location with some name and extension you want
*/

FileUtils.copyFile(screenshot, new File("D:\\screenshot.jpg"));



Example Program to take Full Screenshot with Selenium WebDriver:


public class CaptureScreenshot {

    // Main Method is the execution point of any Java Program
    public static void main(String[] args){

	// Initialize Webdriver Object
	System.setProperty("webdriver.chrome.driver", "D:\\chromedriver.exe");
	WebDriver driver = new ChromeDriver();

	// Open URL
	driver.get("https://www.techlistic.com/p/selenium-tutorials.html");

	// Set Chrome window size
	driver.manage().window().setSize(new Dimension(1552, 840));

	// Enter Firstname
	driver.findElement(By.name("firstname")).sendKeys("Tom");
	// Set Lastname
	driver.findElement(By.name("lastname")).sendKeys("Wood");

	// Create File object and save screenshot of current webpage inside it
	File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

	// Copy screenshot file to a location with some name and extension you want
	FileUtils.copyFile(screenshot, new File("D:\\screenshot.jpg"));
	
	// Close browser
	driver.close();
		
  }
}


2. Take a Partial Screenshot with Selenium

Sometimes we don't want to take a screenshot of the full screen. The reasons might be, full-size images would last in huge memory storage for the image directory or sometimes we need to take element-specific screenshots due to test case requirements which makes more sense.

2.1. Take a Partial Screenshot of the Element using other image libraries

An example code that demonstrates how to take a partial screenshot of an element using the AWT (Abstract Window Toolkit) library:

java
import org.openqa.selenium.By; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; public class PartialScreenshotExample { public static void main(String[] args) { // Set the path to the chromedriver executable System.setProperty("webdriver.chrome.driver", "path/to/chromedriver"); // Create an instance of ChromeDriver WebDriver driver = new ChromeDriver(); // Navigate to the desired page driver.get("https://www.example.com"); // Find the element to capture WebElement element = driver.findElement(By.id("myButton")); // Take the partial screenshot File screenshotFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); // Define the destination path for the screenshot String destinationPath = "path/to/save/screenshot.png"; // Crop the screenshot based on the element's location and dimensions try { // Load the screenshot as a BufferedImage BufferedImage fullScreenshot = ImageIO.read(screenshotFile); // Get the location and dimensions of the element Point elementLocation = element.getLocation(); int elementWidth = element.getSize().getWidth(); int elementHeight = element.getSize().getHeight(); // Create a new BufferedImage for the partial screenshot BufferedImage partialScreenshot = fullScreenshot.getSubimage(elementLocation.getX(), elementLocation.getY(), elementWidth, elementHeight); // Save the partial screenshot to the destination path ImageIO.write(partialScreenshot, "png", new File(destinationPath)); System.out.println("Partial screenshot saved successfully."); } catch (IOException e) { System.out.println("Failed to save the screenshot: " + e.getMessage()); } // Close the browser driver.quit(); } }

Here's an explanation of the code for taking a partial screenshot of an element using other image libraries:

1. Set up Selenium WebDriver:
  • The code starts by setting the path to the chromedriver executable and creating an instance of the ChromeDriver.
2. Navigate to the desired page:
  • The WebDriver navigates to the desired page using the get() method.
3. Find the element to capture:
  • The findElement() method is used to locate the element on the web page. In this example, we're finding an element with the ID "myButton".
4. Take the partial screenshot:
  • The getScreenshotAs() method captures a full screenshot of the web page and returns it as a File object.
5. Define the destination path for the screenshot:
  • A destination path is specified where the partial screenshot will be saved.
6. Crop the screenshot using AWT:
  • The ImageIO.read() method is used to load the full screenshot as a BufferedImage.
  • The location and dimensions of the element are obtained using the getLocation() and getSize() methods.
  • The getSubimage() method is called on the full screenshot BufferedImage to extract the region corresponding to the element.
  • The extracted region is stored in a new BufferedImage called partialScreenshot.
7. Save the partial screenshot:
  • The ImageIO.write() method is used to save the partialScreenshot as a PNG image to the specified destination path.
8. Handle exceptions and close the browser:
  • Exceptions are caught in case there is an error during the process of capturing or saving the screenshot.
  • The browser is closed using the quit() method to clean up resources.
This code utilizes the AWT library, specifically the BufferedImage class and the ImageIO class, to manipulate and save the partial screenshot. The getSubimage() method is used to crop the full screenshot based on the location and dimensions of the element.

Remember to replace the placeholder paths and IDs with the appropriate values for your specific use case.

2.2. Take the Partial Screenshot of the Element using Selenium Command:

To take a partial screenshot, you need to identify the specific element on the web page that you want to capture. You can find elements using various methods provided by Selenium WebDriver, such as locating elements by ID, class name, CSS selector, or XPath.

For example, if you want to capture the screenshot of a button with an ID of "myButton", you can use the findElement() method to locate the element. 

Once you have identified the element to capture, you can take a partial screenshot using the getScreenshotAs() method provided by the WebDriver. This method captures the visible area of the specified element.

Here's the example code:

java
import org.openqa.selenium.By; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import java.io.File; import java.io.IOException; public class PartialScreenshotExample { public static void main(String[] args) { // Set the path to the chromedriver executable System.setProperty("webdriver.chrome.driver", "path/to/chromedriver"); // Create an instance of ChromeDriver WebDriver driver = new ChromeDriver(); // Navigate to the desired page driver.get("https://www.example.com"); // Find the element to capture WebElement element = driver.findElement(By.id("myButton")); // Take the partial screenshot File screenshotFile = element.getScreenshotAs(OutputType.FILE); // Define the destination path for the screenshot String destinationPath = "path/to/save/screenshot.png"; // Save the screenshot to the destination path try { // Use an image processing library like AWT or ImageIO to crop the screenshot based on the element's location and dimensions // Save the cropped image to the destination path System.out.println("Screenshot saved successfully."); } catch (IOException e) { System.out.println("Failed to save the screenshot: " + e.getMessage()); } // Close the browser driver.quit(); } }

3. Take a Screenshot When a Test fails using TestNG Listener

3.1. Create a Custom TestNG Listener

The code provided is an implementation of a custom TestNG listener called CustomTestListener. This listener is responsible for capturing screenshots when a test case fails or is skipped.

Here's the code for the CustomTestListener class:

java
package framework; import java.lang.reflect.Field; import org.openqa.selenium.WebDriver; import org.testng.ITestContext; import org.testng.ITestListener; import org.testng.ITestResult; import org.testng.Reporter; import framework.BrowserDriver; import framework.Screenshot; public class CustomTestListener implements ITestListener { @Override public void onTestFailure(ITestResult result) { String fileName = "failed_" + result.getName(); new Screenshot(driver(result)).capture(fileName); } @Override public void onTestSkipped(ITestResult result) { String fileName = "skipped_" + result.getName(); new Screenshot(driver(result)).capture(fileName); } @SuppressWarnings("unchecked") private WebDriver driver(ITestResult testResult) { BrowserDriver browserDriver = null; try { Class<? extends ITestResult> testClass = (Class<? extends ITestResult>) testResult.getInstance().getClass(); Field driverField = testClass.getDeclaredField("driver"); browserDriver = (BrowserDriver) driverField.get(testResult.getInstance()); } catch (SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) { throw new RuntimeException("Could not get the driver from the test class!"); } return browserDriver.wrappedDriver(); } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) { // Not used in this implementation } @Override public void onStart(ITestContext context) { // Not used in this implementation } @Override public void onFinish(ITestContext context) { // Not used in this implementation } @Override public void onTestStart(ITestResult result) { // Not used in this implementation } @Override public void onTestSuccess(ITestResult result) { // Not used in this implementation } }
Here's an explanation of the code:

1. Import statements:
  • The code imports the necessary classes and interfaces, including WebDriver, ITestContext, ITestListener, ITestResult, Reporter, and custom framework classes.
2. CustomTestListener class:
  • The class implements the ITestListener interface, which allows it to listen to TestNG events.
3. onTestFailure method:
  • This method is called when a test case fails.
  • It retrieves the name of the failed test case using result.getName().
  • It creates a new Screenshot object and calls the capture method to capture a screenshot using the driver(result) method as an argument.
  • The screenshot file is saved with the prefix "failed_" followed by the test case name.
4. onTestSkipped method:
  • This method is called when a test case is skipped.
  • It retrieves the name of the skipped test case using result.getName().
  • It creates a new Screenshot object and calls the capture method to capture a screenshot using the driver(result) method as an argument.
  • The screenshot file is saved with the prefix "skipped_" followed by the test case name.
5. driver method:
  • This method retrieves the WebDriver instance from the test class using reflection.
  • It gets the test class using testResult.getInstance().getClass().
  • It retrieves the driver field using testClass.getDeclaredField("driver").
  • It casts the field value to BrowserDriver.
  • Finally, it returns the wrapped driver using browserDriver.wrappedDriver().
6. Other overridden methods:
  • The remaining methods (onTestFailedButWithinSuccessPercentage, onStart, onFinish, onTestStart, onTestSuccess) are empty and not used in this implementation.
Note that the code assumes the existence of a custom Screenshot class and a BrowserDriver class in the framework package. You may need to provide the implementation for these classes to make the listener work properly.

3.2. Add the listener to the test class using the Listener annotation

If you want to use the CustomTestListener class as a listener for your SiteTests class. To do that, you need to add the @Listeners annotation to your SiteTests class.

Here's an example of how you can add the @Listeners annotation and use the CustomTestListener class as the listener for your SiteTests class:

java
import org.testng.annotations.Listeners; @Listeners(CustomTestListener.class) public class SiteTests { public BrowserDriver driver; // Rest of your test code goes here }
In this example, the @Listeners annotation is used to specify that the CustomTestListener class should be used as the listener for the SiteTests class.

Make sure that the CustomTestListener class is in the same package or accessible to the SiteTests class.

With this setup, the CustomTestListener will be invoked during the execution of your SiteTests class, and it will capture screenshots of test failures and skipped tests.

Selenium Wait Commands  << Previous   ||   Next >>   Find Broken links with Selenium

Author
Passionately working as an Automation Developer for more than a decade.

Comments

Popular posts from this blog

Top 7 Web Development Trends in the Market

14 Best Selenium Practice Exercises for Automation Practice

17 Best Demo Websites for Automation Testing Practice

Automation Practice: Automate Amazon like E-Commerce Website with Selenium

Top 10 Highly Paid Indian CEOs in the USA

How to Automate Google Search with Selenium WebDriver

Mastering Selenium Practice: Automating Web Tables with Demo Examples

Top 51 Most Important Selenium WebDriver Interview Questions

Selenium IDE Tutorial: How to Automate Web Testing with Easy-to-Use Interface

Python Behave Tutorial: A Comprehensive Guide to Behavior-Driven Development (BDD)