Site icon TestingDocs.com

How to Take Screenshot when an Assert fails

Introduction

Let’s learn the steps involved to take screenshot in Selenium automation Tests using TestNG framework when an assert fails in test methods.

It’s an awesome capability  to capture a screenshot when an Assert fails with TestNG Framework. To get started, lets learn Assert life cycle in the TestNG Automation framework.

TestNG Assert Lifecycle

We can write custom assertions in TestNG by overriding the onAssertFailure() method in the Assert lifecycle. This capability hooks this method to capture the screen whenever an Assert Fails during the test runs. To know more about TestNG Assert Life Cycle:

https://www.testingdocs.com/testng-assert-lifecycle/

Sample Code Listing:

Custom implementation of SoftAssert class that overrides the lifecycle method.

package com.testingdocs.testng.tutorial;

//############################################
// www.TestingDocs.com
// CustomSoftAssert.java this class is-A subclass
// of SoftAssert and overrides the life-cycle method
// onAssertFailure().
//#############################################

import java.io.File;
import java.io.IOException;
import java.util.Date;

import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.testng.ITestContext;
import org.testng.asserts.Assertion;
import org.testng.asserts.IAssert;
import org.testng.asserts.SoftAssert;
import org.apache.commons.io.FileUtils;

public class CustomSoftAssert extends SoftAssert {
	private WebDriver driver;
	public CustomSoftAssert(WebDriver driver) {
		this.driver=driver;
	}

	@Override
	public void onAssertFailure(IAssert<?> assertCommand, 
AssertionError ex) {
		System.out.println("Assert Failed...");
		File scrFile = ((TakesScreenshot) driver)
				.getScreenshotAs(OutputType.FILE);
		try {
			FileUtils.copyFile(scrFile, new 
File("AssertFailure_"
					+ assertCommand.getMessage() + ".jpg"));
		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Failing Test – Assert Fails

Let’s write a failing test to capture the screenshot and We can instantiate the class and use it in the test classes.

package com.testingdocs.testng.tutorial;

/**********************************************************
// AssertFailScreenshot.java 
// Sample Failing Test to capture screenshot
// when an assert fails. 
// MyCustomizationListener is used to highlight the 
// web element in the screenshot.
// www.TestingDocs.com
 ************************************************************/

import java.io.IOException;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.events.EventFiringWebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;

public class AssertFailScreenshot {
	public WebDriver tDocsDriver;
	public EventFiringWebDriver eFireDriver = null;
	public CustomSoftAssert csa;

	@BeforeSuite
	public void setup() {
		System.setProperty("webdriver.chrome.driver", 
"drivers/chromedriver.exe");
		tDocsDriver=new ChromeDriver();
		eFireDriver = new EventFiringWebDriver(tDocsDriver);
		MyCustomizationListener myListener = new 
MyCustomizationListener(); 
		eFireDriver.register(myListener);
		csa = new CustomSoftAssert(eFireDriver);
	}

	@Test
	public void sampleAssertFailureTest() throws IOException {
		eFireDriver.get("https://www.twitter.com/login");
		eFireDriver.manage().window().maximize();
		eFireDriver.findElement(
By.name("session[username_or_email]")).clear();
		eFireDriver.findElement(
By.name("session[username_or_email]")).sendKeys("TestingDocs.com");
		WebDriverWait wait = new 
WebDriverWait(eFireDriver, Duration.ofSeconds(120, 1));
		wait.until(ExpectedConditions
.titleContains("Twitter"));
		csa.assertEquals("BogusTitle", 
eFireDriver.getTitle(),	"AssertTwitterLoginPage");
		csa.assertAll();
	}

	@AfterSuite
	public void cleanUp() {
		eFireDriver.close();
	}
}


 

By running the above code, you can capture a screenshot of the failed assert. The screenshot filename will be created with the Assert message as shown in the above code snippet.

 

Custom Listener to paint the web elements found by the Selenium web tests.

package com.testingdocs.testng.tutorial;

/*************************************************
 *  MyCustomizationListener.java is-A 
 *  AbstractWebDriverEventListener adds implementation 
 *  to beforeFindBy() paints web element with
 *  green color.
 ************************************************/
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.events.
AbstractWebDriverEventListener;

public class MyCustomizationListener extends 
AbstractWebDriverEventListener {
	public void beforeFindBy(By by, WebElement element, 
WebDriver driver){
		WebElement webelement = driver.findElement(by); 
		if (driver instanceof JavascriptExecutor) { 
			((JavascriptExecutor)driver)
.executeScript("arguments[0].style.border='10px solid green'",
 webelement);
		} 
	} 
}



Common mistakes

Debugging why the screenshots are not created when tests and assert fails. Below are some of the common mistakes or pitfalls.

#Use Latest TestNG

Use the updated TestNG framework. TestNG testing framework might also have defects. So make sure you are using the updated and latest version of the tool. Remove deprecated code from your tests. Update your tests with the latest Selenium code.

#Use proper imports

Use of proper imports and dependencies in the tests. Screenshot code needs Webdriver driver object and file handling utilities.

For example:

import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;

POM dependency:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.8.0</version>
</dependency>

Test exceptions like TimeOut, SocketException exceptions fail fast and do not make the assert validations.

#Illegal screenshot filenames

The above code appends the Assert message to the screenshot file. This might fail if the assert message has some illegal character that is not allowed by the operating system filenames. The test will encounter InvalidPathException.

For example: if the assert message is Assert -> will fail.

 


sampleAssertFailureTest

java.nio.file.InvalidPathException: Illegal char <>> at index 23: 
AssertFailure_Assert1 -> will fail.jpg at 
java.base/sun.nio.fs.WindowsPathParser
.normalize(WindowsPathParser.java:182)
 at java.base/sun.nio.fs.WindowsPathParser
.parse(WindowsPathParser.java:153)
 at java.base/sun.nio.fs.WindowsPathParser
.parse(WindowsPathParser.java:77)
 at java.base/sun.nio.fs.WindowsPath
.parse(WindowsPath.java:92)
 at java.base/sun.nio.fs.WindowsFileSystem
.getPath(WindowsFileSystem.java:229)
 at java.base/java.io.File.toPath(File.java:2311)

Test Listener

We can mix this capability with Test listening to highlight web elements in the screenshots.

For more information:

https://www.testingdocs.com/eventfiringwebdriver/

https://www.testingdocs.com/questions/how-to-highlight-web-elements-on-the-page-in-selenium-tests/


 

Consider options for capabilities to capture every assert life cycle method. Try mixing the assert lifecycle hooks along with SoftAssert capability to listen to every assert in the @Test annotated method. You can now enhance these custom capabilities & hook them into the TestNG framework for enhanced, robust visual logging to the framework. In conclusion, we’ve created a powerful new capability to give greater control over the test runs.

 

TestNG Tutorials on this website can be found at:

https://www.testingdocs.com/testng-framework-tutorial/

For more details on the TestNG Framework, visit the official website of TestNG at:

https://testng.org

Exit mobile version