Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use a custom TestNG ITestListener and capture the browser in onTestFailure. Save each image beside the generated HTML report, then add a relative image reference through your reporting library. Register the listener with testng.xml or @Listeners. This captures the page while the failure is being reported; an IReporter is better for assembling results after the suite has finished.
What you need before adding screenshots
- A Selenium
WebDriverthat is still alive when TestNG callsonTestFailure. - A reporting output directory whose HTML and image files will be copied together.
- A reporting integration such as ExtentReports, or a small custom HTML writer.
- A unique naming strategy for parallel tests and repeated runs.
TestNG provides the lifecycle event and the ITestResult; it does not define how your framework stores the driver. A listener must obtain the browser belonging to the failing test. A single mutable static driver is unsafe when tests run in parallel because one thread can capture another thread’s page.
Listener or reporter: choose the capture point
Use ITestListener for failure-time capture
TestNG listeners receive real-time notifications when tests start, pass, fail, or are skipped. onTestFailure(ITestResult result) is therefore the natural place to call Selenium’s screenshot API. The browser is captured immediately, before later teardown code changes the page or quits the session.
Free tools Windows power users keep installed
One-click scans. No signup required.
Use IReporter for post-run assembly
IReporter.generateReport(List<ISuite>, String outputDirectory) runs after suites complete. It receives the completed run model and is useful for building or enriching a report from screenshots that were already saved. It is usually too late to take a reliable browser screenshot: teardown may have closed the driver.
#1 Best Overall
A framework-neutral implementation
The following class shows the responsibilities without pretending that driver storage is a TestNG feature. Replace DriverStore, ScreenshotFiles, and reportFailureWithScreenshot with your project’s implementations.
public final class FailureScreenshotListener implements ITestListener {
@Override
public void onTestFailure(ITestResult result) {
WebDriver driver = DriverStore.forCurrentTest();
if (driver == null) {
return;
}
Path image = ScreenshotFiles.write(driver, result.getName());
reportFailureWithScreenshot(result, image);
}
}
The guard prevents a second exception from hiding the original test failure. Your driver store can use a thread-local value, a dependency-injection scope, or a test-context object. Whichever approach you choose, clear it after the test ends and make the lifecycle explicit.
Capture and name the image safely
Selenium exposes screenshots through TakesScreenshot. Write into a directory under the report output, create missing directories, and sanitize test names before using them as filenames. Add a run identifier and a timestamp or monotonic counter so retries and parameterized invocations do not overwrite one another.
public final class ScreenshotFiles {
public static Path write(WebDriver driver, String testName) {
Path root = Paths.get("test-output", "screenshots");
try {
Files.createDirectories(root);
String safe = testName.replaceAll("[^a-zA-Z0-9._-]", "_");
String fileName = safe + "-" + UUID.randomUUID() + ".png";
Path destination = root.resolve(fileName);
File source = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.FILE);
Files.copy(source.toPath(), destination,
StandardCopyOption.REPLACE_EXISTING);
return destination;
} catch (IOException | WebDriverException e) {
throw new UncheckedIOException(
new IOException("Could not save failure screenshot", e));
}
}
}
If the driver is remote, Selenium transfers the screenshot bytes to the test process; the destination path is still local to the process generating the report. For a full-page image, confirm that your browser and driver support the required capture mode. A normal viewport screenshot may omit content below the fold.
Rank #2
- Affordable Versatility - A budget-friendly all-in-one printer perfect for both home users and hybrid workers, offering exceptional value
- Crisp, Vibrant Prints - Experience impressive print quality for both documents and photos, thanks to its 2-cartridge hybrid ink system that delivers sharp text and vivid colors
- Effortless Setup & Use - Get started quickly with easy setup for your smartphone or computer, so you can print, scan, and copy without delay
- Reliable Wireless Connectivity - Enjoy stable and consistent connections with dual-band Wi-Fi (2.4GHz or 5GHz), ensuring smooth printing from anywhere in your home or office
- Scan & Copy Handling - Utilize the device’s integrated scanner for efficient scanning and copying operations
Attach the file to an HTML report
ExtentReports with a path reference
ExtentReports Java documentation describes attaching media from a file path and also supports base64 media entities. A path-based report points from the generated HTML to the image; it does not automatically package the image into the HTML. Keep the relative directory intact when publishing or moving the report.
ExtentTest test = extent.createTest(result.getMethod().getMethodName());
Path image = ScreenshotFiles.write(driver, result.getName());
test.fail(result.getThrowable(),
MediaEntityBuilder.createScreenCaptureFromPath(
reportRelativePath(image)).build());
The exact method signatures vary by ExtentReports and adapter version. Check the API matching the dependency installed in your build. If you need one self-contained HTML file, use the supported base64 media method, accepting the larger report size.
A simple custom HTML link
If you generate HTML yourself, emit a relative link or image tag using the path relative to the report file, not an absolute path from the build machine.
<a href="screenshots/login_test-abc123.png">
<img src="screenshots/login_test-abc123.png"
alt="Failure screenshot for login_test" />
</a>
Escape the test name and any exception text before inserting it into HTML. Treat report content as untrusted data when test parameters can contain user input.
Rank #3
- Affordable Versatility - A budget-friendly all-in-one printer perfect for both home users and hybrid workers, offering exceptional value
- Crisp, Vibrant Prints - Experience impressive print quality for both documents and photos, thanks to its 2-cartridge hybrid ink system that delivers sharp text and vivid colors
- Effortless Setup & Use - Get started quickly with easy setup for your smartphone or computer, so you can print, scan, and copy without delay
- Reliable Wireless Connectivity - Enjoy stable and consistent connections with dual-band Wi-Fi (2.4GHz or 5GHz), ensuring smooth printing from anywhere in your home or office
- Scan & Copy Handling - Utilize the device’s integrated scanner for efficient scanning and copying operations
Register the listener
Using testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="UI suite">
<listeners>
<listener class-name="example.FailureScreenshotListener"/>
</listeners>
<test name="browser tests">
<classes>
<class name="example.LoginTest"/>
</classes>
</test>
</suite>
Using @Listeners
import org.testng.annotations.Listeners;
@Listeners(FailureScreenshotListener.class)
public class LoginTest {
// test methods
}
The suite configuration applies the listener across the selected suite. The annotation is convenient for a class or a shared base test, but avoid registering the same listener through both mechanisms unless you deliberately want duplicate callbacks.
Make parallel execution reliable
- Store one driver per test thread or test scope; never let a global mutable field point to whichever browser started last.
- Include class, method, invocation, retry, and run identifiers in metadata or filenames.
- Create directories before workers write and use collision-resistant names.
- Capture before teardown calls
quit(). If teardown is ordered ahead of the listener in your framework, move cleanup later or capture in an earlier failure hook. - Synchronize only shared report objects when the reporting library requires it; do not serialize the browsers unnecessarily.
Keep report paths portable
Open the generated index.html from the same directory layout that your CI artifact viewer will use. A report that works on the build agent can show broken images after an artifact uploader flattens folders or copies only HTML files. Package the report directory, including its screenshot subdirectory, and verify every image link after extraction.
For base64 attachments, the HTML is more portable but can become very large when a suite captures many high-resolution images. For file references, storage is smaller and images can be opened independently, but the relative files are mandatory.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Common failures and fixes
No screenshot is created
Cause: the listener cannot obtain a driver, the driver has already quit, or the current driver does not implement TakesScreenshot as expected. Fix: log the listener failure separately, verify driver scope, and move capture before browser cleanup.
Rank #4
- The OfficeJet Pro 8125e is perfect for home offices printing professional-quality color documents like business documents, reports, presentations and flyers. Print speeds up to 10 ppm color, 20 ppm black
- PERFECTLY FORMATTED PRINTS WITH HP AI – Print web pages and emails with precision—no wasted pages or awkward layouts; HP AI easily removes unwanted content, so your prints are just the way you want
- UPGRADED FEATURES – Fast color printing, scan, copy, auto 2-sided printing, auto document feeder, and a 225-sheet input tra
- WIRELESS PRINTING – Stay connected with our most reliable dual-band Wi-Fi, which automatically detects and resolves connection issues
- 3 MONTHS OF INSTANT INK WITH HP+ ACTIVATION – Subscribe to Instant Ink delivery service to get ink delivered directly to your door before you run out. After 3 months, monthly fee applies unless cancelled.
The original assertion is replaced by a listener error
Cause: screenshot or report code throws from onTestFailure. Fix: catch attachment errors, preserve the original throwable, and treat the image as diagnostic data rather than a reason to fail the listener.
The report shows a broken image
Cause: the report contains an absolute build path, a wrong relative path, or the image was not copied. Fix: calculate the path relative to the HTML file, retain the directory tree, and inspect the final archived artifact.
Parallel tests overwrite screenshots
Cause: filenames contain only the method name. Fix: add a UUID, invocation number, or run identifier and keep driver state thread-scoped.
Recommended Free Tools
Images are blank or capture the wrong page
Cause: the failure happened during navigation, the page was still loading, or another test shared the session. Fix: isolate drivers, wait for the page state your test requires, and capture immediately at the failure callback.
Best Value
- AFFORDABLE ALL-IN-ONE FOR HOME AND HOME OFFICE: Print, copy, and scan on one compact wireless printer designed for everyday home office printing, schoolwork, documents, and reports. Produce beautiful prints for results that stand out.
- EASY TO USE WITH CLOUD APP CONNECTIONS: Print from and scan to popular Cloud apps(2), including Google Drive, Dropbox, Box, OneDrive, and more from the simple-to-use 1.8” color display on your printer.
- FULL-SIZE FEATURES IN A COMPACT DESIGN: This printer includes automatic duplex (2-sided) printing, a 20-sheet single-sided Automatic Document Feeder (ADF)(3), and a 150-sheet paper tray(3). Engineered to print at fast speeds of up to 16 pages per minute (ppm) in black and up to 9 ppm in color(4).
- MULTIPLE CONNECTION OPTIONS: Connect your way. Interface with your printer on your wireless network or via USB.
- MOBILE PRINTING MADE EASY: Go mobile with the Brother Mobile Connect app(5) that delivers easy onscreen menu navigation for printing, copying, scanning, and device management from your mobile device. Monitor your ink usage with Page Gauge to help ensure you don’t run out(6).
The adapter API does not compile
Cause: examples target a different ExtentReports Java or TestNG adapter version. Fix: align imports and method calls with the versions in your build file and consult that version’s documentation; do not copy an adapter example without checking compatibility.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Verify the workflow with a deliberate failure
- Create a test that fails after a distinctive page state appears.
- Run it through the same TestNG suite configuration used in CI.
- Confirm the listener executes once and writes a uniquely named image.
- Open the report from a copied or extracted artifact, not only the original workspace.
- Check that the image shows the failing state and that retries produce separate files.
- Run the same test with parallel workers to detect driver or filename collisions.
Or skip the browser setup
For services that only need a rendered page image rather than a screenshot taken inside the failing Selenium session, ScreenshotNeo provides a single HTTP call. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and each response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
See the parameter reference in the ScreenshotNeo documentation. cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
It also supports full-page and element capture, device and viewport settings, dark mode, retina scale, PDF output, custom CSS and JavaScript, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, caching, signed links, asynchronous webhooks, bulk capture, and a usage API. Every feature is available on every plan. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account.
Frequently Asked Questions
Can TestNG itself embed screenshots in index.html?
No. TestNG supplies lifecycle callbacks and standard result files; your listener and reporting library must save the image and add the HTML reference.
Should I use a listener and an IReporter together?
Use the listener to capture at failure time. Add an IReporter only when you also need post-suite assembly or transformation of the saved artifacts.
Why does a report work locally but not in CI?
The CI artifact usually lacks the image directory or has a changed relative layout. Archive the complete report directory and test the extracted copy.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteQuick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

