Taking Screenshots in Selenium: A Step-by-Step Guide

Posts

Selenium is an open-source tool widely used for automating web applications for testing purposes. It enables developers and testers to write scripts that control web browsers, allowing them to simulate user interactions, validate application behaviors, and verify UI components. Selenium supports various programming languages such as Java, Python, C#, and JavaScript, making it versatile and accessible to a wide developer base. One of the powerful features offered by Selenium is its ability to take screenshots. This functionality plays a critical role in debugging, test validation, visual regression testing, and reporting.

When automated tests are executed, especially over large applications or across multiple platforms, understanding exactly what the browser rendered at a specific point in the test is invaluable. This visual evidence helps testers quickly identify and document errors, UI misalignments, broken components, or unexpected behaviors. In scenarios where automated scripts fail, a screenshot can provide the exact state of the web page, aiding developers and QA teams in resolving issues faster.

Setting Up the Environment for Selenium Screenshots

Before working with Selenium to capture screenshots, the testing environment must be properly set up. This setup ensures that the browser, the language runtime, and the necessary drivers are ready to interact seamlessly. The process of setting up the environment may vary slightly depending on whether you are using Java or Python, but the general principles remain the same.

Java Development Kit Installation

To use Selenium with Java, you must first install the Java Development Kit. The JDK provides the tools necessary to develop Java applications, including the Java compiler and the Java Runtime Environment. After installation, you should configure your system’s environment variables to include the Java binary path. This allows Java commands to be executed from the command line or integrated development environments.

Installing an IDE for Java

An integrated development environment such as Eclipse or IntelliJ IDEA simplifies Java development by offering code suggestions, project management, error highlighting, and debugging tools. These features make it easier to write and maintain Selenium tests. After installing an IDE, you can create a new Java project where Selenium libraries will be imported.

Downloading and Configuring Selenium WebDriver

The WebDriver is the heart of Selenium. It is responsible for launching and controlling browsers. Depending on the browser you intend to use for testing, you will need to download the corresponding driver executable. For example, Chrome requires ChromeDriver, while Firefox uses GeckoDriver. These drivers must be placed in a known location on your system, and the path to the driver must be specified in your code to initiate browser sessions.

You must also include the Selenium Java bindings in your project. This can be done by downloading the client libraries directly or using a build tool like Maven or Gradle. These bindings allow your Java code to communicate with the WebDriver and control browser actions programmatically.

Creating a Basic Selenium Project

Once your environment is set up, you can begin creating your Selenium project. This involves defining the project structure in your IDE, creating necessary classes, and configuring the project to recognize Selenium libraries. The basic structure of a Selenium project typically includes a main class, a test class, utility functions, and configuration files.

When your project is ready, instantiate the WebDriver and start writing test scripts. The browser can be launched by specifying the driver path and calling the appropriate WebDriver constructor. From here, you can direct the browser to load any URL and begin performing actions such as clicking buttons, filling forms, or capturing screenshots.

Why Screenshots Are Essential in Selenium Testing

Screenshots in Selenium are more than just images; they are critical assets that enhance the quality and transparency of testing. They serve several purposes that go beyond test automation, helping development and QA teams ensure that software behaves as expected.

Visual Evidence for Debugging

During automated testing, especially when tests fail, screenshots serve as a visual log of the browser state. They capture how the web page looked at the moment of failure, providing testers and developers with insight into potential UI or functional issues. Instead of relying solely on console logs or error messages, developers can visually inspect what was rendered and identify what went wrong. This significantly reduces the time spent on debugging and increases the accuracy of issue identification.

Supporting Visual Regression Testing

Visual regression testing involves comparing the visual appearance of a web page before and after changes are made to the codebase. Selenium screenshots are essential for this process. By capturing screenshots at key checkpoints in the application, teams can identify unintended changes in layout, style, font rendering, spacing, and element alignment. This is particularly useful when working with CSS changes, responsive designs, or major UI overhauls. It ensures the visual consistency of the application across updates and enhancements.

Enhancing Test Reporting and Documentation

Screenshots add value to test reports by providing visual documentation of what occurred during the execution. For stakeholders who are not familiar with the code, visual test results are easier to understand. Screenshots make reports more comprehensive, especially when test results are shared with project managers, designers, or clients. Screenshots can also be archived along with test logs, making it easier to audit historical test runs and trace back to issues encountered in past builds.

Capturing Errors in Real Time

There are cases where unexpected issues, such as pop-up alerts, layout shifts, or rendering bugs, occur at runtime. These problems may not cause test failures, but still affect user experience. By capturing screenshots throughout the test process, these anomalies can be recorded and reviewed. This proactive approach helps teams maintain high standards of user interface and usability.

Screenshot Capture Techniques in Java Using Selenium

With the foundational setup in place, we can now dive into the actual process of taking screenshots using Java in Selenium. The Java API provided by Selenium includes a method called getScreenshotAs,, which is part of the TakesScreenshot interface. This method can be used to capture the browser’s view and save it as a file in a specified format and location.

Basic Screenshot Example

The basic procedure for capturing a screenshot involves the following steps: launching the browser, navigating to a web page, capturing the screenshot, and saving the image file. Below is a simple example that demonstrates these steps:

java

CopyEdit

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

import org.openqa.selenium.TakesScreenshot;

import org.openqa.selenium.OutputType;

import org.apache.commons.io.FileUtils;

import java.io.File;

public class ScreenshotExample {

    public static void main(String[] args) throws Exception {

        System.setProperty(“webdriver.chrome.driver”, “path/to/chromedriver”);

        WebDriver driver = new ChromeDriver();

        driver.get(“https://www.example.com”);

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

        FileUtils.copyFile(screenshot, new File(“screenshot.png”));

        driver.quit();

    }

}

This script opens a browser using ChromeDriver, navigates to a website, captures a screenshot of the browser window, and saves it to a file named screenshot.png. The use of the FileUtils class from Apache Commons IO simplifies the process of copying the file from memory to the filesystem.

Capturing Full Page Height

Most browsers display only the visible viewport area by default. If the web page is taller than the viewport, the bottom portion may not be captured in the default screenshot. To capture the full height of the page, you can dynamically resize the browser window based on the page’s height.

java

CopyEdit

JavascriptExecutor js = (JavascriptExecutor) driver;

long height = (Long) js.executeScript(“return document.body.scrollHeight”);

Dimension dimension = new Dimension(1920, (int) height);

driver.manage().window().setSize(dimension);

This technique ensures that the browser resizes to fit the entire length of the page, enabling the screenshot to include all visible content from top to bottom.

Capturing Screenshot on Failure

You can also capture screenshots only when a test fails. This is typically done inside a catch block or an exception handler. This way, the screenshots provide a clear view of what went wrong and are only generated when necessary.

java

CopyEdit

try {

    // Perform test steps

} catch (Exception e) {

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

    FileUtils.copyFile(screenshot, new File(“error_screenshot.png”));

}

This conditional approach saves storage space and makes test reports cleaner, focusing only on failed scenarios that require attention.

Setting Up Selenium for Screenshot Automation

Before diving deeper into using Selenium for capturing screenshots, it’s crucial to establish a solid foundation by properly setting up the environment. A successful setup ensures smoother execution and fewer errors while automating browser interactions.

Java Development Kit and IDE Configuration

To begin with Java-based Selenium development, install the latest version of the Java Development Kit (JDK). This kit includes essential tools and libraries for developing Java applications. Verify the installation by executing a version check command from the terminal. Once JDK is installed, set the environment variable to enable Java to run in any command line window.

Next, choose a suitable Integrated Development Environment (IDE) to write and manage your Selenium scripts. Popular options include Eclipse, IntelliJ IDEA, and Visual Studio Code. For Java users, Eclipse is often preferred due to its seamless integration with Selenium libraries and ease of project setup. Configure your IDE by setting the appropriate JDK and creating a new Java project.

Installing Selenium Libraries and Browser Drivers

After configuring the IDE, download and install the Selenium WebDriver library. For Java, this involves adding Selenium JAR files to your project’s build path. Selenium provides client libraries for different programming languages, so ensure you’re downloading the correct version.

In addition to the WebDriver library, browser drivers must be installed. These drivers act as a bridge between the Selenium code and the browser. For instance, to automate actions in Google Chrome, download ChromeDriver. Place the executable in a known location and add its path in your Selenium script using system properties. This allows WebDriver to initiate and control browser sessions.

Repeat this process for other browsers if you plan to perform cross-browser testing. Each browser has a corresponding driver, such as GeckoDriver for Firefox or EdgeDriver for Microsoft Edge. Always ensure compatibility between the browser version and its respective driver.

Handling Dependencies with Build Tools

Modern Java projects benefit from build automation tools like Maven or Gradle. These tools simplify dependency management. Instead of downloading libraries manually, you can define them in a configuration file and let the tool handle the rest. For Maven, modify the pom.xml file to include Selenium dependencies. This streamlines project setup, especially when collaborating in teams or working on large-scale applications.

For Python users, a similar setup involves installing the selenium package using pip. Browser drivers must still be downloaded and configured. Use virtual environments to manage dependencies efficiently, especially when working on multiple projects.

Verifying Your Setup

To confirm that everything is correctly set up, write a simple script that launches a browser and navigates to a webpage. If the browser opens and displays the expected page, your environment is ready. This validation step prevents future confusion and saves time during more complex implementations.

Now that the environment is prepared, we can move on to incorporating screenshot functionality into Selenium scripts.

Techniques for Capturing Screenshots in Selenium

Screenshots are captured using the TakesScreenshot interface in Selenium. This interface is implemented by most WebDriver classes, including ChromeDriver and FirefoxDriver. Selenium allows you to take different types of screenshots depending on your needs, including full-page captures, specific element captures, and screenshots upon error detection.

Capturing a Full-Page Screenshot

A full-page screenshot captures everything visible in the browser viewport at the time of execution. This is useful for documentation, visual validations, or bug reporting. Use the getScreenshotAs method from the TakesScreenshot interface. The returned object can be saved to a file using utility libraries such as Apache Commons IO in Java.

For example, in Java, you first cast the WebDriver instance to TakesScreenshot. Then call the method, define the output file, and use FileUtils.copyFile to store the image. Ensure that the destination directory exists or create it programmatically before saving.

In Python, the save_screenshot method provides similar functionality. The method is straightforward and saves the image in PNG format by default.

Capturing Screenshots of Specific Elements

There are scenarios where capturing the entire screen is unnecessary or inefficient. Instead, you might only want to capture a specific UI element, such as a button, form, or message box. This is particularly helpful when verifying UI components or debugging individual features.

To capture an element screenshot, first locate the element using a suitable locator strategy such as find_element_by_id, find_element_by_class_name, or CSS selectors. Once identified, call the element’s screenshot method in Python. This method isolates the selected element and captures only that portion of the webpage.

In Java, Selenium WebDriver does not natively support capturing element-only screenshots, but workarounds exist. One common method involves using external libraries like AShot. AShot simplifies the process and offers additional features such as capturing elements with borders or highlighting them.

Handling Dynamic Pages and Viewport Adjustments

Modern websites often contain dynamic content that loads asynchronously or relies on user interaction. In such cases, you must ensure the content is fully loaded before taking the screenshot. Use WebDriver’s wait mechanisms to pause execution until certain elements are visible or conditions are met.

Moreover, the default browser window size may not cover the entire length of the page. Resize the window dynamically using set_window_size to match the scrollable height. This ensures that the entire content is visible during capture.

To achieve this, execute JavaScript using WebDriver’s execute_script method to calculate the total height of the document. Then apply that height to the browser window before taking the screenshot. This technique is especially useful when performing automated documentation or UI regression testing.

Taking Screenshots Upon Failure

Capturing screenshots during test failures is a powerful debugging aid. Integrate screenshot functionality into your test framework so that whenever a test fails, a screenshot is automatically captured. This provides immediate visual feedback and allows you to inspect the application’s state at the time of the error.

In Java, wrap test steps in a try-catch block. When an exception or assertion error occurs, trigger the screenshot logic. Save the image with a timestamp or unique identifier to avoid overwriting existing files.

In Python, use exception handling with try-except blocks. Within the except clause, call the save_screenshot method. Integrate this logic into your testing framework, such as PyTest or Unittest, to automate the process.

Managing Screenshots Efficiently

As your test suite grows, so will the number of screenshots generated. Organizing and managing these images becomes critical. Without structure, it becomes difficult to retrieve or analyze screenshots later.

Naming Conventions and Folder Structure

Use descriptive and consistent naming conventions for your screenshots. Include details such as test case name, browser type, timestamp, or outcome status in the file name. This helps you identify and sort files easily.

Organize screenshots into folders based on their purpose. Create separate directories for passed tests, failed tests, and specific modules. This modular approach ensures clarity and makes it easier to integrate screenshots into automated reports.

For Java projects, use File.separator for cross-platform compatibility. In Python, use the os.path.join method. Always validate that the path exists and create directories dynamically when needed to avoid runtime errors.

Storing and Archiving Screenshots

Over time, you may accumulate a significant number of screenshots, which can consume disk space. Implement a strategy for archiving or deleting old screenshots periodically. Use scripts to compress older files or move them to a cloud storage solution for backup.

If you’re using a continuous integration system, configure it to store screenshots as part of the test artifacts. Tools like Jenkins and GitHub Actions support artifact preservation, allowing you to review screenshots from previous builds.

You can also integrate with test management tools that support attachments. This allows you to upload screenshots as part of test case results, providing visual evidence directly within the test management platform.

Screenshot Comparison for Regression Testing

Another advanced use of screenshots is visual regression testing. In this technique, screenshots from different runs are compared pixel-by-pixel to detect visual inconsistencies. Even small layout shifts or style changes can be flagged.

Several tools and libraries support this approach. For Java, libraries like AShot and Galen can compare images and highlight differences. In Python, you can use libraries like Pillow and image comparison tools to identify mismatches.

Automate the comparison process by capturing a baseline screenshot and comparing it against a current screenshot. Generate a diff image that highlights differences, helping testers quickly spot UI regressions.

Error Proofing Screenshot Logic

Ensure that your screenshot logic does not fail silently. Wrap the file-saving logic in try-catch blocks to capture IO exceptions. Log errors if the screenshot cannot be saved due to permission issues or invalid paths.

Also, confirm that the driver instance is still active before attempting to capture screenshots. If the browser window is closed prematurely, attempting to interact with the driver may result in exceptions.

Enhancing Screenshot Utility in Automation Frameworks

To maximize the benefit of screenshots, integrate them into your automation framework. Whether you’re using TestNG, JUnit, PyTest, or a custom solution, automated screenshot capture should be a core component of your test strategy.

Integrating with Reporting Tools

Most modern test reporting tools support image embedding. Incorporate screenshot capture into your test listener or reporter so that screenshots are automatically added to test reports. This provides immediate context to stakeholders reviewing the report.

In Java, TestNG allows the implementation of ITestListener, which provides hooks for test events such as success or failure. Within the onTestFailure method, add code to capture and attach screenshots. Use reporting tools like ExtentReports to embed screenshots into HTML reports.

In Python, PyTest plugins like pytest-html support screenshot embedding. Implement hooks that capture screenshots upon failure and include them in the generated report. This makes the reports more informative and reduces the need for manual investigation.

Reusability and Utility Methods

Create reusable utility methods for capturing screenshots. Instead of writing screenshot logic in every test case, abstract it into a separate class or module. This promotes code reuse and makes maintenance easier.

In Java, create a utility class with static methods that accept parameters like WebDriver instance and file name. In Python, define functions or class methods within a helper module. Call these methods from within test cases or exception handlers.

This approach standardizes your screenshot process, ensures consistency, and allows easy updates if the underlying logic changes.

Advanced Techniques for Selenium Screenshots

Once you’ve mastered basic screenshot capture, it’s time to explore advanced techniques that elevate your test automation strategy. These methods allow for higher precision, improved reliability, and broader applicability in complex testing environments.

Capturing Full-Page Screenshots Beyond the Viewport

Standard screenshots only capture the visible portion of a page. To capture full pages that extend beyond the current viewport, additional logic is needed. Selenium itself doesn’t support full-page screenshots directly for all browsers. However, third-party tools or JavaScript-based scrolling techniques can help.

Using AShot in Java

AShot is a powerful open-source library that enhances Selenium’s screenshot capabilities. It can stitch multiple viewport images together to simulate a full-page screenshot. Here’s how it works:

  1. It scrolls the page down in segments.
  2. Captures screenshots at each scroll position.
  3. Stitches them into a single image.

To implement AShot:

  • Add it to your Maven or Gradle build.
  • Configure its ShootingStrategy to capture full-page views.
  • Integrate with your existing screenshot utilities.

This is particularly effective for pages with long scrolls, dynamic loading, or responsive design testing.

Using JavaScript Scrolling in Python

In Python, without an external library, you can manually scroll the page in increments using execute_script, capture screenshots, and merge them using Pillow or OpenCV. This is more complex but offers full control. It’s especially useful when dealing with infinite scroll or lazy-loaded content.

Highlighting Elements in Screenshots

When debugging or demonstrating specific UI issues, it’s helpful to visually highlight elements in the screenshot. This can be achieved by temporarily modifying the element’s style using JavaScript.

For example:

java

CopyEdit

JavascriptExecutor js = (JavascriptExecutor) driver;

js.executeScript(“arguments[0].style.border=’3px solid red'”, element);

This applies a visible red border around the element just before the screenshot is taken. After capturing, revert the style to avoid interfering with the test. This technique is highly effective in making screenshots more illustrative during test reviews or defect reporting.

Annotating Screenshots with Information

Another enhancement is adding text annotations or timestamps directly onto the screenshot image. While Selenium doesn’t support this natively, image libraries can be used in combination.

In Java, use BufferedImage and Graphics2D to draw text on the image. In Python, use Pillow’s ImageDraw module to overlay text or shapes. Include useful metadata such as:

  • Test name
  • Timestamp
  • Browser type
  • Element identifier

This is especially helpful when generating large numbers of screenshots as part of automated test runs.


Cross-Browser Compatibility Considerations

Different browsers render web pages slightly differently. Fonts, layout, and even element alignment can vary. This variability can affect how screenshots appear and behave. It’s important to ensure your screenshot strategy works consistently across browsers.

Browser-Specific Quirks

Each browser driver (ChromeDriver, GeckoDriver, EdgeDriver) may handle screenshots slightly differently:

  • ChromeDriver captures the visible viewport and supports full-page screenshots in headless mode.
  • GeckoDriver (Firefox) can capture full-page screenshots out of the box.
  • EdgeDriver behaves similarly to ChromeDriver, but some versions have limitations on headless behavior.

Testing on all target browsers early and often helps identify rendering issues or inconsistent behavior in your screenshot logic.

Ensuring Consistent Viewports

Set a fixed window size before capturing to standardize screenshots across browsers. This avoids layout shifts caused by auto-resizing. Use set_window_size(width, height) consistently before each capture.

For example:

python

CopyEdit

driver.set_window_size(1920, 1080)

Also, disable browser toolbars and popups if applicable to ensure the content area remains consistent.

Managing Browser Differences in Tests

Use conditional logic in your framework to handle browser-specific behavior. For instance, if Firefox supports full-page screenshots natively but Chrome doesn’t, adjust your capture strategy accordingly. Maintain a compatibility layer in your test utilities to abstract these differences.


Headless Mode and Screenshots

Headless browser testing refers to running browsers without a visible UI. This is common in CI/CD pipelines where speed and resource efficiency are priorities. However, headless mode may affect screenshot accuracy or completeness.

Benefits of Headless Screenshots

  • Faster test execution
  • Reduced resource consumption
  • Better suited for containerized environments like Docker

Challenges with Headless Mode

  • Some visual elements may render differently (e.g., fonts, animations).
  • JavaScript-triggered content may not load as expected.
  • Screenshots may capture blank or incomplete content if waits are not used.

Best Practices for Headless Screenshot Accuracy

  • Always set explicit window size: Headless browsers default to smaller windows.
  • Use driver.set_window_size() even in headless mode.
  • Add waits before capturing to ensure content is fully loaded.
  • Use consistent fonts by disabling system font loading or using web fonts.

In Java:

java

CopyEdit

ChromeOptions options = new ChromeOptions();

options.addArguments(“–headless”, “–window-size=1920,1080”);

In Python:

python

CopyEdit

options = webdriver.ChromeOptions()

options.add_argument(“–headless”)

options.add_argument(“–window-size=1920,1080”)

Test your screenshot code in both headed and headless modes to ensure visual consistency.


Integrating with Visual Testing Tools

Selenium’s native screenshot features can be enhanced further with visual testing tools that focus on comparing UI states pixel by pixel.

Visual Regression Testing Tools

Popular visual testing tools include:

  • Applitools Eyes: AI-powered visual comparison tool.
  • Percy by BrowserStack: Automates visual diffing across browsers.
  • BackstopJS: Open-source tool for visual regression.

These tools typically integrate with Selenium, take screenshots during test runs, and compare them against baseline images. They highlight changes and help detect unintended UI regressions.

Integrating Applitools with Selenium

Applitools provides SDKs for multiple languages. You can configure it to capture screenshots at various points and automatically compare them with previous baselines. It supports:

  • Layout comparison (ignoring text changes)
  • Strict comparison (pixel-level)
  • Content comparison

Steps for integration:

  1. Set up an Applitools account.
  2. Add SDK dependency to your project.
  3. Initialize Eyes object.
  4. Call eyes.open() before test steps.
  5. Use eyes.checkWindow() to capture.
  6. Call eyes.closeAsync() at the end.

This simplifies the process of identifying visual issues and can be embedded into CI pipelines.


Best Practices for Screenshot Automation

To make the most of Selenium screenshots, follow industry best practices. These tips ensure maintainability, accuracy, and usability of screenshots in real-world testing workflows.

Ensure Test Stability Before Capturing

Screenshots should only be taken when the UI is stable. Use explicit waits to avoid capturing intermediate states. Selenium’s WebDriverWait with ExpectedConditions helps synchronize actions.

Avoid using Thread.sleep() unless necessary. It leads to flaky tests and may result in inconsistent screenshots.

Use Timestamps and Unique Names

To avoid overwriting screenshots, generate filenames using timestamps or UUIDs. A good filename format might be:

CopyEdit

testName_browser_timestamp.png

This helps in tracking, debugging, and organizing screenshots by test run or browser type.

Centralize Screenshot Logic

Maintain all screenshot logic in a dedicated utility class or module. Avoid repeating getScreenshotAs() calls in multiple places. Centralization simplifies updates, reduces code duplication, and standardizes behavior.

Example in Java:

java

CopyEdit

public static void captureScreenshot(WebDriver driver, String name) {

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

    File dest = new File(“screenshots/” + name + “.png”);

    FileUtils.copyFile(src, dest);

}

Automate Cleanup or Archiving

Old screenshots consume disk space and clutter reporting. Automate cleanup by:

  • Deleting files older than a certain number of days.
  • Moving to cloud storage or an archival folder.
  • Zipping them as part of post-run jobs.

In CI pipelines, this can be handled via shell scripts or CI step logic.

Embed in Reports and Logs

Make screenshots accessible by embedding them into reports. HTML reports with inline images help non-technical stakeholders understand test failures. Logs with image paths also assist in debugging without needing to rerun tests.

Use libraries like:

  • ExtentReports (Java)
  • pytest-html (Python)
  • Allure Reports (Multi-language)

Attach screenshots on failure and optionally on success or checkpoint validations.

Real-World Implementation: End-to-End Example

Let’s walk through a complete Selenium test case in both Java and Python, with screenshots taken at key points, error handling, and reporting integration.

Java Example: Screenshot on Login Test

Dependencies (Maven):

xml

CopyEdit

<dependencies>

    <dependency>

        <groupId>org.seleniumhq.selenium</groupId>

        <artifactId>selenium-java</artifactId>

        <version>4.21.0</version>

    </dependency>

    <dependency>

        <groupId>commons-io</groupId>

        <artifactId>commons-io</artifactId>

        <version>2.15.0</version>

    </dependency>

</dependencies>

Screenshot Utility:

java

CopyEdit

public class ScreenshotUtil {

    public static void takeScreenshot(WebDriver driver, String filename) {

        try {

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

            File dest = new File(“screenshots/” + filename + “.png”);

            FileUtils.copyFile(src, dest);

        } catch (IOException e) {

            System.out.println(“Screenshot failed: ” + e.getMessage());

        }

    }

}

Test Case:

java

CopyEdit

@Test

public void loginTest() {

    WebDriver driver = new ChromeDriver();

    try {

        driver.manage().window().maximize();

        driver.get(“https://example.com/login”);

        ScreenshotUtil.takeScreenshot(driver, “01_login_page”);

        driver.findElement(By.id(“username”)).sendKeys(“testuser”);

        driver.findElement(By.id(“password”)).sendKeys(“password”);

        ScreenshotUtil.takeScreenshot(driver, “02_filled_credentials”);

        driver.findElement(By.id(“loginBtn”)).click();

        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

        wait.until(ExpectedConditions.urlContains(“/dashboard”));

        ScreenshotUtil.takeScreenshot(driver, “03_dashboard”);

    } catch (Exception e) {

        ScreenshotUtil.takeScreenshot(driver, “error”);

        throw e;

    } finally {

        driver.quit();

    }

}

This pattern captures pre-action, post-action, and error screenshots. In a real test suite, this is abstracted further via test hooks or listeners.

Python Example: Screenshot with PyTest

Setup with selenium and pytest:

bash

CopyEdit

pip install selenium pytest pytest-html

Screenshot Utility:

python

CopyEdit

def take_screenshot(driver, name):

    path = f”screenshots/{name}.png”

    driver.save_screenshot(path)

    return path

Test Case with PyTest:

python

CopyEdit

import pytest

from selenium import webdriver

from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

from datetime import datetime

import os

@pytest.fixture

def driver():

    options = webdriver.ChromeOptions()

    options.add_argument(‘–headless’)

    options.add_argument(‘–window-size=1920,1080’)

    driver = webdriver.Chrome(options=options)

    yield driver

    driver.quit()

def timestamp():

    return datetime.now().strftime(“%Y%m%d_%H%M%S”)

def test_login(driver):

    os.makedirs(“screenshots”, exist_ok=True)

    try:

        driver.get(“https://example.com/login”)

        take_screenshot(driver, f”01_login_{timestamp()}”)

        driver.find_element(By.ID, “username”).send_keys(“testuser”)

        driver.find_element(By.ID, “password”).send_keys(“password”)

        take_screenshot(driver, f”02_filled_{timestamp()}”)

        driver.find_element(By.ID, “loginBtn”).click()

        WebDriverWait(driver, 10).until(EC.url_contains(“/dashboard”))

        take_screenshot(driver, f”03_dashboard_{timestamp()}”)

    except Exception as e:

        take_screenshot(driver, f”error_{timestamp()}”)

        raise

With pytest-html, these screenshots can be embedded into a report with –html=report.html –self-contained-html.

CI/CD Integration with Jenkins or GitHub Actions

Jenkins Integration

In Jenkins, create a pipeline that runs your Selenium tests and archives the screenshots:

groovy

CopyEdit

pipeline {

    agent any

    stages {

        stage(‘Build’) {

            steps {

                sh ‘./gradlew clean test’

            }

        }

        stage(‘Archive Screenshots’) {

            steps {

                archiveArtifacts artifacts: ‘screenshots/*.png’, onlyIfSuccessful: false

            }

        }

    }

}

Make sure Jenkins agents have Chrome and ChromeDriver installed.

GitHub Actions Workflow

yaml

CopyEdit

name: Selenium Tests

on: [push]

jobs:

  test:

    runs-on: ubuntu-latest

    steps:

    – uses: actions/checkout@v3

    – name: Set up Python

      uses: actions/setup-python@v4

      with:

        python-version: ‘3.11’

    – name: Install dependencies

      run: |

        pip install selenium pytest pytest-html

    – name: Run tests

      run: pytest –html=report.html –self-contained-html

    – name: Upload screenshots

      uses: actions/upload-artifact@v4

      with:

        name: screenshots

        path: screenshots/

    – name: Upload HTML report

      uses: actions/upload-artifact@v4

      with:

        name: test-report

        path: report.html

This workflow installs dependencies, runs tests in headless mode, and uploads both screenshots and test reports as downloadable artifacts.

Embedding Screenshots in Test Reports

ExtentReports in Java

ExtentReports is a Java reporting library that supports screenshot embedding. You can use it with TestNG or JUnit.

Sample Integration:

java

CopyEdit

ExtentReports extent = new ExtentReports();

ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(“report.html”);

extent.attachReporter(htmlReporter);

ExtentTest test = extent.createTest(“Login Test”);

test.info(“Navigating to login”);

test.addScreenCaptureFromPath(“screenshots/01_login_page.png”);

PyTest + HTML Reports

Use pytest-html to attach screenshots to failed tests.

Hook for Failure Capture:

python

CopyEdit

# conftest.py

@pytest.hookimpl(tryfirst=True, hookwrapper=True)

def pytest_runtest_makereport(item, call):

    outcome = yield

    rep = outcome.get_result()

    if rep.when == ‘call’ and rep.failed:

        driver = item.funcargs.get(“driver”)

        if driver:

            screenshot_path = take_screenshot(driver, f”fail_{timestamp()}”)

            rep.extra = getattr(rep, ‘extra’, [])

            rep.extra.append(pytest_html.extras.image(screenshot_path))

Then run:

bash

CopyEdit

pytest –html=report.html –self-contained-html

You’ll get a rich, navigable HTML report with embedded screenshots for failed steps.

Building Screenshot-Aware Frameworks

As your testing needs scale, you’ll want a maintainable structure.

Directory Structure:

CopyEdit

project/

├── tests/

│   └── test_login.py

├── utils/

│   └── screenshots.py

├── reports/

├── screenshots/

├── conftest.py

└── requirements.txt

Screenshot Strategy Layer

Use an interface or helper class to centralize logic. For example:

  • take_screenshot(driver, label)
  • capture_on_failure(driver, test_name)
  • highlight_element(driver, element)

Keep screenshots:

  • On step checkpoints
  • On failures (automatically in hooks)
  • On assertions (custom assert wrappers)

Final Thoughts 

Here are expert-level tips to get the most from Selenium screenshots:

  • Always log when a screenshot is taken — include file path for easy traceability.
  • Use relative paths for portability across environments.
  • Compress images if you have storage limitations.
  • Don’t overuse screenshots — only at key stages unless debugging.
  • Name files descriptively, including test name, timestamp, and browser.

Example:

CopyEdit

login_success_chrome_20250623_150500.png

you now have a full-featured, production-ready approach to Selenium screenshots:

  • Full automation with CI/CD and cross-browser support
  • Error screenshots and visual logs
  • Integration with reporting frameworks
  • Clean, reusable, and extendable architecture

This setup not only improves test reliability but also boosts communication across teams, helping QA, developers, and product managers align visually on defects.