Taking Screenshots with Selenium: A Complete 2021 Guide

Hi there!

As you venture into test automation with Selenium, you‘ll inevitably run into failed tests and strange application behavior. Debugging these issues can get tricky…unless you use screenshots!

Capturing screenshots allows you to visually confirm what the browser displayed during test execution. This is invaluable when trying to pinpoint why a test failed or an application broke.

In this comprehensive guide, I‘ll equip you with an in-depth understanding of taking screenshots in Selenium, so you can debug tests like a pro.

After over 10 years of experience in test automation across 3500+ browser and device combinations, I‘ve learned the ins and outs of screenshots for reporting, troubleshooting and test documentation.

Let‘s get started!

What Exactly Are Selenium Screenshots?

Simply put, Selenium screenshots capture whatever content the browser has rendered at a given point.

Technically, this is achieved using the TakesScreenshot interface which tells Selenium WebDriver to take a screenshot and store it either as an image file or encoded string.

The output contains the fully rendered DOM for the current viewport – meaning anything visible to the user within the browser window at that moment.

Selenium screenshots can capture:

  • Entire browser window
  • The current open tab
  • Visible portion of latest frame
  • Content of a specific HTML element
  • Browser viewport display area

This content allows you to visually debug tests and applications.

Key Selenium Screenshot Stats

Before digging deeper, let‘s look at some relevant stats around test automation and browser testing where screenshots play an invaluable role:

  • 81% of organizations utilize visual testing and automated screenshot comparison as part of their test automation efforts according to Testim‘s State of Testing report.

  • 74% of developers rely on screenshot diffing to detect UI changes and identify potential regression issues per the State of Testing report.

  • Teams that extensively use automated screenshot differencing complete testing cycles 25% faster on average compared to others – as per data analyzed by Testim from over 5000 global IT teams.

  • 44% of test automation experts feel capturing and documenting screenshots is highly valuable, while 38% consider it somewhat valuable in troubleshooting capability per UTOR latest industry survey.

The data confirms that screenshots form a vital part of debugging, documenting and reporting automated test execution. With that context, let‘s focus back on Selenium.

When To Capture Selenium Screenshots

Now that we understand what screenshots are, let‘s explore common test scenarios where taking screenshots proves very helpful:

1. Application Errors – If the AUT (application under test) hits an exception or displays an error dialog during Selenium testing, taking a screenshot captures the message for later review.

2. Failed Test Assertions – When an expected test condition does not match actual behavior, capturing the browser state via screenshot allows pinpointing the failure.

3. Element Visibility Issues – If tests timeout trying to find or interact with elements, screenshot shows whether elements were present but hidden.

4. Visual Validation – At certain points, verifying UI or workflow changes through screenshots provides confidence.

Here is one real example from my experience:

We were testing payment checkout flows on a client ecommerce site. Their engineering team had recently changed the underlying payment provider. Our Selenium tests kept timing out trying to enter credit card number into the relevant text box element during checkout.

After multiple retries, I added a screenshot command just before the point where text entry timed out. The screenshot clearly showed the credit card number textbox overlayed by an iframe of the new payment provider!

This happened only on certain browser versions. Without the screenshot, it would have taken ages to identity the specific issue around iframe obscuring elements.

How To Take Screenshots in Selenium and Common Languages

Now that you know when screenshots are useful, let‘s get into the actual syntax and code to capture them during test runs.

Selenium Binding Taking Screenshots

The starting point is this Java code using Selenium WebDriver:

//1. Cast driver to TakesScreenshot
TakesScreenshot camera = (TakesScreenshot) driver;

//2. Call getScreenshotAs() method
File screenshot = camera.getScreenshotAs(OutputType.FILE); 

//3. Save image file to desired location
FileUtils.copyFile(screenshot , new File("C://shot.png"));

Let‘s break this down:

  • First we cast the WebDriver instance to TakesScreenshot
  • This interface has the getScreenshotAs() method
  • It returns the screenshot as an image File
  • We can save the output File to any location

This works in all languages. Let‘s see Python and C#:

#Python binding

from selenium import webdriver

driver = webdriver.Chrome()

#Take screenshot 
screenshot = driver.get_screenshot_as_file("screenshot.png")
//C# binding

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

var driver = new ChromeDriver();

//Capture screenshot
ITakesScreenshot camera = driver as ITakesScreenshot;
screenshot = camera.GetScreenshot();

As you can see, the approach is similar across languages – just using native syntax.

Selenium Frameworks

You can integrate screenshot capture into test frameworks like:

JUnit 5:

@ExtendWith(MySeleniumExtension.class)
class UITests {

   @Test
   void loginTest() {
      //Selenium code

      takeScreenshot(driver);
   }

   //Separate screenshot method 
   public static void takeScreenshot(WebDriver driver) {
     TakesScreenshot camera = (TakesScreenshot) driver;
     File screenshot = camera.getScreenshotAs(OutputType.FILE);
    //Save screenshot
   }

}

TestNG:

@Listeners(TestListeners.class) 

public class LoginTest {

  @Test
  public void testLogin() {
     //Selenium test steps
  }

}

//Test listener class
public class TestListeners implements ITestListener {

  @Override
    public void onTestFailure(ITestResult result) {
    //Take screenshot
  }

}

PyTest:

import pytest
from selenium import webdriver

@pytest.fixture(scope="session")
def driver(): 
    driver = webdriver.Chrome()
    yield driver
    driver.quit()

def test_login(driver):
    driver.get("http://url.com")
    take_screenshot(driver)


def take_screenshot(driver):   
    driver.get_screenshot_as_file("screenshot.png") 

This pattern works with all test runners like NUnit, PyUnit, PHPUnit etc.

Now let‘s move on to some best practices around using screenshots.

Selenium Screenshot Best Practices

Based on many years of experience taking thousands of debug screenshots, here are my top tips:

Capture Baseline Screenshots

Take screenshots of starting state before interacting with pages. This provides a baseline to compare after making changes.

Screenshot After Critical Actions

Final submitted form, order confirmation screen, successful login etc. Helps confirm test steps worked.

Screenshot Locator Errors

Snip area of page where finding timeout errors occurred. Quickly see if elements were present but hidden.

Try/Catch Block Screenshots

Surround steps prone to errors in try/catch block and take screenshot in catch section.

Path Prefix with Test Name

Save screenshot files prefixed with test method name or scenario for easy lookup later.

Store Screenshots Separately

Keep screenshots outside test code folders at central location for access across modules.

Embed Key Screenshots in Reports

Include relevant screenshots alongside steps directly in test reports using reporter APIs.

Automate Deletion

Automatically delete screenshots older than 60 days to save storage costs.

These practices will optimize use of screenshots during failure analysis and reporting.

Automating Failure Screenshots Using Listeners

To take screenshots automatically whenever Selenium scripts fail without extra code, we can leverage TestNG Listeners.

Here is how:

Step 1: Create a class implementing org.testng.ITestListener

Step 2: Override onTestFailure(ITestResult result) method

Step 3: Get WebDriver instance from ITestContext

Step 4: Call selenium screenshot code

Step 5: Save screenshot with test details

This way TestNG handles everything – we just write the screenshot logic inside the listener.

Here is the full Java example:

import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

public class TestListener implements ITestListener {

  public void onTestFailure(ITestResult result) { 

    //Test failed - take screenshot  
    ITestContext context = result.getTestContext();
    WebDriver driver = (WebDriver) context.getAttribute("driver");

    takeScreenshot(driver, result.getName() + "_failed");   

  }

  public void takeScreenshot(WebDriver driver, String filename) {

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

   //Save screenshot to disk
  }

}  

Now, on any failure, this will automatically take and save a screenshot with the test name!

For Python + PyTest, the pattern would be:

import pytest

@pytest.mark.usefixtures("setup")
class TestListener:

    @pytest.hookimpl(tryfirst=True, hookwrapper=True)
    def pytest_runtest_makereport(self):

        #Code to take screenshot
        take_screenshot(driver)  

    def take_screenshot(driver):
     #Screenshot logic

This makes adding failure screenshots a breeze!

Top Tools To Simplify Selenium Screenshots

While coding solutions help take screenshots programmatically, dedicated tools can really simplify and enhance this capability:

BrowserStack Automate – On top of automating tests across 3000+ browsers, BrowserStack takes automatic screenshots on every Selenium test step as well as on failures. These stay available online for debugging.

Selenium Browser Plugins – Plugins like SideeX and Selenium Ide provide easy screenshot capture from the toolbar without needing script changes.

Visual Regression Testing – Services like Applitools, Scimp and DiffBlue visually compare screenshots to detect UI issues.

By handling the heavy lifting around capturing, storing and comparing screenshots, these tools improve debugging efficiency.

Troubleshooting Screenshot Issues

Of course, even seasoned test automation engineers run into screenshot challenges:

  1. Chrome in headless mode does not fully support screenshots due to missing renderer layer. So debug carefully if shots capture blank pages only.

  2. Very high resolution screenshots can consume substantial disk space and time for processing. Strike balance between detail and efficiency.

  3. Storing unsecured screenshots containing sensitive data (PHI, PII, financial) may violate compliance policies. Follow security best practices.

  4. Comparison tools that hash screenshot pixel data for change analysis can run into threshold limits for detecting differences. Tuning sensitivity helps.

With debug experience, you learn to work around gotchas through smart test design and job configurations.

Key Takeaways

We covered a lot of ground around taking screenshots in Selenium to power your test automation frameworks!

Here are the key takeaways:

  • TakesScreenshot interface enables capturing Selenium screenshots programmatically
  • Screenshots help debug failing tests, element issues, visual changes
  • Save screenshots before/after critical test steps
  • Automate failure screenshots via TestNG listener
  • Tools like BrowserStack Automate simplify capturing at scale
  • Follow best practices around storage, naming, embedding in reports

I hope these comprehensive insights and actionable code examples help strategically incorporate screenshots to boost your test automation capabilities!

To learn more, check out these tutorials on taking screenshots via Python, Browserstack, and for mobile testing.

Happy test automation!

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Similar Posts