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!!!

How to take ScreenShot of failed test case using ITestResult interface in @AfterMethod annotation?

Taking Screen shot of all the test cases may create a memory issue, because we will be running the automation suite multiple times. Moreover, we can see the status of test cases (pass / failed / skipped) in the testing report. 
So, what is better is, to take the screen shot of only failed test cases.
To achieve this, we can use ITestResult interface in @AfterMethod annotation of testng.
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
What we can do here is, in @AfterMethod annotation, get the status of the test using ITestResult Interface & check if it is failed. If failed then capture the screen shot. As simple as that.
Below Example Explains this.

package screenshotOfFailedTest;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;

public class CaptureScreenShotUsingITestResult {

WebDriver driver;

@Test
public void Testcase1(){

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("ajhjhj")).click(); //take incorrect xpath, so that test will fail becuase element does not exist.

}

@AfterMethod
public void TearDown(ITestResult result) throws IOException{

if (result.getStatus() == ITestResult.FAILURE ){
TakesScreenshot ts = (TakesScreenshot)driver;
File srcFile = ts.getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(srcFile, new File("./ScreenShots/"+result.getName()+".jpg"));
//result.getname() method will give you current test case name.
//./ScreenShots/ tell you that, in your current directory, create folder ScreenShots. dot represents current directory
}
}

}

To know about how the same can be achieved using ITestListener, refer below post –
Hope This Helps!!!

 

How to take ScreenShot of failed test case using ITestListener Interface?

Taking Screen shot of all the test cases may create a memory issue, because we will be running the automation suite multiple times. Moreover, we can see the status of test cases (pass / failed / skipped) in the testing report. 
So, what is better is, to take the screen shot of only failed test cases.
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.
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.      Write code to capture screen shot in OnTestFailure Method.
v        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) {
// TODO Auto-generated method stub

}

@Override
public void onStart(ITestContext arg0) {
// TODO Auto-generated method stub

}

@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult arg0) {
// TODO Auto-generated method stub

}

@Override
public void onTestFailure(ITestResult arg0) {
// TODO Auto-generated method stub

}

@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

}

}
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.
Now, if you want to capture screen shot of only failed test cases, then you need to write the code to capture screen shot in OnTestFailure method.

Note:
To take screen shot in selenium, we have one predefined interface known as TakesScreenshot, we can not create object of an interface in java. So we need to typecast it to Webdriver object.
                TakesScreenshot ts = (TakesScreenshot)driver;       (can’t create object directly so typecast and then create ).
                File srcFile = ts.getScreenShotAs(OutPutType.FILE);              (use the object created, then get screenshot as file & assign it to the File variable).
           FileUtils.copyFile(srcFile, new File(“./ScreenShots/image1.png”);        (now you need to copy the srcFile, so use FileUtils class, then give source file & destination file. In destination file “.” (dot) refers to the current working directory)     
                            
Refer below code now –
First 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.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.
}

}
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, Update the above created listener class for onTestFailure method. Add the code to take screen shot in this method. The code will look like –

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.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

public class ListenerClass implements ITestListener {
CaptureScreenShot c = new CaptureScreenShot();

@Override
public void onFinish(ITestContext arg0) { }

@Override
public void onStart(ITestContext arg0) { }

@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult arg0) { }

@Override
public void onTestSkipped(ITestResult arg0) { }

@Override
public void onTestStart(ITestResult arg0) { }

@Override
public void onTestSuccess(ITestResult arg0) { }

@Override
public void onTestFailure(ITestResult arg0) {

//in below code, "SampleTest.driver" is used to get same driver from sample test class.
TakesScreenshot ts = (TakesScreenshot)SampleTest.driver;

File srcFile = ts.getScreenshotAs(OutputType.FILE);

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

}
}
This is all done. Now whenever you run the test case & if it fails, the screenshot will be captured at given location.

Hope this helps !!!!

How to take screen shot of failed test case only?

Taking Screen shot of all the test cases may create a memory issue, because we will be running the automation suite multiple times. Moreover, we can see the status of test cases (pass / failed / skipped) in the testing report. 
So, what is better is, to take the screen shot of only failed test cases.
Why to take screenshot is required in automation? 
              1. Screenshot helps us to understand the flow of application whether application is behaving correctly or not.
                 2. It helps as while doing cross browser testing.
                3. Another use is, while doing headless testing, you will not see actual GUI screen, but it will run on backend (ex – by using HTMLUnitBrowser ), in that case, we can track failed tests.
Now, there are two ways how we can take screen shot of failed test case only.
             
             1.      By using ITestListener Interface
             2.      By using ITestResult interface in @AfterMethod
In the below links, both the ways of taking screen shot on test failure are covered.

Data Driven test suite using TestNG framework

What is Data Driven Testing? 
Consider an example of account open to the bank. Now there are various possible scenarios for account open itself. But notice that the flow remains same, you will pass through the same screens but only you will enter different sets of data. 
Now, writing a test case for each set of data for same type of functionality it not a good idea, so what we can do here is, we can write one generic test case and pass the all sets of data to this test case. Here the role of data driven testing comes in to picture.
Data driven testing is where the test input and the expected output results are stored in a separate data file (normally in a tabular format) so that a single driver script can execute all the test cases with multiple sets of data.
The driver script contains navigation through the program, reading of the data files and logging of the test status information.
Test data (data file) can be stored in one or more central data sources like excel file, xml file or can be text file.

Below snap explains this – 

Advantages:
• This framework reduces the number of overall test scripts needed to implement all the test cases.
• Less amount of code is required to generate all the test cases.
• Offers greater flexibility when it comes to maintenance and fixing of bugs.
• The test data can be created before test implementation is ready or even before the system to be tested is ready.
Let us see now. How data driven testing can be achieved using TestNG framework.
Below steps explains how to create data driven testing framework.
              
              1.      Create a script with a set of constant test data
              2.      Replace constant test data with some variables.
              3.      Create multiple sets of test data in data storage like excel or xml file.
              4.      Assign the values to variable.
Consider a very simple example of emi calculator. We will write one generic test case & will pass different sets of data to the test case.
My Input Excel file, containing test data, looks like –

Below piece of code explains how can we pass multiple sets of test data to a single test case.
We need to use @DataProvider annotation of testing. This will help to provide the data to test case.
Note that, @DataProvider should always return an array of object.
Give some meaningful name to @DataProvider annotation.
Use the same name in @Test annotation.
Note: we need to add Apache POI jar files in project build path
Step1: Write test case with variables in it.
Step2: Use apache POI to read excel file, and return an array of object (because @DataProvider annotation should always return an array of Object).
Step3: Give some meaningful name to @DataProvider annotation.  Ex.    @DataProvider(name = “data”)
Step4: Use the same name in @Test annotation.   Ex.       @Test(dataProvider= “data”)
Refer Below code –

package dataDrivenTestingExample;

import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.TimeUnit;

import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DataDrivenTest {


@Test(dataProvider = "data")
public void DataDrivenTest1(String LoanAmount, String InterestRate, String Tenure){

WebDriver driver = new FirefoxDriver();

driver.navigate().to("https://emicalculator.site/");

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().window().maximize();

driver.findElement(By.xpath("//*[@id='frm-emi']/p[1]/input")).sendKeys(LoanAmount);
driver.findElement(By.xpath("//*[@id='frm-emi']/p[2]/input")).sendKeys(InterestRate);
driver.findElement(By.xpath("//*[@id='frm-emi']/div/div/input")).sendKeys(Tenure);
driver.findElement(By.xpath("//*[@id='frm-emi']/p[3]/input")).click();

driver.close();

}


@DataProvider(name = "data")
public Object[][] testDataSupplier() throws Exception{
//file path where excel file placed, containing test data.
String filePath = "C:UsersPrakashworkspaceLearnTestNGTestDataSheet.xlsx";

//read excel file using file input stream, using Apache POI
FileInputStream fis = new FileInputStream(new File (filePath));
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet sheet = wb.getSheet("TestData");

//calculate total number of rows and columns so that we can iterate over it.
int totalNumberOfRows = sheet.getLastRowNum()+1;
int totalNumberOfCols = sheet.getRow(0).getLastCellNum();

//create an object array. which will store the test data from excel file
Object[][] testdata1 = new Object[totalNumberOfRows][totalNumberOfCols];


for (int i = 0; i <totalNumberOfRows; i++ ){
for (int j = 0; j < totalNumberOfCols; j++){

testdata1[i][j] = sheet.getRow(i).getCell(j).toString();
}
}
return testdata1;
}

}
Hope this helps !!!!

How to Execute TestNG.xml using batch file (.bat file)

TestNG tests can be directly run from batch file (.bat file). Let us see below how this can be done.
Create sample java project.
Write some testing test in the project.
Create testing.xml file.
Create batch file (.bat file)
Sample test: (we will run this test from batch file)

package runTestNGxmlFromCMD;

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

public class RunTestNGTest {

@Test
public void test() throws InterruptedException{

WebDriver driver = new FirefoxDriver();

driver.navigate().to("https://learnaboutsoftwaretesting.blogspot.in");

System.out.println("navigate to website");

Thread.sleep(3000); //sleep for 3 second so that you can observe that site is opened, before it closes quickly

driver.close();

}

}
Testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Default suite">
<test verbose="2" name="Default test">
<classes>
<class name="runTestNGxmlFromCMD.RunTestNGTest"/>
</classes>
</test> <!-- Default test -->
</suite> <!-- Default suite -->
Now, in this case, my project location is: C:UsersPrakashworkspaceRunTestNGXML
My project folder structure looks like –

Go to your project (or anywhere, where you want to keep your batch file)
Then create new file. Name the file with some name & with extension .bat
(if you are unable to create with .bat extension, use double quote, example – “testing.bat”  while saving file.
Add below piece of lines in to the .bat file just created.
cd C:UsersPrakashworkspaceRunTestNGXML
java -cp C:UsersPrakashworkspaceRunTestNGXMLlib*;C:UsersPrakashworkspaceRunTestNGXMLbin org.testng.TestNG testng.xml
and it is done. Double click on your .bat file, your test running should start.

Hope this helps !!!!

 

How to Execute TestNG.xml from command prompt?

There are various ways we can execute testing.xml file. We can run this from Eclipse itself. We can run it from command prompt, we can run it by creating .bat (batch) file, we can run it from any continuous integration tool.
Let us see here how can we run this command prompt.
Create sample java project.
 
Write some testing test in the project.
Create testing.xml file.
Sample test: (we will run this test from command prompt)

package runTestNGxmlFromCMD;

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

public class RunTestNGTest {

@Test
public void test() throws InterruptedException{

WebDriver driver = new FirefoxDriver();

driver.navigate().to("https://learnaboutsoftwaretesting.blogspot.in");

System.out.println("navigate to website");

Thread.sleep(3000); //sleep for 3 second so that you can observe that site is opened, before it closes quickly

driver.close();

}

}

Testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Default suite">
<test verbose="2" name="Default test">
<classes>
<class name="runTestNGxmlFromCMD.RunTestNGTest"/>
</classes>
</test> <!-- Default test -->
</suite> <!-- Default suite -->
Now, my project structure looks like – 

Here is below commands to execute ‘testng.xml’ file from command line
Now,   my project location is:    C:UsersPrakashworkspaceRunTestNGXML
           Location of my jar files:  C:UsersPrakashworkspaceRunTestNGXMLlib*
      By default, class files will be created in project location (here – C:UsersPrakashworkspaceRunTestNGXMLbin)
So, based on above information, we need to run below piece of code in you command prompt.
cd C:UsersPrakashworkspaceRunTestNGXML

java -cp C:UsersPrakashworkspaceRunTestNGXMLlib*;C:UsersPrakashworkspaceRunTestNGXMLbin org.testng.TestNG testng.xml

Hope this helps !!!

Cross browser testing using TestNG framework?

Let us understand first what is cross browser testing.
 
Whenever the application is developed, it is intended to use on most of the web browser. So, while testing we need to make sure that the application works all and all for major browsers like IE, firefox, Chrome, Safari etc. To test the application over multiple browsers is known as cross browser testing.
In an automation framework, there are two ways to pass browser name which will decide on which browser our test should run.
            1.      To pass the browser name / value from external file like properties file or excel file
            2.      To pass the browser name / value from testing.xml file.
Let us understand how can we pass the browser value from testing.xml here.
Below piece of code accepts the parameter form testing.xml
In Testng.xml, browser values are given.

package crossBrowserTests;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;

public class CrossBrowserTestFromTestNG {

WebDriver driver;

@Parameters("browser")
@BeforeMethod
public void lanuchBrowser(String browser){

if (browser.equalsIgnoreCase("firefox")){

driver = new FirefoxDriver();
System.out.println("Browser selected for testing is : Firefox");

}
else if (browser.equalsIgnoreCase("chrome")){
System.setProperty("webdriver.chrome.driver", "C:chromedriver.exe");

driver = new ChromeDriver();
System.out.println("Browser selected for testing is : Google Chrome");

}
else if (browser.equalsIgnoreCase("ie")){
System.setProperty("webdriver.ie.driver", "C:IEDriverServer.exe");
driver = new InternetExplorerDriver();
System.out.println("Browser selected for testing is : IE");
}
}

@org.testng.annotations.Test
public void Test(){

driver.navigate().to("https://learnaboutsoftwaretesting.blogspot.in");
System.out.println("Title of the webpage is: "+driver.getTitle());
}

@AfterMethod
public void closeBrowser(){
driver.close();
}


}

Sample Testng.xml (where browser value is supplied)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Default suite">
<test verbose="2" name="FireFox Test">
<parameter name="browser" value="firefox"></parameter>
<classes>
<class name="crossBrowserTests.CrossBrowserTestFromTestNG"/>
</classes>
</test> <!-- Default test -->
<test verbose="2" name="Chrome Test">
<parameter name="browser" value="chrome"></parameter>
<classes>
<class name="crossBrowserTests.CrossBrowserTestFromTestNG"/>
</classes>
</test> <!-- Default test -->
<test verbose="2" name="Internet Explorer Test">
<parameter name="browser" value="ie"></parameter>
<classes>
<class name="crossBrowserTests.CrossBrowserTestFromTestNG"/>
</classes>
</test> <!-- Default test -->
</suite> <!-- Default suite -->
When you run testing.xml, it will run 3 tests. A similar test in 3 different browsers (firefox, ie, chrome).
Hope this helps !!!