Mark,
What you ask is definitely possible in TestNG. You just need to connect a few things to get this requirement to work.
First things first. TestNG 6.x series is a very old version. Please upgrade to the latest released version (7.10.2 as of today). This will require you to be on JDK11.
Now to solve your specific use case of wanting to run tests that have only 2 or more specific groups, you can do that using a beanshell.
Steps to follow:
2. Define an implementation of IAlterSuiteListener
3. Within this listener, programmatically add a beanshell that ensures that “and” constraint for groups is adhered to.
Here’s a full fledged example.
I created a file called beanshell.txt under “src/test/resources” with its contents as below:
String jvmValue = System.getProperty("groups");
String[] allGroups = jvmValue.split(",");
for(String group: allGroups){
if (!groups.containsKey(group)) {
print("Exclude " + testngMethod.getQualifiedName() + " because it belongs to " + Arrays.toString(testngMethod.getGroups()));
return false;
}
}
return true;
My IAlterSuiteListener implementation, which reads the above mentioned text file, gets its contents and then wires it up as a beanshell expression.
import org.testng.*;
import org.testng.xml.XmlMethodSelector;
import org.testng.xml.XmlScript;
import org.testng.xml.XmlSuite;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
public class GroupsAddingListener implements IAlterSuiteListener {
@Override
public void alter(List<XmlSuite> suites) {
String groups = System.getProperty("groups", "");
if (!groups.isEmpty()) {
System.err.println("Running for the groups " + groups);
suites.stream()
.flatMap(it -> it.getTests().stream())
.forEach(it -> it.setMethodSelectors(List.of(xmlMethodSelector())));
}
}
private static XmlMethodSelector xmlMethodSelector() {
XmlMethodSelector selector = new XmlMethodSelector();
XmlScript script = new XmlScript();
script.setLanguage("beanshell");
String expression = beanshell();
script.setExpression(expression);
selector.setScript(script);
return selector;
}
private static String beanshell() {
try {
return Files.readString(Paths.get("src/test/resources/beanshell.txt"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
My test classes look like below:
import org.testng.ITestNGMethod;
import org.testng.Reporter;
import org.testng.annotations.Test;
public class ATestCase {
@Test(groups = {"p1", "p2"})
public void testMethod() {
ITestNGMethod method = Reporter.getCurrentTestResult().getMethod();
String name = method.getQualifiedName();
String groups = String.join(",", method.getGroups());
System.err.println("Executing " + name + " in " + groups);
}
}
import org.testng.ITestNGMethod;
import org.testng.Reporter;
import org.testng.annotations.Test;
public class BTestCase {
@Test(groups = {"p1", "p3"})
public void testMethod() {
ITestNGMethod method = Reporter.getCurrentTestResult().getMethod();
String name = method.getQualifiedName();
String groups = String.join(",", method.getGroups());
System.err.println("Executing " + name + " in " + groups);
}
}
My execution output looks like below (when I ran mvn clean test -Dgroups=p1,p3
[INFO] --- surefire:3.2.5:test (default-test) @ groups_demo ---
[INFO] Using auto detected provider org.apache.maven.surefire.testng.TestNGProvider
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running TestSuite
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Running for the groups p1,p3
Exclude com.rationaleemotions.groups.ATestCase.testMethod because it belongs to [p1, p2]
Exclude com.rationaleemotions.groups.ATestCase.testMethod because it belongs to [p1, p2]
Executing com.rationaleemotions.groups.BTestCase.testMethod in p1,p3
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.485 s -- in TestSuite
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.104 s
[INFO] Finished at: 2024-05-07T10:11:54+05:30
[INFO] ------------------------------------------------------------------------