← Blog

"Selenium Series #12: Screenshots, File Downloads and Test Evidence"

Capture screenshots on demand, on failure, and for full-page captures. Handle file downloads in Chrome and Firefox, verify downloaded files, and attach evidence to TestNG HTML reports.

reading now
views
comments

Series Navigation

Part 11: Actions Class

Part 13: Data-Driven Testing — Excel, CSV and DataProviders


Taking Screenshots

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;

// Screenshot as File
File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(screenshot, new File("screenshots/test.png"));

// Screenshot as byte array (for embedding in reports)
byte[] bytes = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);

// Screenshot as Base64 string (for HTML reports)
String base64 = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);

Screenshot Utility Class

// src/test/java/com/yourname/selenium/utils/ScreenshotUtils.java
public class ScreenshotUtils {

    private static final String SCREENSHOT_DIR = "test-output/screenshots/";

    static { new File(SCREENSHOT_DIR).mkdirs(); }

    public static String capture(WebDriver driver, String name) {
        String timestamp = LocalDateTime.now()
            .format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        String filename  = name + "_" + timestamp + ".png";
        String fullPath  = SCREENSHOT_DIR + filename;

        try {
            File src  = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
            File dest = new File(fullPath);
            FileUtils.copyFile(src, dest);
            System.out.println("[Screenshot] Saved: " + fullPath);
            return fullPath;
        } catch (IOException e) {
            System.err.println("[Screenshot] Failed: " + e.getMessage());
            return null;
        }
    }

    public static String captureElement(WebDriver driver, WebElement element, String name) {
        String timestamp = LocalDateTime.now()
            .format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        String filename  = name + "_element_" + timestamp + ".png";

        try {
            // Scroll element into view first
            ((JavascriptExecutor) driver)
                .executeScript("arguments[0].scrollIntoView(true);", element);

            File src  = element.getScreenshotAs(OutputType.FILE);
            File dest = new File(SCREENSHOT_DIR + filename);
            FileUtils.copyFile(src, dest);
            return dest.getAbsolutePath();
        } catch (IOException e) {
            System.err.println("[Screenshot] Element capture failed: " + e.getMessage());
            return null;
        }
    }

    public static String captureOnFailure(WebDriver driver, ITestResult result) {
        return capture(driver, "FAIL_" + result.getName());
    }

    // Base64 encoded screenshot for embedding in HTML reports
    public static String captureAsBase64(WebDriver driver) {
        return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);
    }
}

Attaching Screenshots to TestNG Reports

// In your TestListener
@Override
public void onTestFailure(ITestResult result) {
    WebDriver driver = getDriverFromTest(result);
    if (driver == null) return;

    // Capture screenshot
    String screenshotPath = ScreenshotUtils.captureOnFailure(driver, result);

    // Attach to TestNG reporter (appears in emailable-report.html)
    Reporter.log("<br><b>Screenshot:</b><br>");
    Reporter.log("<img src='" + screenshotPath + "' width='800' /><br>");

    // Also log URL and page title for debugging
    Reporter.log("<b>URL:</b> " + driver.getCurrentUrl() + "<br>");
    Reporter.log("<b>Title:</b> " + driver.getTitle() + "<br>");

    // If using Extent Reports or Allure — attach differently:
    // extentTest.addScreenCaptureFromPath(screenshotPath);
    // Allure.addAttachment("Failure Screenshot", new FileInputStream(screenshotPath));
}

Configuring File Downloads in Chrome

By default Chrome asks where to save downloads. Disable the dialog:

public static WebDriver createChromeWithDownloads(String downloadPath) {
    new File(downloadPath).mkdirs();

    Map<String, Object> prefs = new HashMap<>();
    prefs.put("download.default_directory", downloadPath);
    prefs.put("download.prompt_for_download", false);
    prefs.put("download.directory_upgrade", true);
    prefs.put("safebrowsing.enabled", true);
    prefs.put("plugins.always_open_pdf_externally", true); // don't open PDFs in browser

    ChromeOptions options = new ChromeOptions();
    options.setExperimentalOption("prefs", prefs);

    WebDriverManager.chromedriver().setup();
    return new ChromeDriver(options);
}

Verifying Downloads

public static File waitForDownload(String downloadDir, String expectedFilename, int timeoutSeconds) {
    File dir = new File(downloadDir);
    long deadline = System.currentTimeMillis() + (timeoutSeconds * 1000L);

    while (System.currentTimeMillis() < deadline) {
        File[] files = dir.listFiles();
        if (files != null) {
            for (File file : files) {
                // Skip incomplete Chrome downloads (.crdownload extension)
                if (file.getName().equals(expectedFilename) &&
                    !file.getName().endsWith(".crdownload")) {
                    return file;
                }
            }
        }
        try { Thread.sleep(500); } catch (InterruptedException e) { break; }
    }
    throw new RuntimeException("Download did not complete: " + expectedFilename);
}

// Usage in test
@Test
public void testReportDownload() {
    String downloadPath = System.getProperty("user.dir") + "/downloads";
    WebDriver driver = createChromeWithDownloads(downloadPath);

    driver.get("https://app.example.com/reports");
    driver.findElement(By.id("downloadReportBtn")).click();

    // Wait for PDF to download
    File downloadedFile = waitForDownload(downloadPath, "report.pdf", 30);

    Assert.assertTrue(downloadedFile.exists(), "PDF should be downloaded");
    Assert.assertTrue(downloadedFile.length() > 1000, "PDF should not be empty");
    System.out.println("Downloaded: " + downloadedFile.getName() +
                       " (" + downloadedFile.length() + " bytes)");
}

What's Next

In Part 13 we implement data-driven testing — reading test data from Excel files and CSVs, using TestNG DataProviders, and building parameterised tests that run the same scenario with dozens of data combinations.

Discussion

Loading...

Leave a Comment

All comments are reviewed before appearing. No links please.

0 / 1000