How override ITestRunnerFactory in testng 7.9.0

104 views
Skip to first unread message

Rajeswari Subramanian

unread,
Jan 10, 2024, 3:50:29 AMJan 10
to testng-users
Hi,


we override ITestRunnerFactory (for maven surefire plugin to rerun the failed cases) and created custom TestRunner and override the run() method in TestRunner while using 7.4.0 version. while upgrading to 7.9.0, it is asking new parameter called suiteRunner. we don't know how to pass that information. I posted the code here. could you please help us to correct the code.

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-surefire-plugin</artifactId>

<version>3.0.0-M5</version>

<configuration>

<testFailureIgnore>true</testFailureIgnore>

<suiteXmlFiles>

<suiteXmlFile>./src/test/resources/${test.suite}.xml</suiteXmlFile>

</suiteXmlFiles>

<forkMode>never</forkMode>

<properties>

<property>

<name>testrunfactory</name>

<value>com.xxx.cx.qe.core.extensions.testng.TestNGRunnerFactory</value>

</property>

</properties>

</configuration>

</plugin>


******************************************

public class TestNGRunnerFactory implements ITestRunnerFactory {

@Override

public TestRunner newTestRunner(ISuite iSuite, XmlTest xmlTest, Collection<IInvokedMethodListener> collection, List<IClassListener> list) {

IConfiguration configuration = new Configuration();

configuration.setObjectFactory(new DefaultTestObjectFactory());

SuiteRunner suiteRunner = (SuiteRunner) iSuite;

suiteRunner.setObjectFactory(configuration.getObjectFactory());

return new TestNGRunner(configuration,iSuite, xmlTest, xmlTest.skipFailedInvocationCounts(), collection, list,(ISuiteRunnerListener) iSuite);

}

}


**************************************************************

public class TestNGRunner extends TestRunner {


public TestNGRunner(IConfiguration configuration, ISuite suite, XmlTest test, boolean skipFailedInvocationCounts

, Collection<IInvokedMethodListener> invokedMethodListeners, List<IClassListener> classListeners,ISuiteRunnerListener suiteRunner) {

super(configuration, suite, test, skipFailedInvocationCounts, invokedMethodListeners, classListeners, suiteRunner);

}


@Override

public void run() {

RetryManager.getInstance().setCurrentReTry(0); // Need this to support multi suite TestNG XMLs.

super.run();

int retryCount = 3;

LoggerUtil.logINFO("Retry count set in system property 'failure.retry.count' : " + retryCount);

for (int i = 0; i < retryCount; i++) {


IResultMap failedTests = super.getFailedTests();

IResultMap skippedTests = super.getSkippedTests();


Collection<ITestNGMethod> failedMethods = failedTests.getAllMethods();

Collection<ITestNGMethod> skippedMethods = skippedTests.getAllMethods();


if (!failedMethods.isEmpty() || !skippedMethods.isEmpty()) {

// Set the current retry count to the retryManager instance

RetryManager.getInstance().setCurrentReTry(i + 1);

// Iterate each failed test and execute again.

FailedTestInterceptor failedTestInterceptor = new FailedTestInterceptor(failedMethods, skippedMethods);

super.addListener(failedTestInterceptor);

super.run();

}

else {

break;

}

}

}

}

************************************************************

public class RetryManager {

private static RetryManager retryManager;

private int retry = 0;

private RetryManager() {


}


// Return the retry manager instance

public static RetryManager getInstance() {

if (retryManager == null) {

retryManager = new RetryManager();

}

return retryManager;

}


public int getCurrentReTry() {

return this.retry;

}


public void setCurrentReTry(int currentCycle) {

this.retry = currentCycle;

}


/**

* This method is to check if there are remaining re-try attempts.

* Note that this method does not account the statuses of test results

* (ie: It simply says whether there are remaining retries if there are any failures at the end of current run)

*

* @return true if {@link RetryManager#getCurrentReTry()} is less than {@link CoreConstants#RETRY_COUNT}

*/

public boolean hasNext() {

return this.retry < 3

}

}

*********

public class TestNGRetryAnalyzer implements IRetryAnalyzer {


private int count = 0;


public boolean retry(ITestResult result) {

int retryLimit = 3;

if (count < retryLimit) {

LoggerUtil.logINFO("Retrying test case: " + result.getMethod() + " [" + (count + 1)

+ " out of " + retryLimit + "]");

count++;

return true;

}

return false;

}

}

*****************

public class FailedTestInterceptor implements IMethodInterceptor {


private Collection<ITestNGMethod> failedTests;

private Collection<ITestNGMethod> skippedTests;


public FailedTestInterceptor(Collection<ITestNGMethod> failedTests, Collection<ITestNGMethod> skippedTests) {

this.failedTests = failedTests;

this.skippedTests = skippedTests;

}


@Override

public List<IMethodInstance> intercept(List<IMethodInstance> list, ITestContext iTestContext) {

List<IMethodInstance> result = new ArrayList<>();

filterMethods(failedTests, list, result);

filterMethods(skippedTests, list, result);

return result;

}


private void filterMethods(Collection<ITestNGMethod> methodCollection, List<IMethodInstance> list, List<IMethodInstance> result) {

for (ITestNGMethod testNGMethod : methodCollection) {

for (IMethodInstance method : list) {

if (method.getMethod().getMethodName().equals(testNGMethod.getMethodName())

&& method.getMethod().getRealClass().getCanonicalName().equals(testNGMethod.getRealClass().getCanonicalName())) {

result.add(method);

break;

}

}

}

}

}


********************

⇜Krishnan Mahadevan⇝

unread,
Jan 10, 2024, 4:53:23 AMJan 10
to testng...@googlegroups.com
Rajeshwari

To be honest, that's the first time I have seen someone customising TestNG to that level :)
So kudos to you folks on that.

The below should do the trick for you folks

public class TestNGRunnerFactory implements ITestRunnerFactory { @Override public TestRunner newTestRunner( ISuite iSuite, XmlTest xmlTest, Collection<IInvokedMethodListener> collection, List<IClassListener> list) { IConfiguration configuration = new Configuration(); configuration.setObjectFactory(iSuite.getObjectFactory()); SuiteRunner suiteRunner = (SuiteRunner) iSuite; suiteRunner.setObjectFactory(configuration.getObjectFactory()); return new TestNGRunner(configuration, iSuite, xmlTest, xmlTest.skipFailedInvocationCounts(), collection, list, suiteRunner); } }

Hope that helps.

Thanks & Regards
Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"
My Scribblings @ http://wakened-cognition.blogspot.com/
My Technical Scribblings @ https://rationaleemotions.com/


--
You received this message because you are subscribed to the Google Groups "testng-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to testng-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/testng-users/34d2f7b7-63c8-44b5-a426-261e7145a024n%40googlegroups.com.

Rajeswari Subramanian

unread,
Jan 23, 2024, 6:44:21 AMJan 23
to testng-users

Thanks for update Krishan..:)
however i am getting below error after the change, in my aftersuite method after testng upgrade,

Native Injection is NOT supported for @AfterSuite annotated afterSuite

@AfterSuite(alwaysRun = true)

public void afterSuitee(ITestContext iTestContext) {

System.out.println("inside afterSuite);

}

⇜Krishnan Mahadevan⇝

unread,
Jan 23, 2024, 7:20:49 AMJan 23
to testng...@googlegroups.com
Please remove the method parameter ITestContext. It's not valid to inject a suite level configuration method with a parameter that represents a "<test>" tag (ITestContext represents a <test> tag).

If you want to access an ITestContext,  then you can do it via 

ITestResult itr = Reporter.getCurrentTestResult();
ITestContext ctx = itr.getTestContext();


Thanks & Regards
Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"
My Scribblings @ http://wakened-cognition.blogspot.com/
My Technical Scribblings @ https://rationaleemotions.com/

Rajeswari Subramanian

unread,
Jan 23, 2024, 10:00:14 AMJan 23
to testng-users

Hi Krishnan,
In the documentation, it is mentioned that (in table matrix)  ITestContext is allowed for AfterSuite Annotation.. 

⇜Krishnan Mahadevan⇝

unread,
Jan 23, 2024, 10:10:04 AMJan 23
to testng...@googlegroups.com
That's a bug in the documentation. Thanks for pointing that out. Will get it sorted out.

Thanks & Regards
Krishnan Mahadevan

"All the desirable things in life are either illegal, expensive, fattening or in love with someone else!"
My Scribblings @ http://wakened-cognition.blogspot.com/
My Technical Scribblings @ https://rationaleemotions.com/

Reply all
Reply to author
Forward
0 new messages