Reputation: 156
I have a following testNg xml file.
Can someone please advice how to create this dynamically using java.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="Test">
<groups>
<run>
<include name="PrometheusHome" />
<include name="AlertMgrHome" />
</run>
</groups>
<classes>
<class name="com.amex.eag.telemetry.testcases.PrometheusTests"/>
<class name="com.amex.eag.telemetry.testcases.AlertManagerTests"/>
</classes>
</test>
</suite>
Upvotes: 3
Views: 4794
Reputation: 56
Taking reference from here
Let's suppose that we want to run the below XML file
<suite name="codekru">
<test name="codekru">
<classes>
<class name="Test.CodekruTest" />
</classes>
</test>
Now TestNG provides equivalent of the tags
<suite>
tag is equivalent with XmlSuite class of TestNG.<test>
tag is equivalent with XmlTest class of TestNG.<class>
tag is equivalent with XmlClass class of TestNG.So, keeping that in mind, we can make the above Xml file using the below code
public class GenerateXmlAndExecuteItAtRuntime {
public static void main(String[] args) {
XmlSuite suite = new XmlSuite();
suite.setName("codekru"); // this means <suite name = "codekru">
XmlTest test = new XmlTest(suite);
test.setName("codekru"); // this means <test name = "codekru">
List<XmlClass> classes = new ArrayList<XmlClass>(); // <classes>
classes.add(new XmlClass("Test.CodekruTest")); // this means <class name = "Test.CodekruTest">
test.setXmlClasses(classes);
List<XmlSuite> suites = new ArrayList<XmlSuite>();
suites.add(suite);
TestNG testng = new TestNG();
testng.setXmlSuites(suites);
testng.run();
}
}
More information can be found on these links below
Upvotes: 0
Reputation: 459
TestNG Official Documentation on Programattic Execution If you are looking to run your tests programmatically, it's best to read an existing testng XML file, do some runtime modifications and run it programmatically. This would basically avoid the problem of hardcoding class names and test names in the code. If you are hardcoding test names and class names, then you would need to change the test names and class names every time you need to run a different case. So please avoid hardcoding. Please follow the below approach, it would suit your need.
List<String> deviceNames = StringUtils.isEmpty(System.getProperty("deviceNames")) ?
new ArrayList<>() : Arrays.asList(System.getProperty("deviceNames").split(","));
TestNG tng = new TestNG();
File initialFile = new File("testng.xml");
InputStream inputStream = FileUtils.openInputStream(initialFile);
Parser p = new Parser(inputStream);
List<XmlSuite> suites = p.parseToList();
List<XmlSuite> modifiedSuites = new ArrayList<>();
for (XmlSuite suite : suites) {
XmlSuite modifiedSuite = new XmlSuite();
modifiedSuite.setParallel(suite.getParallel());
modifiedSuite.setThreadCount(deviceNames.size());
modifiedSuite.setName(suite.getName());
modifiedSuite.setListeners(suite.getListeners());
List<XmlTest> tests = suite.getTests();
for (XmlTest test : tests) {
for (int i = 0; i < deviceNames.size(); i++) {
XmlTest modifedtest = new XmlTest(modifiedSuite);
HashMap<String, String> parametersMap = new HashMap<>();
parametersMap.put("deviceName", deviceNames.get(i));
modifedtest.setParameters(parametersMap);
modifedtest.setName(test.getName() + "Device - " + deviceNames.get(i) +
", OS Version - " + platformVersions.get(i));
modifedtest.setXmlClasses(test.getXmlClasses());
}
}
modifiedSuites.add(modifiedSuite);
}
inputStream.close();
tng.setXmlSuites(modifiedSuites);
tng.run();
I am adding runtime parameters to each and every test based on the parameters passed in the maven runtime arguments. You could use the same approach for passing test names or class names as runtime arguments and update your testng XML file as per your need.
Upvotes: 1
Reputation: 156
Adjusted core from here:
public class DynamicTestNG {
public void runTestNGTest(Map<String,String> testngParams)
{ //Create an instance on TestNG
TestNG myTestNG = new TestNG();
//Create an instance of XML Suite and assign a name for it.
XmlSuite mySuite = new XmlSuite();
mySuite.setName("Suite");
mySuite.setParallel(XmlSuite.ParallelMode.METHODS);
//Create an instance of XmlTest and assign a name for it.
XmlTest myTest = new XmlTest(mySuite);
myTest.setName("Test");
//add groups
myTest.addIncludedGroup("PrometheusHome")
myTest.addIncludedGroup("AlertMgrHome")
//Add any parameters that you want to set to the Test.
myTest.setParameters(testngParams);
//Create a list which can contain the classes that you want to run.
List<XmlClass> myClasses = new ArrayList<XmlClass>();
myClasses.add(new XmlClass("com.amex.eag.telemetry.testcases.PrometheusTests"));
myClasses.add(new XmlClass("com.amex.eag.telemetry.testcases.AlertManagerTests"));
//Assign that to the XmlTest Object created earlier.
myTest.setXmlClasses(myClasses);
//Create a list of XmlTests and add the Xmltest you created earlier to it.
List<XmlTest> myTests = new ArrayList<XmlTest>();
myTests.add(myTest);
//add the list of tests to your Suite.
mySuite.setTests(myTests);
//Add the suite to the list of suites.
List<XmlSuite> mySuites = new ArrayList<XmlSuite>();
mySuites.add(mySuite);
//Set the list of Suites to the testNG object you created earlier.
myTestNG.setXmlSuites(mySuites);
mySuite.setFileName("myTemp.xml");
mySuite.setThreadCount(3);
myTestNG.run();
//Create physical XML file based on the virtual XML content
for(XmlSuite suite : mySuites)
{
createXmlFile(suite);
}
System.out.println("File generated successfully.");
//Print the parameter values
Map<String,String> params = myTest.getParameters();
for(Map.Entry<String, String> entry : params.entrySet())
{
System.out.println(entry.getKey() + " => " + entry.getValue());
}
}
//This method will create an Xml file based on the XmlSuite data
public void createXmlFile(XmlSuite mSuite)
{
FileWriter writer;
try {
writer = new FileWriter(new File("myTemp.xml"));
writer.write(mSuite.toXml());
writer.flush();
writer.close();
System.out.println(new File("myTemp.xml").getAbsolutePath());
} catch (IOException e)
{
e.printStackTrace();
}
}
//Main Method
public static void main (String args[])
{
DynamicTestNG dt = new DynamicTestNG();
//This Map can hold your testng Parameters.
Map<String,String> testngParams = new HashMap<String,String> ();
testngParams.put("device1", "Desktop");
dt.runTestNGTest(testngParams);
}
}
Upvotes: 3