Take Smug Shot

When a test case fails, we want to take screenshot to make later debugging easier.

Things to consider when taking screenshot:

  • When shall we take screenshot?
    Whenever a case fails.
    and When will a test case fail?
    whenever an assertion fails, or when an exception is thrown out of our script

    And Screenshot shall be taken automatically upon failure

  • How shall we name our screenshot?
    • Screenshot name shall give you some hint on what test case it is associated with. Pre-fix screenshot name with test case name is a good idea.
    • Screenshot name shall be unique each time the case is run. Postfix screenshot name with current timestamp will do

Take Screenshot of Whole Page

WebDriver has a interface called TakesScreenshot, which is for taking care of screenshot. Almost all webdrivers implement this interface. We can simply cast our driver into TakesScreenshot, and call getScreenshotAs() method to generate the screenshot:

public void takeScreenshot(String screenshotName) {
if (driver instanceof TakesScreenshot) {
File tempFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
try {
FileUtils.copyFile(tempFile, new File(“screenshots/” + screenshotName + “.png”));
} catch (IOException e) {
// TODO handle exception
}
}
}

Capture the screenshot of a specific element only

We can crop the specific element out of entire page screenshot as following:

1. Take a whole page screenshot
2. Get the location of the element, and calculate its size.
3. Using java’s BufferedImage to crop the element out
4. Save the cropped part to disk
driver.get(“http://www.yourwebsite.com”);
WebElement ele = driver.findElement(By.id(“elementID”));

// Get entire page screenshot
File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
BufferedImage fullImg = ImageIO.read(screenshot);

// Get the location of element on the page
Point point = ele.getLocation();

// Get width and height of the element
int eleWidth = ele.getSize().getWidth();
int eleHeight = ele.getSize().getHeight();

// Crop the entire page screenshot to get only element screenshot
BufferedImage eleScreenshot= fullImg.getSubimage(point.getX(), point.getY(),
eleWidth, eleHeight);
ImageIO.write(eleScreenshot, “png”, screenshot);

// Copy the element screenshot to disk
File screenshotLocation = new File(“C:\\yourpath\\specificElement_screenshot.png”);
FileUtils.copyFile(screenshot, screenshotLocation);

Take screenshot automatically upon failure

WebDriver has this interface ‘WebDriverEventListener‘ which allows us to override corresponding event method with whatever action we want to take. In our case, we want to take screenshot when exception happens.

We need to register WebDriverEventListener with our driver, to make whole thing work.

This will make your script to take a screenshot for every Exception thrown by the underlying WebDriver, but not if you fail an assertTrue() check.

EventFiringWebDriver driver = new EventFiringWebDriver(yourWebDriver);
WebDriverEventListener errorListener = new AbstractWebDriverEventListener() {
@Override
public void onException(Throwable throwable, WebDriver driver) {
takeScreenshot(“some name”);
}
};
driver.register(errorListener);

If you’re using JUnit, use the @Rule and TestRule. This will take a screenshot if the test fails for whatever reason.

@Rule
public TestRule testWatcher = new TestWatcher() {
@Override
public void failed(Throwable t, Description test) {
takeScreenshot(“some name”);
}
};