Setup Selenium Grid to run test parallelly across platforms

In this tutorial, we will talk about how can we setup selenium Grid to execute tests parallel.
Prior to this, to understand the basic concept of Selenium Grid, refer below article – 
Introduction to Selenium Grid – What is Selenium Grid?  <Link>
Selenium Grid will actual help you to run the tests on multiple nodes which will reduce the total execution time. Let us see how selenium Grid work – 
How Selenium Grid works? 
 Observe the above image, it shows how Selenium Grid works. It has Hub and Multiple nodes. Entire script is done at Hub node whereas entire execution will be done at Nodes. So, on various nodes we can have various OS along with various browsers. 

(Note: Note that, ideally node machines are different from Hub machine)

Let us talk more about Hub and Node –  
As the image shows, Hub is the machine where we write all our scripts. So, it a central point where we load out tests. In entire Grid system, we will have one Hub and multiple nodes. As it is Hub, it is launched on single machine. All the execution will be happening on Node machines, so there can be one or multiple nodes having different platforms with same or different browser. 
So, the concept is like, Hub has got one PC (Parent PC) whereas Nodes has got multiple machines (Child PC). Hub will be giving instructions to Nodes, accordingly nodes will execute the test cases. Hub is only to give instructions.
Before we setup Hub and Nodes, we need to get selenium Standalone server from http://docs.seleniumhq.org/download/   
To download Selenium Grid, click here
Let us see now how-to setup the Hub – 
Now, Selenium Standalone Server is a jar file, so we need to do the setup from command prompt.
Open Command Prompt.
Use below command to start Hub.
java -jar C:selenium-server-standalone-3.4.0.jar -role hub

Once above command has run, hub setup will complete. You will see the message saying Hub is running. Also, it gives the Hub address which we need while registering nodes.
Note that, Hub will start at port 4444 by default.
Now, let us see how to setup Nodes – 
Note: Ideally, nodes should be setup on different machines than Hub machine, but for demo purpose, I am using the same machine. The process for using different machines for Nodes is exactly same. Just we need to do the node setup on each of the node machine individually by giving Hub address (shown in above image).

To setup Node, we need same jar again. We just need to setup the role as node and give hub address while registering the Node. Let us see how this can be done.
Open another command Prompt. Do not close the command prompt where Hub is running.
Use below command to setup Node – 
java -jar C:selenium-server-standalone-3.4.0.jar -role node -hub http://192.168.1.106:4444/grid/register/
where, Selenium server standalone jar is placed in C drive. Hub machine address Is used to register node.

 
Observe above screenshot, it shows Node is running.
Now, we are done with hub and node setup. In the similar way, we can do the node setup on multiple nodes (machines) as required.
That’s it, Node setup is done on the machine for 3 browsers by default ( Firefox, IE and Chrome). To verify this, go to the link – http://localhost:4444/grid/console

Now, suppose, you want to setup only 1 browser, then use below command line –
java -jar C:selenium-server-standalone-3.4.0.jar -role webdriver -hub http://localhost:4444/grid/register -port 5556 -browser browserName=iexplore
Above command will set Internet Explorer.
If you want to setup only Chrome browser or Firefox browser, then use browserName=firefox and browserName=chrome
If you want to setup only 1 instance of all 3 browsers (Chrome, IE and firefox), then use – 
java -jar C:selenium-server-standalone-3.4.0.jar -role webdriver -hub http://localhost:4444/grid/register -port 5556 -browser browserName=iexplore -browser browserName=firefox -browser browserName=chrome

Once Hub and Node setup is done (Grid setup is done), Create one sample test case to run on the Grid.
Refer below example – 

package basicsOfSelenium;

import java.net.MalformedURLException;
import java.net.URL;

import org.openqa.selenium.By;
import org.openqa.selenium.Platform;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.Test;

public class ArrayDemo {

@Test

public void mailTest() throws MalformedURLException{

DesiredCapabilities dr=null;

dr=DesiredCapabilities.firefox();

dr.setBrowserName("firefox");

dr.setPlatform(Platform.WINDOWS);

RemoteWebDriver driver=new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), dr);

driver.navigate().to("https://www.google.co.in");

driver.findElement(By.xpath("//*[@id='gs_htif0']")) .sendKeys("Search me");

driver.findElement(By.xpath("//*[@id='tsf']/div[2]/div[3]/center/input[1]")) .click();

driver.close();

}
}
When you run above piece of code, your test should be executed on node machine, on firefox browser.
If you want to run the test on multiple platforms, parallelly, then what you can do is, set browserType parameter in testng.xml as below – 
                    <parametername =”browserType” value=”IE”/>
In similar way add above parameter for Chrome and firefox browser in testng.xml. Update the code to handle browser type in your program.
That’s it. 
This is how we can setup the Selenium Grid and run test cases in parallel on Selenium Grid.
Hope this helps.

 

Introduction to Selenium Grid – What is Selenium Grid?

Let us Try to understand about selenium grid from an example.
Example 1:
Consider a scenario where you want to execute 1000 test cases. You can do this by setting “thread-count” to suppose 5. So, here using threads your test cases will be executed. One thread will execute 200 test cases. So, time taken will be 1/5th of total time.
Now, let us say, you want to execute multiple test cases (or same test cases) on multiple operating systems and on multiple browsers.  Suppose 1000 test cases need to be executed on Windows OS, Linux OS (on Mozilla Firefox, chrome, safari, IE -> all 4 browsers). In this case, we can use Selenium Grid by setting various nodes on the hub machine.
Example 2:
There are so many web browsers which are in use today. Users may be using either Chrome or Firefox or Safari or Opera or even Internet Explorer for reading this very blog. They may be using different versions of the browsers. They may also be running these browsers on any OS, be it Windows or Mac or Ubuntu or any other distribution of Linux.
What if the users were seeing something important on the internet? Something important to your business. Wouldn’t you want to go that extra mile (testing the web app) just to ensure that your users and/ or customers get the best user experience? You would, right?
Well, you should!
But the question is, how feasible is it? Will you be able to spend time testing your web app on every possible OS and every available web browser? Hmm, that sounds like a bit of a challenge. This is where Selenium Grid fits the bill and helps save your time and energy.
Observe below diagram.
The above example shows, in Selenium Grid, we have a concept of Hub and Nodes. Hub is set on a machine from which you are trying to execute the test cases. On hub, we can set multiple nodes (suppose as like multiple Operating systems / multiple computes) and on these multiple nodes, various browsers can be set for test execution. All these things are virtually.
So, in short, Selenium-grid works on different machines against different browsers at the same time. Selenium grid support distributed test execution environment.
when to use selenium grid:
1.Run your tests against different browsers, operating systems, and machines all at the same time. This will ensure that the application you are testing is fully compatible with a wide range of browser- O.S combinations.
2.Save time in the execution of your test suites. If you set up Selenium Grid to run, say, 4 tests at a time, then you would be able to finish the whole suite around 4 times faster.
Grid concept is introduced to support parallel execution of test cases.
For Example, executing the same test case in different browsers in different operating systems.
Executing a set of test cases at an instance – This could be elaborated as below: if you are running a set of 30 test cases which consumes around 5 mins each, run time for the test suite will be 5*30(You have wait until first test cases execution is completed to start second test case execution) = 150 Mins. If the same is ran through GRID it triggers 30 instance of test cases at once, so 5*1 = 5 Mins (All the test cases will run at once as 30 different browser instances will be opened).
Advantages of using selenium Grid – 
         1.       It allows running test cases in parallel with different browsers.
         2.       It reduces script execution time.
         3.       It provides the flexibility to run your test automation scripts on different browsers and different OS at the same time.

How to read Excel 2007 (.xlsx) file using Apache POI?

Before you start with how to read excel 2007 file using apache poi article, suggested pre-requisites to read –

Introduction to Apache POI

How to set up Apache POI in java – selenium project.

How to read an excel 2003 (.xls) file using Apache POI

To start with the article, about how to read an excel file using Apache POI, Pre-rwquisite is, you have configured Apache POI in your project. If not, refer above link.
As we saw earlier, HSSF is the POI Project’s pure Java implementation of the Excel ’97(-2007) file format. Whereas XSSF is the POI Project’s pure Java implementation of the Excel 2007 OOXML (.xlsx) file format.
Let us understand about excel first.
First find out the excel file, known as Workbook here. Then within a workbook, we have multiple sheets. Go to the desired sheet using sheet name / sheet index. Then go to row & column position & get the cell data.
Below are the steps to Read excel sheet.
             1.        Create object of the File, provide file path where your excel sheet is placed. Make sure that Excel file is in 2003 format (.xls format).
             2.       Get the file in FileInputStream which we will use for reading excel sheet.
             3.       Now use XSSFWorkbook class to get the desired workbook from FileInputStream.
              XSSFWorkbook wb = new XSSFWorkbook(ExcelFileToRead);
            4.       Get the required sheet using class XSSFSheet (of the above workbook).
               XSSFSheet sheet=wb.getSheetAt(0);
           5.       Now get the data from sheet using object created by XSSFSheet. Look at the below example.
There are two ways
           1.       If the excel sheet has only String data (or one type of data)
           2.       If the excel sheet has combination of data like String /int/Boolean etc.
Consider the First point when Excel sheet has only one type of data. Below ScreenShot shows the input excel file.
Observe the below piece of code, which will be used to read excel file data (have only one type of data – String here)
package apachePOI;

import java.io.File;
import java.io.FileInputStream;

import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class Read2007FormatExcel {

 public static void main(String[] args) throws Exception {

  //location of your file - filepath
  String filepath = "C:UsersPrakashDesktopTestData.xlsx";
  
  //Create File object with above file path
  File srcFile = new File(filepath);
  
  //Create FileInputStream for above srcFile - to read file
  FileInputStream fis = new FileInputStream(srcFile);
  
  //Excel file is nothing but workbook, so create workbook object.
  XSSFWorkbook wb = new XSSFWorkbook(fis);
  
  //Go to the desired sheet, here index 0 means first tab
  XSSFSheet sheet = wb.getSheetAt(0);
  
  //get total number of rows & columns so that we can iterate over it.
  int TotalNumOfRows = sheet.getLastRowNum()+1;
  int TotalNumOfCols = sheet.getRow(0).getLastCellNum();
  
  //Iterate over the sheet, using total number of rows and columns
  for (int i = 0; i < TotalNumOfRows; i++ ){
   for (int j = 0; j < TotalNumOfCols; j++){
    
    //get the cell data using row number and column number of the cell.
    XSSFRichTextString cellData = sheet.getRow(i).getCell(j).getRichStringCellValue();   
    System.out.println(cellData);
   }
  }
  wb.close();
  fis.close();
  
 }

}

Now, in Another case, when Excel sheet contain all type of data, example – String / int / Boolean etc

Observe below piece of code – to read data from excel sheet containing all type of data (can be used even if excel sheet has one type of data)
package apachePOI;

import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class Read2007FormatExcelUsingIterator {

 @SuppressWarnings("deprecation")
 public static void main(String[] args) throws Exception {

  //location of your file - filepath
  String filepath = "C:UsersPrakashDesktopTestData.xlsx";
  
  //Create File object with above file path
  File srcFile = new File(filepath);
  
  //Create FileInputStream for above srcFile - to read file
  FileInputStream fis = new FileInputStream(srcFile);
  
  //Excel file is nothing but workbook, so create workbook object.
  XSSFWorkbook wb = new XSSFWorkbook(fis);
  
  //Go to the desired sheet, here index 0 means first tab
  XSSFSheet sheet = wb.getSheetAt(0);
  
  //get total number of rows & columns so that we can iterate over it.

  Iterator<Row> itr = sheet.rowIterator();
  while (itr.hasNext()){
   Row row = itr.next();
   
   Iterator<Cell> itrCell = row.cellIterator();
   
   while (itrCell.hasNext()){
    Cell cell =  itrCell.next();
    switch (cell.getCellType()){
    case Cell.CELL_TYPE_NUMERIC:
     System.out.println("cell type is Numeric: "+cell.getNumericCellValue());
     break;
    case Cell.CELL_TYPE_STRING:
     System.out.println("cell type is String: "+cell.getStringCellValue());
     break;
    
    }
   }
  }
  wb.close();
  fis.close();
  
 }

}

Hope This Helps !!!! do post your questions if any !!!

Suggested next article to read –     Writing Excel files using Apache POI

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