Search code examples
javaseleniumautomated-teststestngtestng-eclipse

Dynamic TestNG XML Creation. Getting wrong XML. Where I am wrong


Dynamic TestNG XML Creation. Getting wrong XML. Where I am wrong.

I want my testNG xml to be print as shown below.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="App Automation Testing">
  <parameter name="BrowserName" value="chrome"/>
  <test name="MyTest1">
    <classes>
      <class name="etaf.tests.LaunchApp"/>
      <class name="etaf.tests.LoginTests"/>
    </classes>
  </test> <!-- MyTest1 -->
  <test name="MyTest2">
    <classes>
      <class name="etaf.tests.LaunchApp"/>
    </classes>
  </test> <!-- MyTest2 -->
</suite> <!-- App Automation Testing -->

But with the below Java Code; this code is having a array similar to what shown below

|testclass|testname|
|class1   |TC_LOGIN|
|class2   |TC_LOGIN|
|class1   |TC_WORK |
public void sample(String[][] dbArr, Map<String,String> parameters ) {

        //Create an instance on TestNG
        TestNG myTestNG = new TestNG();

        //Create an instance of XML Suite and assign a name for it.
        XmlSuite suite = new XmlSuite();
        suite.setName("App Automation Testing");
        suite.setParameters(parameters);

        String dummyName = "";
        List<XmlClass> classes1 = null;
        List<XmlTest> tests = new ArrayList<XmlTest>();
        XmlTest test1 = null;


        for(int i=0;i<dbArr.length;i++) {
            if(!dummyName.equalsIgnoreCase(dbArr[i][1])) {
                test1 = new XmlTest(suite);
                test1.setName(dbArr[i][1]);
                classes1 = new ArrayList<XmlClass> ();
                classes1.add(new XmlClass(dbArr[i][0]));
                dummyName = dbArr[i][1];

            } else if(dummyName.equalsIgnoreCase(dbArr[i][1])) {
                classes1.add(new XmlClass(dbArr[i][0]));
                dummyName = dbArr[i][1];
            }
            test1.setXmlClasses(classes1);
            tests.add(test1);
        }

        //add the list of tests to your Suite.
        suite.setTests(tests);

        //Add the suite to the list of suites.
        List<XmlSuite> suites = new ArrayList<XmlSuite>();
        suites.add(suite);

        System.out.println(suite.toXml());

        //Set the list of Suites to the testNG object you created earlier.
        myTestNG.setXmlSuites(suites);

        //invoke run() - this will run your class.
        myTestNG.run();
    }

it is printing like this. Where I am wrong.? Please help.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="App Automation Testing">
  <parameter name="BrowserName" value="chrome"/>
  <test name="TC_LOGIN">
    <classes>
      <class name="etaf.tests.LaunchApp"/>
      <class name="etaf.tests.LoginTests"/>
    </classes>
  </test> <!-- TC_LOGIN -->
  <test name="TC_LOGIN">
    <classes>
      <class name="etaf.tests.LaunchApp"/>
      <class name="etaf.tests.LoginTests"/>
    </classes>
  </test> <!-- TC_LOGIN -->
  <test name="TC_WORK">
    <classes>
      <class name="etaf.tests.LaunchApp"/>
    </classes>
  </test> <!-- TC_WORK -->
</suite> <!-- App Automation Testing -->

Solution

  • I believe the problem lies in the way in which you are iterating through the 2D array.

    Here's an easier of getting this done.

    import org.testng.TestNG;
    import org.testng.xml.XmlClass;
    import org.testng.xml.XmlSuite;
    import org.testng.xml.XmlTest;
    
    import java.util.*;
    
    public class TestClassExample {
        public static void main(String[] args) {
            String[][] data = new String[][]{
                    {"class1", "TC_LOGIN"},
                    {"class2", "TC_LOGIN"},
                    {"class1", "TC_WORK"}
            };
            sample(transformToMap(data), Collections.emptyMap());
        }
    
        private static Map<String, List<String>> transformToMap(String[][] data) {
            Map<String, List<String>> map = new HashMap<>();
            for (String[] aData : data) {
                String key = aData[1];
                List<String> classes = map.computeIfAbsent(key, k -> new ArrayList<>());
                classes.add(aData[0]);
            }
            return map;
        }
    
        private static void sample(Map<String, List<String>> dbArr, Map<String, String> parameters) {
    
            //Create an instance on TestNG
            TestNG myTestNG = new TestNG();
    
            //Create an instance of XML Suite and assign a name for it.
            XmlSuite suite = new XmlSuite();
            suite.setName("App Automation Testing");
            suite.setParameters(parameters);
            dbArr.forEach((key, value) -> {
                XmlTest xmlTest = new XmlTest(suite);
                xmlTest.setName(key);
                value.forEach(eachValue -> {
                    XmlClass xmlClass = new XmlClass(eachValue, false);
                    xmlTest.getClasses().add(xmlClass);
                });
            });
    
            //Add the suite to the list of suites.
            List<XmlSuite> suites = new ArrayList<>();
            suites.add(suite);
    
            System.out.println(suite.toXml());
    
            //Set the list of Suites to the testNG object you created earlier.
            myTestNG.setXmlSuites(suites);
        }
    }
    

    The output is as below:

    objc[59296]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/bin/java (0x102a554c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x102ae14e0). One of the two will be used. Which one is undefined.
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="App Automation Testing">
      <test thread-count="5" name="TC_WORK">
        <classes>
          <class name="class1"/>
        </classes>
      </test> <!-- TC_WORK -->
      <test thread-count="5" name="TC_LOGIN">
        <classes>
          <class name="class1"/>
          <class name="class2"/>
        </classes>
      </test> <!-- TC_LOGIN -->
    </suite> <!-- App Automation Testing -->
    
    
    Process finished with exit code 0