Taking Screenshots
An assertion tells you a test failed. A screenshot tells you what the browser actually looked like at the moment it failed — which locator broke, which page it landed on, whether an unexpected popup was in the way. Selenium captures screenshots through the TakesScreenshot interface, which every real WebDriver implementation (Chrome, Firefox, Edge) supports.
The TakesScreenshot Interface
WebDriver itself doesn't declare a screenshot method — you cast the driver to TakesScreenshot and call getScreenshotAs(), passing the output format you want.
WebDriver driver = new ChromeDriver();
driver.get("https://recipebox.example.com/recipes/add");
// Cast the driver to TakesScreenshot, then capture as a File
File screenshotFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
// Selenium writes it to a temp file; you must copy it somewhere permanent
File destination = new File("screenshots/recipe-saved.png");
FileUtils.copyFile(screenshotFile, destination); // e.g. org.apache.commons.io.FileUtils
Saving with a Timestamped Filename
Overwriting the same screenshot.png on every run makes it useless for debugging a specific failure. Timestamp the filename so every capture is kept.
public static String takeScreenshot(WebDriver driver, String label) throws IOException {
String timestamp = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date());
String fileName = label + "_" + timestamp + ".png";
File src = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
File dest = new File("screenshots/" + fileName);
FileUtils.copyFile(src, dest);
return dest.getAbsolutePath();
}
Capturing the "Recipe Saved!" Confirmation
Some moments are worth capturing even on a passing test — proof that the feature actually worked, not just that an assertion string matched. After RecipeBox saves a new recipe, it shows a confirmation banner reading "Recipe saved!". Here's a test that waits for it and screenshots it as evidence.
@Test
public void savingRecipeShowsConfirmation() throws IOException {
driver.findElement(By.id("recipeTitle")).sendKeys("Paneer Butter Masala");
driver.findElement(By.id("categoryDropdown")).sendKeys("Main Course");
driver.findElement(By.id("saveRecipeBtn")).click();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement confirmation = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.className("confirmation-banner"))
);
Assert.assertEquals(confirmation.getText(), "Recipe saved!");
// Capture proof of the confirmation screen
takeScreenshot(driver, "recipe_saved_confirmation");
}
Auto-Capturing a Screenshot on Failure
The pattern testers reach for the most: wrap the test body (or assertion) in a try/catch, and on any thrown exception or failed assertion, take a screenshot before re-throwing — so you never lose the failure evidence, and the test still reports as failed.
@Test
public void addRecipeAndCaptureFailures() {
try {
driver.findElement(By.id("recipeTitle")).sendKeys("Chicken Tikka Masala");
driver.findElement(By.id("saveRecipeBtn")).click();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement confirmation = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.className("confirmation-banner"))
);
Assert.assertEquals(confirmation.getText(), "Recipe saved!");
} catch (Throwable t) {
try {
takeScreenshot(driver, "FAILURE_addRecipe");
} catch (IOException ioEx) {
System.err.println("Could not save failure screenshot: " + ioEx.getMessage());
}
throw t; // re-throw so TestNG still reports the test as failed
}
}