Skip to content

Commit

Permalink
Support ITestNGFactory customisation
Browse files Browse the repository at this point in the history
  • Loading branch information
krmahadevan committed Feb 8, 2024
1 parent 4af6e94 commit 38b4fd4
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Current
7.10.0
Fixed: GITHUB-3059: Support the ability to inject custom listener factory (Krishnan Mahadevan)
Fixed: GITHUB-3038: java.lang.IllegalStateException: Results per method should NOT have been empty (Krishnan Mahadevan)
Fixed: GITHUB-3022: Remove deprecated JUnit related support in TestNG (Krishnan Mahadevan)

Expand Down
5 changes: 5 additions & 0 deletions testng-core/src/main/java/org/testng/CommandLineArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ public class CommandLineArgs {
description = "The factory used to create tests")
public String testRunnerFactory;

public static final String LISTENER_FACTORY = "-listenerfactory";

@Parameter(names = LISTENER_FACTORY, description = "The factory used to create TestNG listeners")
public String listenerFactory;

public static final String METHODS = "-methods";

@Parameter(names = METHODS, description = "Comma separated of test methods")
Expand Down
18 changes: 17 additions & 1 deletion testng-core/src/main/java/org/testng/TestNG.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.testng.collections.Sets;
import org.testng.internal.ClassHelper;
import org.testng.internal.Configuration;
import org.testng.internal.DefaultListenerFactory;
import org.testng.internal.DynamicGraph;
import org.testng.internal.ExitCode;
import org.testng.internal.IConfiguration;
Expand Down Expand Up @@ -682,8 +683,12 @@ public void setObjectFactory(ITestObjectFactory factory) {
* IReporter
*/
public void setListenerClasses(List<Class<? extends ITestNGListener>> classes) {
ITestNGListenerFactory factory = m_configuration.getListenerFactory();
if (factory == null) {
factory = new DefaultListenerFactory(m_objectFactory, null);
}
for (Class<? extends ITestNGListener> cls : classes) {
addListener(m_objectFactory.newInstance(cls));
addListener(factory.createListener(cls));
}
}

Expand Down Expand Up @@ -835,6 +840,10 @@ public void setExecutorFactoryClass(String clazzName) {
this.m_executorFactory = createExecutorFactoryInstanceUsing(clazzName);
}

public void setListenerFactory(ITestNGListenerFactory factory) {
this.m_configuration.setListenerFactory(factory);
}

public void setGenerateResultsPerSuite(boolean generateResultsPerSuite) {
this.m_generateResultsPerSuite = generateResultsPerSuite;
}
Expand Down Expand Up @@ -1466,6 +1475,13 @@ protected void configure(CommandLineArgs cla) {
.ifPresent(value -> propagateDataProviderFailureAsTestFailure());
setReportAllDataDrivenTestsAsSkipped(cla.includeAllDataDrivenTestsWhenSkipping);

Optional.ofNullable(cla.listenerFactory)
.map(ClassHelper::forName)
.filter(ITestNGListenerFactory.class::isAssignableFrom)
.map(it -> m_objectFactory.newInstance(it))
.map(it -> (ITestNGListenerFactory) it)
.ifPresent(this::setListenerFactory);

Optional.ofNullable(cla.generateResultsPerSuite).ifPresent(this::setGenerateResultsPerSuite);

if (cla.verbose != null) {
Expand Down
5 changes: 3 additions & 2 deletions testng-core/src/main/java/org/testng/TestRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
Expand Down Expand Up @@ -377,8 +378,8 @@ private void initListeners() {
//

ITestNGListenerFactory factory =
TestListenerHelper.createListenerFactory(
m_objectFactory, m_testClassFinder, listenerFactoryClass, this);
Optional.ofNullable(m_configuration.getListenerFactory())
.orElse(new DefaultListenerFactory(m_objectFactory, this));

// Instantiate all the listeners
for (Class<? extends ITestNGListener> c : listenerClasses) {
Expand Down
13 changes: 13 additions & 0 deletions testng-core/src/main/java/org/testng/internal/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.testng.IExecutionListener;
import org.testng.IHookable;
import org.testng.IInjectorFactory;
import org.testng.ITestNGListenerFactory;
import org.testng.ITestObjectFactory;
import org.testng.collections.Lists;
import org.testng.collections.Maps;
Expand All @@ -24,6 +25,8 @@ public class Configuration implements IConfiguration {
private IHookable m_hookable;
private IConfigurable m_configurable;

private ITestNGListenerFactory m_listenerFactory;

private boolean shareThreadPoolForDataProviders = false;
private final Map<Class<? extends IExecutionListener>, IExecutionListener> m_executionListeners =
Maps.newLinkedHashMap();
Expand Down Expand Up @@ -63,6 +66,16 @@ public void setAnnotationFinder(IAnnotationFinder finder) {
m_annotationFinder = finder;
}

@Override
public void setListenerFactory(ITestNGListenerFactory testNGListenerFactory) {
this.m_listenerFactory = testNGListenerFactory;
}

@Override
public ITestNGListenerFactory getListenerFactory() {
return m_listenerFactory;
}

@Override
public ITestObjectFactory getObjectFactory() {
return m_objectFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ public interface IConfiguration {

void setAnnotationFinder(IAnnotationFinder finder);

void setListenerFactory(ITestNGListenerFactory testNGListenerFactory);

ITestNGListenerFactory getListenerFactory();

ITestObjectFactory getObjectFactory();

void setObjectFactory(ITestObjectFactory m_objectFactory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ public static ListenerHolder findAllListeners(Class<?> cls, IAnnotationFinder fi
return result;
}

/** @deprecated - This method stands deprecated as of TestNG version <code>7.10.0</code> */
@Deprecated
public static ITestNGListenerFactory createListenerFactory(
ITestObjectFactory objectFactory,
TestNGClassFinder finder,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.testng.internal.objects.pojo;

import java.util.Objects;
import org.testng.ITestContext;
import org.testng.internal.invokers.objects.GuiceContext;

Expand All @@ -13,7 +12,6 @@ public class CreationAttributes {
private final GuiceContext suiteContext;

public CreationAttributes(ITestContext ctx, BasicAttributes basic, DetailedAttributes detailed) {
Objects.requireNonNull(ctx);
this.basic = basic;
this.detailed = detailed;
this.context = ctx;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package test.listeners.factory;

import org.testng.IExecutionListener;

public class ExampleListener implements IExecutionListener {

public static ExampleListener instance;

public ExampleListener() {
setInstance(this);
}

private static synchronized void setInstance(ExampleListener instance) {
if (ExampleListener.instance == null) {
ExampleListener.instance = instance;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package test.listeners.factory;

import org.testng.annotations.Test;

public class SampleTestCase {
@Test
public void testMethod() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package test.listeners.factory;

import org.testng.ITestNGListener;
import org.testng.ITestNGListenerFactory;
import org.testng.internal.objects.InstanceCreator;

public class SampleTestFactory implements ITestNGListenerFactory {

public static ITestNGListenerFactory instance;

private boolean invoked = false;

public boolean isInvoked() {
return invoked;
}

public SampleTestFactory() {
setInstance(this);
}

private static void setInstance(ITestNGListenerFactory instance) {
SampleTestFactory.instance = instance;
}

@Override
public ITestNGListener createListener(Class<? extends ITestNGListener> listenerClass) {
invoked = true;
return InstanceCreator.newInstance(listenerClass);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package test.listeners.factory;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

import java.util.List;
import org.testng.CommandLineArgs;
import org.testng.TestNG;
import org.testng.annotations.Test;
import test.SimpleBaseTest;

public class TestNGFactoryTest extends SimpleBaseTest {

@Test(description = "GITHUB-3059")
public void testListenerFactoryViaConfigurationArg() {
String[] args =
new String[] {
CommandLineArgs.LISTENER_FACTORY,
SampleTestFactory.class.getName(),
CommandLineArgs.TEST_CLASS,
SampleTestCase.class.getName(),
CommandLineArgs.LISTENER,
ExampleListener.class.getName()
};
TestNG testng = TestNG.privateMain(args, null);
assertThat(SampleTestFactory.instance).isNotNull();
assertThat(ExampleListener.instance).isNotNull();
assertThat(testng.getStatus()).isZero();
}

@Test(description = "GITHUB-3059")
public void testListenerFactoryViaTestNGApi() {
TestNG testng = new TestNG();
SampleTestFactory factory = new SampleTestFactory();
testng.setListenerFactory(factory);
testng.setListenerClasses(List.of(ExampleListener.class));
testng.setTestClasses(new Class[] {SampleTestCase.class});
testng.run();
assertThat(testng.getStatus()).isZero();
assertThat(factory.isInvoked()).isTrue();
}
}
1 change: 1 addition & 0 deletions testng-core/src/test/resources/testng.xml
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@
<class name="test.skip.github1632.IssueTest"/>
<class name="test.listeners.issue2220.IssueTest"/>
<class name="test.listeners.issue2328.IssueTest"/>
<class name="test.listeners.factory.TestNGFactoryTest"/>
<class name="test_result.ResultStatusTest"/>
<class name="test_result.TestResultTest"/>
<class name="test.listeners.github1319.TestResultInstanceCheckTest"/>
Expand Down

0 comments on commit 38b4fd4

Please sign in to comment.