Use of Map (Hashmap) with TestNG Dataprovider in Data Driven Testing.

In this article, i will talk about how to use Map (Hashmap) with TestNG DataProvider for Data Driven Testing in Selenium WebDriver. Before to this, let us understand little more about Map.

What is Map in Java?
—> Map is a interface in java and can implements various classes in java like Hashmap, Hashtable & many other. They are the part of collections framework and are used to handle. store data. Map interface represent the mapping in between key and value. What that mean it, in Map or hashmap, value is stored in the form of Key & Value pair. In this article i will try to demonstrate the same.

Map in testng dataprovider selenium webdriver

Syntax to define map –>  Map mapA = new HashMap();

How to add value in map?   –> mapA.put(“key1”, “element 1”);

How to get value from map?  –>  Object value = mapA.get(key);
–> Value from map can also be retrived by using Iterator. Shown in above screenshot.

Now, how to use Map to with TestNG Dataprovider in Data Driven Testing?

Let us suppose my Test data file is located at: C://Users//Prakash//Desktop//TestData.xlsx & it looks as shown in below image –

Test data for Data Driven Testing with Map and TestNG DataProvider

Now, our task is to pass value from row 2 onward to our test case using Map. Have a look on below Selenium Java code –

package demoPackage1;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class Testclass {

  @Test(dataProvider = "data")
  public void integrationTest(Map<Object, Object> map) {
    System.out.println("-------------Test case started ----------------");
    System.out.println(map.get("UserName"));
    System.out.println(map.get("Password"));
    System.out.println(map.get("DoB"));

    System.out.println("-------------Test case Ended ----------------");

  }

  @DataProvider(name = "data")
  public Object[][] dataSupplier() throws IOException {

    File file = new File("C://Users//Prakash//Desktop//TestData.xlsx");
    FileInputStream fis = new FileInputStream(file);

    XSSFWorkbook wb = new XSSFWorkbook(fis);
    XSSFSheet sheet = wb.getSheetAt(0);
    wb.close();
    int lastRowNum = sheet.getLastRowNum() ;
    int lastCellNum = sheet.getRow(0).getLastCellNum();
    Object[][] obj = new Object[lastRowNum][1];

    for (int i = 0; i < lastRowNum; i++) {
      Map<Object, Object> datamap = new HashMap<>();
      for (int j = 0; j < lastCellNum; j++) {
        datamap.put(sheet.getRow(0).getCell(j).toString(), sheet.getRow(i+1).getCell(j).toString());
      }
      obj[i][0] = datamap;

    }
    return  obj;
  }

}

Once you run above test case, Console output will looks like –

[TestNG] Running:
  C:\Users\Prakash\AppData\Local\Temp\testng-eclipse-1161438956\testng-customsuite.xml

-------------Test case started ----------------
user1
pass1
dob1
-------------Test case Ended ----------------
-------------Test case started ----------------
user2
pass2
dob2
-------------Test case Ended ----------------
-------------Test case started ----------------
user3
pass3
dob3
-------------Test case Ended ----------------
PASSED: integrationTest({UserName=user1, DoB=dob1, Password=pass1})
PASSED: integrationTest({UserName=user2, DoB=dob2, Password=pass2})
PASSED: integrationTest({UserName=user3, DoB=dob3, Password=pass3})

===============================================
    Default test
    Tests run: 3, Failures: 0, Skips: 0
===============================================


===============================================
Default suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================

[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@7c30a502: 47 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter2@7e0ea639: 15 ms
[TestNG] Time taken by org.testng.reporters.jq.Main@3ac3fd8b: 47 ms
[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@71be98f5: 16 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@511baa65: 15 ms
[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 0 ms

In Above Console O/P you can clearly see that, test case has been run 3 times with 3 set of test data & is taken from Excel sheet using testNG DataProvider.

 

Refer below video to understand more about How to use map and hashmap along with testng dataprovider –

Hope above example helps !!!

 

For more about Test Automation Framework, refer below links –

Automation Frameworks –

1. Why Automation Framework in selenium?
2. Types of Test Automation Framework in Selenium
         a. Page Object Model (POM)
         b. Data Driven Test Automation Framework
         c. Keyword Driven Test Automation Framework
         d. Hybrid Test Automation Framework
         e. Behavior Driven Development Framework

 

How to Run Failed test cases using TestNG?

When we run our test suite, sometime few test cases may fail because of various reasons like locator has been changed, because of defect or may be due to slow response of the system at some times.
Test cases failed because of slow response due to internet issue, should not fail actually, so we need to retry those test cases. Now the question is, how can we run the test cases which are failed.
Let us talk about how can we execute failed test cases using testng in selenium Webdriver.
Two approaches 
           1.      Using testng-failed.xml
           2.      Using IRetryAnalyser
Let us talk one by one. 

How to execute failed test cases using testng-failed.xml ?

Every time tests fail in a suite, TestNG creates a file called testng-failed.xml in the output directory. This XML file contains the necessary information to rerun only these methods that failed, allowing you to quickly reproduce the failures without having to run the entirety of your tests.
If you want to rerun the test exactly after the failure you need to call the method that failed. You can get that method name from ITestResult object.
If you want to rerun all the failed test cases together, then you can give the testng-failed.xml as input xml after the first execution.
Steps –
1-If your test cases are failing then once all test suite completed then you have to refresh your project. Right click on project > Click on refresh or Select project and press f5.
2-Check test-output folder, at last, you will get testng-failed.xml

3- Now simply run testng-failed.xml.
That’s done, it will execute your failed test cases

How to execute failed test cases using IRetryAnalyser?

Another way to run failed test cases using testng is, using IRetryAnalyser interface. Again this is very simple to implement.
How retryAnalizer works is, we define maximum retry count (how many times you wish to retry failed test case).
If the test case is failing, it shows as Skipped, and in the last try, it shows as test case failed. (if it continuous to fail till last retry count).
Let us create class for defining retry. Implement IRetryAnalyser.

package retrypackage;

import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;

public class RetryClass implements IRetryAnalyzer {

private int count = 1;
private static int maxTry = 3;

@Override
public boolean retry(ITestResult result) {
if(count<maxTry){
count++;
return true;
}
return false;
}

}

Using retryAnalyzer attribute in the @Test annotation

Next step is to associate your test cases with IRetryAnalyzer. In order to do this, you need to use the method below.

@Test(retryAnalyzer = Retry.class)
public void testCase() {
}

Now, create a sample test case, I am failing the test case purposely, so that we can observe the RetryAnalyzer functionality.
Below is sample test case –

package retrypackage;

import org.testng.Assert;
import org.testng.annotations.Test;

public class TestCase {

@Test(retryAnalyzer = RetryClass.class)
public void test(){
Assert.assertTrue(false);
}
}
Run the above test case as TestNG Test.
Below console Output shows, that test case as attempted to run 3 times as specified in retry class.
Console Output – 
[TestNG] Running:
  C:UsersPrakashAppDataLocalTemptestng-eclipse-1379819527testng-customsuite.xml
FAILED: test
java.lang.AssertionError: expected [true] but found [false]
     at org.testng.Assert.fail(Assert.java:94)
     at org.testng.Assert.failNotEquals(Assert.java:496)
     at org.testng.Assert.assertTrue(Assert.java:42)
     at org.testng.Assert.assertTrue(Assert.java:52)
     at retrypackage.TestCase.test(TestCase.java:10)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
     at java.lang.reflect.Method.invoke(Unknown Source)
     at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:85)
     at org.testng.internal.Invoker.invokeMethod(Invoker.java:639)
     at org.testng.internal.Invoker.retryFailed(Invoker.java:963)
     at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1142)
     at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
     at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
     at org.testng.TestRunner.privateRun(TestRunner.java:774)
     at org.testng.TestRunner.run(TestRunner.java:624)
     at org.testng.SuiteRunner.runTest(SuiteRunner.java:359)
     at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:354)
     at org.testng.SuiteRunner.privateRun(SuiteRunner.java:312)
     at org.testng.SuiteRunner.run(SuiteRunner.java:261)
     at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
     at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
     at org.testng.TestNG.runSuitesSequentially(TestNG.java:1215)
     at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
     at org.testng.TestNG.run(TestNG.java:1048)
     at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
     at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:230)
     at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:76)
SKIPPED: test
java.lang.AssertionError: expected [true] but found [false]
     at org.testng.Assert.fail(Assert.java:94)
     at org.testng.Assert.failNotEquals(Assert.java:496)
     at org.testng.Assert.assertTrue(Assert.java:42)
     at org.testng.Assert.assertTrue(Assert.java:52)
     at retrypackage.TestCase.test(TestCase.java:10)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
     at java.lang.reflect.Method.invoke(Unknown Source)
     at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:85)
     at org.testng.internal.Invoker.invokeMethod(Invoker.java:639)
     at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:816)
     at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1124)
     at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
     at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
     at org.testng.TestRunner.privateRun(TestRunner.java:774)
     at org.testng.TestRunner.run(TestRunner.java:624)
     at org.testng.SuiteRunner.runTest(SuiteRunner.java:359)
     at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:354)
     at org.testng.SuiteRunner.privateRun(SuiteRunner.java:312)
     at org.testng.SuiteRunner.run(SuiteRunner.java:261)
     at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
     at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
     at org.testng.TestNG.runSuitesSequentially(TestNG.java:1215)
     at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
     at org.testng.TestNG.run(TestNG.java:1048)
     at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
     at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:230)
     at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:76)
SKIPPED: test
java.lang.AssertionError: expected [true] but found [false]
     at org.testng.Assert.fail(Assert.java:94)
     at org.testng.Assert.failNotEquals(Assert.java:496)
     at org.testng.Assert.assertTrue(Assert.java:42)
     at org.testng.Assert.assertTrue(Assert.java:52)
     at retrypackage.TestCase.test(TestCase.java:10)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
     at java.lang.reflect.Method.invoke(Unknown Source)
     at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:85)
     at org.testng.internal.Invoker.invokeMethod(Invoker.java:639)
     at org.testng.internal.Invoker.retryFailed(Invoker.java:963)
     at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1142)
     at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
     at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
     at org.testng.TestRunner.privateRun(TestRunner.java:774)
     at org.testng.TestRunner.run(TestRunner.java:624)
     at org.testng.SuiteRunner.runTest(SuiteRunner.java:359)
     at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:354)
     at org.testng.SuiteRunner.privateRun(SuiteRunner.java:312)
     at org.testng.SuiteRunner.run(SuiteRunner.java:261)
     at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
     at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
     at org.testng.TestNG.runSuitesSequentially(TestNG.java:1215)
     at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
     at org.testng.TestNG.run(TestNG.java:1048)
     at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
     at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:230)
     at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:76)
===============================================
    Default test
    Tests run: 3, Failures: 1, Skips: 2
===============================================
===============================================
Default suite
Total tests run: 3, Failures: 1, Skips: 2
===============================================
[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@880ec60: 100 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter2@67b64c45: 15 ms
[TestNG] Time taken by [FailedReporter passed=0 failed=0 skipped=0]: 20 ms
[TestNG] Time taken by org.testng.reporters.jq.Main@39ba5a14: 77 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@17f6480: 8 ms
[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@35f983a6: 11 ms

How to execute test Methods / classes in parallel in TestNG framework?

Refer: Execute multiple classes from testng xml

We can achieve this by running the classes or tests or methods with multiple threads.
If we want to run methods/classes in separate threads, we need to set ‘parallel’ attribute on the tag to ‘methods’ / ‘classes’
In suite tag change the “parallel” attribute value from “tests” to “classes” for example:
If you wish to execute
  1. tests in parallel then use = parallel=”tests”
  2. classes in parallel then use = parallel=”classes”
  3. Methods in parallel then use = parallel=”methods”
The parallel attribute on the <suite> tag can take one of following values:
<suite name=”My suite” parallel=”methods” thread-count=”5″>
<suite name=”My suite” parallel=”tests” thread-count=”5″>
<suite name=”My suite” parallel=”classes” thread-count=”5″>
<suite name=”My suite” parallel=”instances” thread-count=”5″>
  • parallel=”methods”: TestNG will run all your test methods in separate threads. Dependent methods will also run in separate threads but they will respect the order that you specified. 
  • parallel=”tests”: TestNG will run all the methods in the same <test> tag in the same thread, but each <test> tag will be in a separate thread. This allows you to group all your classes that are not thread safe in the same <test> and guarantee they will all run in the same thread while taking advantage of TestNG using as many threads as possible to run your tests.
  • parallel=”classes”: TestNG will run all the methods in the same class in the same thread, but each class will be run in a separate thread.
  • parallel=”instances”: TestNG will run all the methods in the same instance in the same thread, but two methods on two different instances will be running in different threads.
Additionally, the attribute thread-countallows you to specify how many threads should be allocated for this execution.
Note: the @Test attribute timeOut works in both parallel and non-parallel mode.
You can also specify that a @Test method should be invoked from different threads. You can use the attribute threadPoolSize to achieve this result:
Refer below example –
Class1: 

package package1;

import org.testng.annotations.Test;

public class Class1 {
@Test
public void Package1Class1Test1(){
System.out.println("Package1Class1Test1 is executed with Thread count: "+Thread.currentThread().getId());
}
@Test
public void Package1Class1Test2(){
System.out.println("Package1Class1Test2 is executed with Thread count: "+Thread.currentThread().getId());
}

}
Class2:

package package1;

import org.testng.annotations.Test;

public class Class2 {

@Test
public void Package1Class2Test1(){
System.out.println("Package1Class2Test1 is executed with Thread count: "+Thread.currentThread().getId());
}
@Test
public void Package1Class2Test2(){
System.out.println("Package1Class2Test1 is executed with Thread count: "+Thread.currentThread().getId());
}
}
Use below testng.xml.

<?xml version="1.0" encoding="UTF-8"?>
<suite name="example suite 1" verbose="1" parallel="methods" thread-count="2" >
<test name="Test suite 1" >
<classes>
<class name="package1.Class1"/>
<class name="package1.Class2"/>
</classes>
</test>
</suite>
In above testng.xml you can see parallel = “methods” which let us to decide what can we run in parallel, if it is a class or it is a method etc.

Thread-count = “2” let us decide in how many threads you wish to do execution in parallel.

Observe below console output

Console output shows the tests / methods execution is done in parallel. Just look at thread count.
Console Output:
[TestNG] Running:
  C:UsersPrakashworkspacesampleProjecttestng.xml
Package1Class1Test1 is executed with Thread count: 11
Package1Class1Test2 is executed with Thread count: 12
Package1Class2Test1 is executed with Thread count: 12
Package1Class2Test1 is executed with Thread count: 11
===============================================
example suite 1
Total tests run: 4, Failures: 0, Skips: 0
===============================================

 

 

Execute multiple classes from testng xml.

Before we start with this article, one should know what is testng.xml? what are the content of Testng.xml.
Below is recommended article to understand about testng.xml

What is TestNG.xml?

Now, let us talk about running multiple classes via testng.xml file.
Our test cases will be in different classes, we can run multiple classes from testng.xml
Let us take some example.
I have created 2 packages having different classes in it. Each class have various tests in it.

Let us see how can we run all these in single testng.xml file.
Class1 of Package1: 

package package1;

import org.testng.annotations.Test;

public class Class1 {
@Test
public void Package1Class1Test1(){
System.out.println("Package1Class1Test1 is executed");
}
@Test
public void Package1Class1Test2(){
System.out.println("Package1Class1Test2 is executed");
}

}
Class2 of Package1:

package package1;

import org.testng.annotations.Test;

public class Class2 {

@Test
public void Package1Class2Test1(){
System.out.println("Package1Class2Test1 is executed");
}
@Test
public void Package1Class2Test2(){
System.out.println("Package1Class2Test2 is executed");
}
}

Class1 of Package2:

package package2;

import org.testng.annotations.Test;

public class Class1 {

@Test
public void Package2Class1Test1(){
System.out.println("Package2Class1Test1 is executed");
}
@Test
public void Package2Class1Test2(){
System.out.println("Package2Class1Test2 is executed");
}

@Test
public void Package2Class1Test3(){
System.out.println("Package2Class1Test3 is executed");
}

}

Now, we can create testng.xml file.
In testng.xml, under tag <classes> We can add multiple classes, so that all classes will run.
Below is testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<suite name="example suite 1" verbose="1" >
<test name="Test suite 1" >
<classes>
<class name="package1.Class1"/>
<class name="package1.Class2"/>
<class name="package2.Class1"/>
</classes>
</test>
</suite>

 

Below console output shows, all the classes mentioned in testng.xml has run.
Console Output:
[TestNG] Running:
  C:UsersPrakashworkspacesampleProjecttestng.xml
Package1Class1Test1 is executed
Package1Class1Test2 is executed
Package1Class2Test1 is executed
Package1Class2Test2 is executed
Package2Class1Test1 is executed
Package2Class1Test2 is executed
Package2Class1Test3 is executed
===============================================
example suite 1
Total tests run: 7, Failures: 0, Skips: 0
===============================================
Hope this helps !!!!

 
 

Logging using Listeners (ITestListener) in TestNG

Logging is very important in selenium framework, it helps us to understand the code, it helps a lot while debugging, and lot many other advantages.
For logging the message in selenium, we have multiple options. One way is to use Log4J API.
Refer below post to know how can we do logging using Log4j.
Another way to perform logging is, with the help of ITestListener interface of TestNG.
To achieve this, we need to trigger an event (of capturing screen shot) whenever any test case fails. 
We can use testng listener for this purpose.
Once we implement ITestListener interface, below methods are created –
onFinish -> you can write some message here which will be written in to log file after finishing execution.
onStart -> you can write some message here which will be written in to log file after execution starts.
onTestFailedButWithinSuccessPercentage -> written in to log file after test failed, but within success percentage.
onTestFailure -> you can write some message here which will be written in to log file if test fails.
onTestSkipped -> you can write some message here which will be written in to log file if test skips.
onTestSuccess -> you can write some message here which will be written in to log file after successful execution of test.
Let us see how can we use ITestListener
Basically, ITestListener is an interface, which we need to implement in our class.
Follow these steps to take screen shot of failed test cases only.
         1.      Create sample class & implement ITestListener
         2.      After implementation, various methods are created. Put the proper message as required.
         3.      Define listener either in testng.xml (if you want to apply this for all the classes which are going to execute from testng.xml) or in the class which contains testng tests (if you want to apply this to only some specific class)
         4.      That’s it, all done. Refer below code & screenshots.
Create a sample class and implements ITestListener in it.
When you import ITestListener in the class, you will see option to implement unimplemented methods.
Refer below screen shot.
Once clicked on “Add unimplemented methods”, all methods will be implemented, code will look like –

package screenshotOfFailedTest;

import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

public class ListenerClass implements ITestListener {

@Override
public void onFinish(ITestContext arg0) {
// write the logging code here which will be executed on test finish
log("Test Finished....");

}

@Override
public void onStart(ITestContext arg0) {
// write the logging code here which will be executed on test start
log("Test Started....");

}

@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult arg0) {
// write the logging code here which will be executed on test failure within success %
log("Test failed but is within....");

}

@Override
public void onTestFailure(ITestResult arg0) {
// write the logging code here which will be executed on test failure
log("Test failed....");

}

@Override
public void onTestSkipped(ITestResult arg0) {
// write the logging code here which will be executed on test skip
log("Test Skipped....");

}

@Override
public void onTestStart(ITestResult arg0) {
// write the logging code here which will be executed on test start
log("Test Started....");

}

@Override
public void onTestSuccess(ITestResult arg0) {
// write the logging code here which will be executed on test success
log("Test completed successfully....");

}

}
In the above code, ITestResult is an interface which keeps all information about test case which is being executed. It captures some information like Test case execution status, test case name etc.
Note: Using ITestResult is variable, we can get various states / information about current test, which is under execution, like – arg0.getName(), arg0.getMethod().getPriority()
               
Refer below code in which we will use above defined Listener.

package screenshotOfFailedTest;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;


@Listeners (screenshotOfFailedTest.ListenerClass.class)

public class SampleTest {

public static WebDriver driver;

@Test
public void TestCase(){
driver = new FirefoxDriver();
driver.navigate().to("https://learnaboutsoftwaretesting.blogspot.in/");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().window().maximize();

driver.findElement(By.xpath("invalidXpath")).click(); //using invalid xpath so that test will fail & we can invoke ITestListener.
}

}

So, in above program, test is failing, since listener is used there, onTestfailure() method will execute.
Note: We need to mention somewhere about listenerclass in our test case. There are 2 ways to do so. You may like to do this at class level (this will be applicable to all test cases in that class) or you may like to do this at suite level (which will be applicable to whole suite. You need to define this in testng.xml file).
In above example. I have done it for class level by adding below line of code for listener.
                              @Listeners(screenshotOfFailedTest.ListenerClass.class)
Hope this helps !!!!!

What is SoftAssert in TestNG (Selenium)?

To overcome the disadvantage that HardAssert has (it stops the execution of test after assertion error has occurred), a customized error handler is provided by TestNG, called SoftAssert.
SoftAssert – collects errors during @Test (no exception is thrown) and if you call org.testng.asserts.SoftAssert#assertAll at the end of @Testexception is thrown if there was any and test suite again continue with next @Test
If there are multiple assert in test case, and suppose your first assert fails, then in case of SoftAssert, test case will not fail immediately after assertion error has occurred. It continuous the processing for next statements. If will go till the end of the test even though multiple assertion error occurs. Finally we need to use assertAll(); method of SoftAssert, which will check if any of the assert exception has occurred, if any, then it will fail the test case (but after executing all the statements in the test).
Note: make sure that you use assertAll(); method at last. If you don’t use it, your test case will pass even if multiple assert errors are in test.
Below example shows the difference between softAssert & Hard Assert
Example

package samplePackage;

import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;


public class Asserts {

@Test
public void softAssertTest(){
System.out.println("------------OutPut for SoftAssert --------------------------");

//In case of SoftAssert, we need to create object of it, & then use that object (unlike normal assert)
SoftAssert a = new SoftAssert();

System.out.println("I am Before SoftAssert statment");
//Failing assert so that assertion error should occur
a.assertTrue(false);
System.out.println("I am After SoftAssert statment1");

a.assertTrue(false);

System.out.println("I am After SoftAssert statment2");

a.assertTrue(false);

System.out.println("I am After SoftAssert statment3");

a.assertAll();

}

}
Observe the below console output,
Even if assertion error occurs, it continued execution till end, & lastly it failed test.
Console Output: 

[TestNG] Running:
  C:UsersPrakashAppDataLocalTemptestng-eclipse–212981613testng-customsuite.xml
————OutPut for SoftAssert ————————–
I am Before SoftAssert statment
I am After SoftAssert statment1
I am After SoftAssert statment2
I am After SoftAssert statment3
FAILED: softAssertTest
java.lang.AssertionError: The following asserts failed:
     expected [true] but found [false],
     expected [true] but found [false],
     expected [true] but found [false]
     at org.testng.asserts.SoftAssert.assertAll(SoftAssert.java:48)
     at samplePackage.Asserts.softAssertTest(Asserts.java:29)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
     at java.lang.reflect.Method.invoke(Unknown Source)
     at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:85)
     at org.testng.internal.Invoker.invokeMethod(Invoker.java:639)
     at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:821)
     at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1131)
     at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:124)
     at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
     at org.testng.TestRunner.privateRun(TestRunner.java:773)
     at org.testng.TestRunner.run(TestRunner.java:623)
     at org.testng.SuiteRunner.runTest(SuiteRunner.java:357)
     at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:352)
     at org.testng.SuiteRunner.privateRun(SuiteRunner.java:310)
     at org.testng.SuiteRunner.run(SuiteRunner.java:259)
     at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
     at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
     at org.testng.TestNG.runSuitesSequentially(TestNG.java:1185)
     at org.testng.TestNG.runSuitesLocally(TestNG.java:1110)
     at org.testng.TestNG.run(TestNG.java:1018)
     at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
     at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:230)
     at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:76)
===============================================
    Default test
    Tests run: 1, Failures: 1, Skips: 0
===============================================

Hope this helps !!!!

What are the assertions in TestNG framework?

Assert class is provided by TestNG and not by Selenium. Assertion in selenium are used to perform validation checks in test cases, which helps us to decide if the test case is passed or failed.
There are two types if asserts.
             
            1.     HardAsserts (or simply Assert )
HardAssert – throws AssertException immediately, test is marked as failed and test suited continues with next test cases. If hard Assert fails, other assertions in the test case will not be executed and test fails immediately.
If there are multiple assert statements in the test, and suppose your first assert fails, then in case of Hard Assert (or simply termed as assert), test case will fail immediate after AssertException occurs. If does not continues the processing for next statements. Stops the execution of test case there itself.
The disadvantage of HardAssert is, it stops the execution of test after assertion error has occurred.
        
           2.    SoftAssert
To overcome the disadvantage that HardAssert has (it stops the execution of test after assertion error has occurred), a customized error handler is provided by TestNG, called SoftAssert.
SoftAssert – collects errors during @Test (no exception is thrown) and if you call org.testng.asserts.SoftAssert#assertAll at the end of @Testexception is thrown if there was any and test suite again continue with next @Test
If there are multiple assert in test case, and suppose your first assert fails, then in case of SoftAssert, test case will not fail immediately after assertion error has occurred. It continuous the processing for next statements. If will go till the end of the test even though multiple assertion error occurs. Finally we need to use assertAll(); method of SoftAssert, which will check if any of the assert exception has occurred, if any, then it will fail the test case (but after executing all the statements in the test).
Note: make sure that you use assertAll(); method at last. If you don’t use it, your test case will pass even if multiple assert errors are in test.
Below example shows the difference between softAssert & Hard Assert
Example – 

package samplePackage;

import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;


public class Asserts {

@Test
public void hardAssertTest(){
System.out.println("------------OutPut for HardAssert --------------------------");
System.out.println("I am Before HardAssert statment");

//failing the assert, so that it will not execute any statment after assert fails (in case of assert (soft assert))
Assert.assertTrue(false);
System.out.println("I am After HardAssert statment");

}

@Test
public void softAssertTest(){
System.out.println("------------OutPut for SoftAssert --------------------------");

//In case of SoftAssert, we need to create object of it, & then use that object (unlike normal assert)
SoftAssert a = new SoftAssert();

System.out.println("I am Before SoftAssert statment");
//Failing assert so that assertion error should occur
a.assertTrue(false);
System.out.println("I am After SoftAssert statment1");

a.assertTrue(false);

System.out.println("I am After SoftAssert statment2");

a.assertTrue(false);

System.out.println("I am After SoftAssert statment3");



}

}
Observe the below console output, 
In case of HardAssert, if assertion error occurs, it has stopped execution  
In case of SoftAssert, even if assertion error occurs, it continued execution till end, & lastly it failed test.  
Console Output: 
[TestNG] Running:
  C:UsersPrakashAppDataLocalTemptestng-eclipse-1927411577testng-customsuite.xml
————OutPut for HardAssert ————————–
I am Before HardAssert statment
————OutPut for SoftAssert ————————–
I am Before SoftAssert statment
I am After SoftAssert statment1
I am After SoftAssert statment2
I am After SoftAssert statment3
FAILED: hardAssertTest
java.lang.AssertionError: expected [true] but found [false]
     at org.testng.Assert.fail(Assert.java:94)
     at org.testng.Assert.failNotEquals(Assert.java:496)
     at org.testng.Assert.assertTrue(Assert.java:42)
     at org.testng.Assert.assertTrue(Assert.java:52)
     at samplePackage.Asserts.hardAssertTest(Asserts.java:16)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
     at java.lang.reflect.Method.invoke(Unknown Source)
     at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:85)
     at org.testng.internal.Invoker.invokeMethod(Invoker.java:639)
     at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:821)
     at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1131)
     at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:124)
     at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
     at org.testng.TestRunner.privateRun(TestRunner.java:773)
     at org.testng.TestRunner.run(TestRunner.java:623)
     at org.testng.SuiteRunner.runTest(SuiteRunner.java:357)
     at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:352)
     at org.testng.SuiteRunner.privateRun(SuiteRunner.java:310)
     at org.testng.SuiteRunner.run(SuiteRunner.java:259)
     at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
     at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
     at org.testng.TestNG.runSuitesSequentially(TestNG.java:1185)
     at org.testng.TestNG.runSuitesLocally(TestNG.java:1110)
     at org.testng.TestNG.run(TestNG.java:1018)
     at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
     at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:230)
     at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:76)
FAILED: softAssertTest
java.lang.AssertionError: The following asserts failed:
     expected [true] but found [false],
     expected [true] but found [false],
     expected [true] but found [false]
     at org.testng.asserts.SoftAssert.assertAll(SoftAssert.java:48)
     at samplePackage.Asserts.softAssertTest(Asserts.java:41)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
     at java.lang.reflect.Method.invoke(Unknown Source)
     at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:85)
     at org.testng.internal.Invoker.invokeMethod(Invoker.java:639)
     at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:821)
     at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1131)
     at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:124)
     at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
     at org.testng.TestRunner.privateRun(TestRunner.java:773)
     at org.testng.TestRunner.run(TestRunner.java:623)
     at org.testng.SuiteRunner.runTest(SuiteRunner.java:357)
     at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:352)
     at org.testng.SuiteRunner.privateRun(SuiteRunner.java:310)
     at org.testng.SuiteRunner.run(SuiteRunner.java:259)
     at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
     at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
     at org.testng.TestNG.runSuitesSequentially(TestNG.java:1185)
     at org.testng.TestNG.runSuitesLocally(TestNG.java:1110)
     at org.testng.TestNG.run(TestNG.java:1018)
     at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
     at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:230)
     at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:76)
===============================================
    Default test
    Tests run: 2, Failures: 2, Skips: 0
===============================================
Hope this helps !!!!

How to take ScreenShot of failed test case using TestListenerAdapter class?

In TestNG, we can generate logs for some specific conditions like OnTestStart, OnTestSuccess, OnTestFailure, and many other. Most of us prefer to take the screen shot of the failed test case.
To Achieve this, you can either extends TestListenerAdapter or implement and interdate ITestListener.
By using TestNG listeners ‘ITestListener’ or ‘TestListenerAdapter’ we can change the default behavior write our own implementation when a Test fails or Skips etc.
TestListenerAdapter internally implements ITestListener Interface only. So, using them is like one and same.
Here, we will see how can we take logs / take screen shot of failed test cases by using TestListenerAdapter.
To know how can we achieve the same using ITestListener, refer below post – 
To start, Create one sample test case.

package screenshotOfFailedTest;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;


@Listeners (screenshotOfFailedTest.CustomListener.class)

public class SampleTest {

public static WebDriver driver;

@Test
public void TestCase(){
driver = new FirefoxDriver();
driver.navigate().to("https://learnaboutsoftwaretesting.blogspot.in/");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().window().maximize();

driver.findElement(By.xpath("invalidXpath")).click(); //using invalid xpath so that test will fail & we can invoke ITestListener.
}

}

Note: We need to mention somewhere about listenerclass in our test case. There are 2 ways to do so. You may like to do this at class level (this will be applicable to all test cases in that class) or you may like to do this at suite level (which will be applicable to whole suite. You need to define this in testng.xml file).
In above example. I have done it for class level by adding below line of code for listener.
                              @Listeners(screenshotOfFailedTest.ListenerClass.class)
Now, create a class for customListenerwhich will extends to TestListenerAdapter. Write the code to capture screen shot in OnTestFailure method.

package screenshotOfFailedTest;

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;

public class CustomListener extends TestListenerAdapter {

public void onTestFailure(ITestResult result){

TakesScreenshot ts = (TakesScreenshot)SampleTest.driver;
File srcFile = ts.getScreenshotAs(OutputType.FILE);

try {
FileUtils.copyFile(srcFile, new File("./ScreenShots/"+result.getName()+".jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}

}
That’s it, all done, when you run this sample test case & if the test case fails, it will capture screen shot.
Hope this helps!!!