IMethodInterceptor examples to reorder list of test methods

IMethodInterceptor is used to alter/modify the list of test methods to be executed by TestNG.

When we implement IMethodInterceptor interface which has just one method to implement 'intercept(java.util.List methods, ITestContext context)', using this method we can reorder the list of test methods and return List of IMethodInstance which TestNG runs. TestNG will now run these test methods in the same order which is found in the returned list.

public interface IMethodInterceptor {
  List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context);
}

TestNG runs these test methods in the same order found in the returned value. We can filter these test methods by implementing IMethodInterceptor and return a list of test methods based on the logic that we add that can be based on priority / groups etc.

public class TestSortInterceptor implements IMethodInterceptor {
public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
    List<IMethodInstance> result = new ArrayList<IMethodInstance>();
    for (IMethodInstance method : methods) {
          if(<logic to order tests goes here>)  {
             result.add(method);
          }
    }
 return result;
}

Let us see an example to run ONLY a specific Priority Tests example - Run Tests with 'Priority=1'. As we all know, we will add priorities for test methods and lower priorities will be scheduled first. Check 'TestNG Priorities'.

Example 1:- Execute TestNG tests using specific priority

Step 1: Create a class 'PriorityInterceptor.java' and implement with IMethodInterceptor as below :-

We have added a condition to execute only test with specified Priority as "testMethod.priority() == 1", If we want to execute Tests with 'Priority=2' just replace value with 2.

package com.easy;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.testng.IMethodInstance;
import org.testng.IMethodInterceptor;
import org.testng.ITestContext;
import org.testng.annotations.Test;

public class PriorityInterceptor implements IMethodInterceptor {

	@Override
	public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
		List<IMethodInstance> result = new ArrayList<IMethodInstance>();
		for (IMethodInstance method : methods) {
			Test testMethod = method.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class);
			if (testMethod.priority() == 1) {
				result.add(method);
			}
		}
		return result;
	}
}

Step 2:- Create a class TestA.java and add below sample code which has only one test 'testcase3()' with 'Priority=1' :-

package com.easy;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

public class TestA {
	
	@BeforeClass
	public void setUp() {
		System.out.println("Before class A");
	}

	@Test(priority=3, groups={"smoke"})
	public void testcase1() {
		System.out.println("A test one - priority 3");
	}
	
	@Test(priority=2, groups={"regression"})
	public void testcase2() {
		System.out.println("A - test two - priority 2");
	}

	@Test(priority=1, groups="smoke")
	public void testcase3() {
		System.out.println("A test three - priority 1");
	}

	@Test(priority=2, groups="UI")
	public void testcase4() {
		System.out.println("A test four - priority 2");
	}
}

Step 3:- Create a class TestB.java and add below sample code which has only one test 'testcase3()' with 'Priority=1' :-

package com.easy;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

public class TestB{
	
	@BeforeClass
	public void setUp() {
		System.out.println("Before class B");
	}

	@Test(priority=3, groups="smoke")
	public void testcase1() {
		System.out.println("B test one - priority 3");
	}
	
	@Test(priority=2, groups="UI")
	public void testcase2() {
		System.out.println("B test two - priority 2");
	}

	@Test(priority=1, groups={"smoke", "regression"})
	public void testcase3() {
		System.out.println("B test three - priority 1");
	}
}

Step 4 :- Add the Listener to testng.xml file

	<listeners>
		<listener class-name="com.easy.PriorityInterceptor" />
	</listeners>
M/code>

<b>Step 5</b>: - Create testng.xml file as below : -

<code>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Suite1" verbose="1">
	<listeners>
		<listener class-name="com.easy.PriorityInterceptor" />
	</listeners>
	<test name="Regression Test Suite">
		<classes>
			<class name="com.easy.TestA" />
			<class name="com.easy.TestB" />
		</classes>
	</test>
</suite>

All together, the project structure will look like below image :-

TestNG IMethodInterceptor Example

Done. Now when we run testng.xml, it should give you the output as below, One test method from each Class A and Class B are executed based on the specified priority :-

[TestNG] Running:
  F:\Selenium\Easy\TestNGMethodInterceptor\testng.xml

Before class A
A test three - priority 1
Before class B
B test three - priority 1

===============================================
Suite1
Total tests run: 2, Failures: 0, Skips: 0
===============================================

Example 2: - Execute TestNG tests using priority and group

Now lets us say, we have many test cases for example say there are 500 test cases with 'priority=1'. But to execute all 500 test cases may not be required sometimes.

We generally defines testng 'groups' for test methods like regression, smoke, UI or etc. Using 'IMethodInterceptor' we can also execute only specific group/groups tests using the same priority condition.

Lets take an example to Execute only Tests with 'priority=1' And which has Group 'Regression'.

package com.easy;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.testng.IMethodInstance;
import org.testng.IMethodInterceptor;
import org.testng.ITestContext;
import org.testng.annotations.Test;

public class PriorityInterceptor implements IMethodInterceptor {

	@Override
	public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
		List<IMethodInstance> result = new ArrayList<IMethodInstance>();
		for (IMethodInstance method : methods) {
			Test testMethod = method.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class);
			Set<String> groups = new HashSet<String>();
			 for (String group : testMethod.groups()) {
			      groups.add(group);
			    }
			if (testMethod.priority() == 1 && groups.contains("regression")) {
				result.add(method);
			}
		}
		return result;
	}
}

The above will execute only tests which has 'priority=1' and group value as 'regression'.

In this way we can modify the list of test methods that we want TestNG to run using IMethodInterceptor interface. You can play around with other options using 'IMethodInterceptor' which has control of all the @Test methods.

Test Frameworks: 

Add new comment