This listener tracks everything about test cases execution.
Requirement is → take screenshots for every failure test cases.
If you are not aware of listeners then every time you will be checking whether test case is failed or not. Then writing a code for screen shot. This is not good for maintenance to overcome this we can use listener.
Step 1: create listener class implements it with ITestListener. Try reading name of every method, you will easily understand what that method does its self-explanatory.
package com.javabykiran;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
public class TrackTestExecution implements ITestListener {
@Override
public void onTestStart(ITestResult result) {
System.out.println("onTestStart>> ");
}
@Override
public void onTestSuccess(ITestResult result) {
System.out.println("onTestSuccess>> ");
}
@Override
public void onTestFailure(ITestResult result) {
System.out.println("onTestFailure >> ");
}
@Override
public void onTestSkipped(ITestResult result) {
System.out.println("onTestSkipped>> ");
}
@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
System.out.println("onTestFailedButWithinSuccessPercentage>> ");
}
@Override
public void onStart(ITestContext context) {
System.out.println("onStart>> ");
}
@Override
public void onFinish(ITestContext context) {
System.out.println("onFinish>> ");
}
}
Just to explain
@Override
public void onTestFailure(ITestResult result) {
System.out.println("onTestFailure >> ");
}
Above method which will get executed for every failure of any test cases so we can write any code here which we want to execute for every failure of test case.
Now we can add screen shot code of selenium write here.
Step 2: Modify testng.xml file to add listener entry there. So that whenever our suite runs it initializes listener and it will watch our execution.
Run above xml and observe output.
Now we will see one live example, it is using data provider.
1) ListenerTest.java
package com.javabykiran;
import java.io.IOException;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
public class ListenerTest implements ITestListener {
@Override
public void onFinish(ITestContext result){
System.out.println("test cases finished time >> :: "+re- sult.getName() );
System.out.println("finish time >> "+new java.util.Date());
}
@Override
public void onStart(ITestContext result){
System.out.println("test cases finished time >> :: "+result.getName() );
System.out.println("start time >> "+new java.util.Date());
}
@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult arg0){
}
// This method takes screen shots after test case failed.
@Override
public void onTestFailure(ITestResult result){
try {
CaptureScreenShot.capture(result.getName());
}catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onTestSkipped(ITestResult arg0)
{
// TODO Auto-generated method stub
}
@Override
public void onTestStart(ITestResult arg0)
{
// TODO Auto-generated method stub
}
@Override
public void onTestSuccess(ITestResult arg0)
{
// TODO Auto-generated method stub
}
}
2) DataProviderEx.java
package com.javabykiran;
import org.testng.annotations.BeforeClass;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class DataProviderEx {
public static WebDriver driver;
WebElement weUserName;
WebElement wePassword;
WebElement weSignInButton;
WebElement weErrorMessage;
@BeforeSuite
public void setupEnvironMent(){
driver = new FirefoxDriver();
driver.get("http://www.javabykiran.com/selenium/demo");
}
@BeforeClass
public void locateAllWebElements(){
weUserName=driver.findElement(By.xpath("//*[@id=\"email\"]"));
wePassword=driver.findElement(By.xpath("//*[@id=\"password\"]"));
weSignInButton=driver.findElement(By.xpath("//*[@id=\"form\"]/ div[3]/div/button"));
}
@BeforeMethod
public void clearAllTextBoxes(){
weUserName.clear(); wePassword.clear();
}
@Test(dataProvider = "login-data",dataProviderClass = DataProviderEx.class,groups="smoke")
public void LoginTestCases(String tcId,String tcDescr,String uname,String passwd,String expResult){
// printing all data we got for each test case.
System.out.println(tcId + " tcDescr>> " + tcDescr + " uname " + uname + " passwd " + passwd + " expResult " + expResult);
// we start putting data in text boxes.
weUserName. sendKeys(uname);
wePassword.sendKeys(passwd);
// click on signIn button for getting error message.
weSignInButton.click();
// Now we will start testing error messages.
if(!"validus- er".equals(tcDescr))
{
weErrorMessage=driver.findElement(By.xpath("//*[@id=\"email_er- ror\"]"));
String actualMessage=weErrorMessage.getText();
Assert.assertEquals(actualMessage, expResult);
}
else
{
String actualTitle=driver.getTitle();
Assert.assertEquals(actualTitle, expResult);
}
}
@DataProvider(name = "login-data") public Object[][] loginData(){
return new Object[][] { new Object[] { "TC01", "blankUser", "", "", "Please enter email." },
new Object[] { "TC02", "invaliduser", "hellokiran", "kiranpassword", "Please enter email as kiran@gmail.com" },
new Object[]{ "TC03", "validuser", "kiran@ gmail.com", "123456", "AdminLTE 2 | Dashboard 11" },};
}
@AfterSuite
public void closeBrowser()
{
driver.close();
}
}
3) CaptureScreenShot.java
package com.javabykiran;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
public class CaptureScreenShot{
public static String capture(String screenshotName) throws IOException {
TakesScreenshotts = (TakesScreenshot) DataProviderEx.driver;
File source = ts.getScreenshotAs(OutputType.FILE);
String dest = System.getProperty("user.dir") + "/ErrorScreenshot/"+ screenshotName + ".png"; File destination = new File(dest);
FileUtils.copyFile(source, destination);
return dest;
}
}
4) Testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="Test">
<classes>
<class name="com.javabykiran.DataProviderEx"/>
</classes>
</test><!-- Test -->
<listeners>
<listener class-name="com.javabykiran.ListenerTest"></listener>
</listeners>
</suite><!-- Suite -->
Sometimes our test case fails because of setup,network issue, Random browser issues etc not because of product bug. TestNG provides a RetryAnalyzer interface feature using which we can retry a test case multiple times before declaring it as Failed.
public interface IRetryAnalyzer {
/**
* Returns true if the test method has to be retried, false otherwise.
*
* @param result The result of the test method that just ran.
* @return true if the test method has to be retried, false otherwise.
*/
public boolean retry(ITestResult result);
}
As above IRetryAnalyzer has only one method.
i.e : public boolean retry(ITestResult result);
Below is IRetryAnalyzer implementation
Here we are creating maven project and adding dependencies for Retryanalyzer so all the required jars will add in project.
POM.xml
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jbk</groupId>
<artifactId>RetryAnalyzerSample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.beust/jcommander -->
<dependency>
<groupId>com.beust</groupId>
<artifactId>jcommander</artifactId>
<version>1.7</version>
</dependency>
</dependencies>
</project>
Create a class which implement IRetryAnalyzer interface as below:
package com.jbk;
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
public class RetryTest implements IRetryAnalyzer{
int counter = 0;
int retryLimit = 4;
/*
* (non-Javadoc)
* @see org.testng.IRetryAnalyzer#retry(org.testng.ITestResult)
*
* This method decides how many times a test needs to be rerun.
* TestNg will call this method every time a test fails. So we
* can put some code in here to decide when to rerun the test.
* Note: This method will return true if a tests needs to be retried and false it not.
*/
public boolean retry(ITestResult result) {
// TODO Auto-generated method stub
if(counter < retryLimit)
{
counter++;
return true;
}
return false;
}
}
In order for TestNG to know about retry analyzer implementation, it provides a retryAnalyzer property in @Test annotation. So below is a small code of how the test configuration would look like:
Create a class which implement IRetryAnalyzer interface as below:
package com.jbk;
import org.testng.Assert;
import org.testng.annotations.Test;
public class SampleTest {
@Test(retryAnalyzer = RetryTest.class) public void Test1(){
Assert.assertEquals(false, true);
}
@Test
public void Test2(){
Assert.assertEquals(false, true);
}
}
Here we are failing both TC and provides a retryAnalyzer property for only first testcase. So once first TC will fail again it will execute the same TC as per mention in retry limit. Here first time TC fails then it will retry again till retry limit i.e 4 so the same TC will execute 5 times and the result will look like as below :
List of other testNG listeners (only remember, no need to check example of these)
IAnnotationTransformer
IAnnotationTransformer2
IHookable
IInvokedMethodListener
IMethodInterceptor
IReporter
ISuiteListener
ITestListener
IRetryAnalyzer -- Retry Failed Tests in TestNG