Need help on creating 'testng.xml' programatically

47 views
Skip to first unread message

Saran S

unread,
Aug 17, 2017, 10:03:27 PM8/17/17
to testng-users
Below is the scenario:

I have an excel document which contains TestCase Name, for ex., 'verifyHomePage', 'verifyLoginPage'. I have to read those TestCase Name from that excel file and pass it to 'testng.xml' file and it has to execute only those particular methods.

Ex.: In a Java file (TestNG class file), I have 3 methods: 'verifyHomePage', 'verifyLoginPage' and 'verifyAccountsPage'. In the excel I have mentioned only two method names: 'verifyHomePage', 'verifyLoginPage', so it should execute only those 2 methods.

Below is my code:

package testngpackage;


import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


import org.testng.TestNG;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlInclude;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;


import testpackage2.ReadTestCaseNameFromExcel;


public class TestNG_FS {
   
public static ArrayList<XmlClass> classes = new ArrayList<XmlClass>();


   
public static void main(String[] args) throws IOException {
       
XmlSuite suite = new XmlSuite();
        suite
.setName("Test Suite");
        suite
.setThreadCount(10);


       
XmlTest test = new XmlTest(suite);
        test
.setName("Test");
        test
.setPreserveOrder("true");


       
List<XmlClass> classNames = getClassNames();
       
int classSize = classNames.size();
       
System.out.println("Class size: " + classSize);


       
List<String> methodNames = ReadTestCaseNameFromExcel.readScenarioName(); //This is another class file I am using to fetch the method names from excel document, it is working fine.
         
int methodSize = methodNames.size();
         
System.out.println("Total no of methods: " + methodSize);


       
for (int i = 0; i < classNames.size(); i++) {
           
XmlClass className = classNames.get(i);
           
System.out.println("Class Name: " + className);
                       
           
for (int j = 0; j < methodNames.size(); j++) {
               
String methodName = methodNames.get(j);
           
               
List<XmlInclude> methodsToRun = new ArrayList<XmlInclude>();
                methodsToRun
.add(new XmlInclude(methodName));
                className
.setIncludedMethods(methodsToRun);
           
               
List<XmlSuite> suites = new ArrayList<XmlSuite>();
                suites
.add(suite);
               
                test
.setXmlClasses(classes);


               
/*TestNG testng = new TestNG();
                testng.setXmlSuites(suites);
                testng.run();*/



               
File file = new File("C:/Temp/TestNG.xml");
               
FileWriter writer = new FileWriter(file);
                writer
.write(suite.toXml());
               
System.out.println(suite.toXml());
                writer
.close();    
           
}
       
}    
   
}


   
public static List<XmlClass> getClassNames() {


       
XmlClass groupingClass = new XmlClass();
        groupingClass
.setName("testngpackage.TestNG_Grouping");
        classes
.add(groupingClass);


       
XmlClass classDemo1 = new XmlClass();
        classDemo1
.setName("testngpackage.TestNG_ClassDemo1");
        classes
.add(classDemo1);


       
return classes;
   
}
}


I am using another class file 'ReadTestCaseNameFromExcel​' with the method name 'readScenarioName​' to read the excel document to fetch the method names, it is Working Fine.

And also I am using 'getClassNames' (above code) method to pass the Class names.

I am getting the output as below:

Class size: 2


Total no of methods: 3
Class Name: [XmlClass class=testngpackage.TestNG_Grouping]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite thread-count="10" name="Test Suite">
 
<test name="Test">
   
<classes>
     
<class name="testngpackage.TestNG_Grouping">
       
<methods>
         
<include name="cars_sedan"/>
       
</methods>
      </
class> <!-- testngpackage.TestNG_Grouping -->
     
<class name="testngpackage.TestNG_ClassDemo1"/>
   
</classes>
  </
test> <!-- Test -->
</suite> <!-- Test Suite -->


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http:/
/testng.org/testng-1.0.dtd">
<suite thread-count="
10" name="Test Suite">
  <test name="
Test">
    <classes>
      <class name="
testngpackage.TestNG_Grouping">
        <methods>
          <include name="
train_Local"/>
        </methods>
      </class> <!-- testngpackage.TestNG_Grouping -->
      <class name="
testngpackage.TestNG_ClassDemo1"/>
    </classes>
  </test> <!-- Test -->
</suite> <!-- Test Suite -->


<?xml version="
1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "
http://testng.org/testng-1.0.dtd">
<suite thread-count="10" name="Test Suite">
 
<test name="Test">
   
<classes>
     
<class name="testngpackage.TestNG_Grouping">
       
<methods>
         
<include name="flight_Domestic"/>
       
</methods>
      </
class> <!-- testngpackage.TestNG_Grouping -->
     
<class name="testngpackage.TestNG_ClassDemo1"/>
   
</classes>
  </
test> <!-- Test -->
</suite> <!-- Test Suite -->


Class Name: [XmlClass class=testngpackage.TestNG_ClassDemo1]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http:/
/testng.org/testng-1.0.dtd">
<suite thread-count="
10" name="Test Suite">
  <test name="
Test">
    <classes>
      <class name="
testngpackage.TestNG_Grouping">
        <methods>
          <include name="
flight_Domestic"/>
        </methods>
      </class> <!-- testngpackage.TestNG_Grouping -->
      <class name="
testngpackage.TestNG_ClassDemo1">
        <methods>
          <include name="
cars_sedan"/>
        </methods>
      </class> <!-- testngpackage.TestNG_ClassDemo1 -->
    </classes>
  </test> <!-- Test -->
</suite> <!-- Test Suite -->


<?xml version="
1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "
http://testng.org/testng-1.0.dtd">
<suite thread-count="10" name="Test Suite">
 
<test name="Test">
   
<classes>
     
<class name="testngpackage.TestNG_Grouping">
       
<methods>
         
<include name="flight_Domestic"/>
       
</methods>
      </
class> <!-- testngpackage.TestNG_Grouping -->
     
<class name="testngpackage.TestNG_ClassDemo1">
       
<methods>
         
<include name="train_Local"/>
       
</methods>
      </
class> <!-- testngpackage.TestNG_ClassDemo1 -->
   
</classes>
  </
test> <!-- Test -->
</suite> <!-- Test Suite -->


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http:/
/testng.org/testng-1.0.dtd">
<suite thread-count="
10" name="Test Suite">
  <test name="
Test">
    <classes>
      <class name="
testngpackage.TestNG_Grouping">
        <methods>
          <include name="
flight_Domestic"/>
        </methods>
      </class> <!-- testngpackage.TestNG_Grouping -->
      <class name="
testngpackage.TestNG_ClassDemo1">
        <methods>
          <include name="
flight_Domestic"/>
        </methods>
      </class> <!-- testngpackage.TestNG_ClassDemo1 -->
    </classes>
  </test> <!-- Test -->
</suite> <!-- Test Suite -->


I am expecting the result as: One class name should be passed at a time in testng.xml file and it should iterate through all the methods from excel document as below:

My expected output is:

Class size: 2


Total no of methods: 3
Class Name: [XmlClass class=testngpackage.TestNG_Grouping]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite thread-count="10" name="Test Suite">
 
<test name="Test">
   
<classes>
     
<class name="testngpackage.TestNG_Grouping">        (First class file - only one class file for testng.xml)
       
<methods>
         
<include name="cars_sedan"/>                     (First method name from excel file)
       
</methods>
      </
class> <!-- testngpackage.TestNG_Grouping -->
   
</classes>
  </
test> <!-- Test -->
</suite> <!-- Test Suite -->


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http:/
/testng.org/testng-1.0.dtd">
<suite thread-count="
10" name="Test Suite">
  <test name="
Test">
    <classes>
      <class name="
testngpackage.TestNG_Grouping">        (First class file)
        <methods>
          <include name="
train_Local"/>                    (Second method name from excel file)
        </methods>
      </class> <!-- testngpackage.TestNG_Grouping -->
    </classes>
  </test> <!-- Test -->
</suite> <!-- Test Suite -->


<?xml version="
1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "
http://testng.org/testng-1.0.dtd">
<suite thread-count="10" name="Test Suite">
 
<test name="Test">
   
<classes>
     
<class name="testngpackage.TestNG_Grouping">        (First class file)
       
<methods>
         
<include name="flight_Domestic"/>                (Third method name from excel file)
       
</methods>
      </
class> <!-- testngpackage.TestNG_Grouping -->
   
</classes>
  </
test> <!-- Test -->
</suite> <!-- Test Suite -->


Class Name: [XmlClass class=testngpackage.TestNG_ClassDemo1]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http:/
/testng.org/testng-1.0.dtd">
<suite thread-count="
10" name="Test Suite">
  <test name="
Test">
    <classes>
      <class name="
testngpackage.TestNG_ClassDemo1">    (Second class file)
        <methods>
          <include name="
cars_sedan"/>                    (First method name from excel file)
        </methods>
      </class> <!-- testngpackage.TestNG_ClassDemo1 -->
    </classes>
  </test> <!-- Test -->
</suite> <!-- Test Suite -->


<?xml version="
1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "
http://testng.org/testng-1.0.dtd">
<suite thread-count="10" name="Test Suite">
 
<test name="Test">
   
<classes>
     
<class name="testngpackage.TestNG_ClassDemo1">    (Second class file)
       
<methods>
         
<include name="train_Local"/>                    (Second method name from excel file)
       
</methods>
      </
class> <!-- testngpackage.TestNG_ClassDemo1 -->
   
</classes>
  </
test> <!-- Test -->
</suite> <!-- Test Suite -->


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http:/
/testng.org/testng-1.0.dtd">
<suite thread-count="
10" name="Test Suite">
  <test name="
Test">
    <classes>
      <class name="
testngpackage.TestNG_ClassDemo1">    (Second class file)
        <methods>
          <include name="
flight_Domestic"/>                (Third method name from excel file)
        </methods>
      </class> <!-- testngpackage.TestNG_ClassDemo1 -->
    </classes>
  </test> <!-- Test -->
</suite> <!-- Test Suite -->

Could anyone please give me any suggestion or code to achieve this?

Thanks in advance

Krishnan Mahadevan

unread,
Aug 17, 2017, 10:57:46 PM8/17/17
to testng...@googlegroups.com

The bug lies in your code.

 

Here’s a working sample.

 

import org.testng.xml.XmlClass;

import org.testng.xml.XmlInclude;

import org.testng.xml.XmlSuite;

import org.testng.xml.XmlTest;

 

import java.io.IOException;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

 

public class TestNG_FS {

 

   public static void main(String[] args) throws IOException {

        XmlSuite suite = new XmlSuite();

        suite.setName("Test Suite");

        suite.setThreadCount(10);

 

 

        XmlTest test = new XmlTest(suite);

        test.setName("Test");

 

        List<XmlClass> xmlClasses = new ArrayList<>();

        for (String className : getClassNames()) {

            List<String> methods = readScenarioName(className);

            //Calling the two arg constructor, so that TestNG doesnt try searching for the classes and load them

            //Since I dont have those classes in my project. In real life scenario you would be using only the

            //one arg constructor.

            XmlClass xmlClass = new XmlClass(className, false);

            List<XmlInclude> methodsToRun = new ArrayList<>();

            for (String method : methods) {

                methodsToRun.add(new XmlInclude(method));

            }

            xmlClass.setIncludedMethods(methodsToRun);

            xmlClasses.add(xmlClass);

        }

        test.setClasses(xmlClasses);

        System.err.println("Printing the suite");

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

    }

 

 

    public static List<String> getClassNames() {

        //Replace this with the actual logic of getting hold of the class names.

        return Arrays.asList("testngpackage.TestNG_Grouping", "testngpackage.TestNG_ClassDemo1");

    }

 

    private static List<String> readScenarioName(String forClass) {

        //Include logic here such that you retrieve the list of methods that are applicable for the given class

        //by reading up the Excel spreadsheet properly

 

        return Arrays.asList("foo", "bar", "foobar");

    }

}

 

And here’s the output:

 

Printing the suite

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite thread-count="10" name="Test Suite">

  <test name="Test">

    <classes>

      <class name="testngpackage.TestNG_Grouping">

        <methods>

          <include name="foo"/>

          <include name="bar"/>

          <include name="foobar"/>

        </methods>

      </class> <!-- testngpackage.TestNG_Grouping -->

      <class name="testngpackage.TestNG_ClassDemo1">

        <methods>

          <include name="foo"/>

          <include name="bar"/>

          <include name="foobar"/>

        </methods>

      </class> <!-- testngpackage.TestNG_ClassDemo1 -->

    </classes>

  </test> <!-- Test -->

</suite> <!-- Test Suite -->

 

 

Process finished with exit code 0

 

 

 

 

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 Scribbings @ http://rationaleemotions.wordpress.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 post to this group, send email to testng...@googlegroups.com.
Visit this group at https://groups.google.com/group/testng-users.
For more options, visit https://groups.google.com/d/optout.

Saran S

unread,
Aug 18, 2017, 10:59:33 AM8/18/17
to testng-users
Thank you so much for your help, thanks...

Saran S

unread,
Aug 19, 2017, 8:21:04 AM8/19/17
to testng-users
Hi,

Thanks for your reply.

I have changed the code as per your suggestion as below:

package testngpackage;


import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

import java.util.Iterator;
import java.util.List;


import org.testng.TestNG;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlInclude;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;


import testpackage2.ReadTestCaseNameFromExcel;


public class TestNG_FS {
 
public static ArrayList<XmlClass> classes = new ArrayList<XmlClass>();


 
public static void main(String[] args) throws IOException {
 
XmlSuite suite = new XmlSuite();
 suite
.setName("Test Suite");
 suite
.setThreadCount(10);


 
XmlTest test = new XmlTest(suite);
 test
.setName("Test");
 test
.setPreserveOrder("true");



 
List<XmlClass> xmlClasses = new ArrayList<>();
 
 
List<String> methods = ReadTestCaseNameFromExcel.readScenarioName();


 
for (String className : getClassNames()) {

 
XmlClass xmlClass = new XmlClass(className, false);
 
List<XmlInclude> methodsToRun = new ArrayList<>();
 
for (String method : methods) {
 methodsToRun
.add(new XmlInclude(method));
 
}
 xmlClass
.setIncludedMethods(methodsToRun);
 xmlClasses
.add(xmlClass);
 
}


 test
.setClasses(xmlClasses);

 
System.out.println("Printing the suite");
 
System.out.println(suite.toXml());

 
 
List<XmlSuite> suites = new ArrayList<XmlSuite>();
 suites
.add(suite);

 
 
TestNG testng = new TestNG();
 testng
.setXmlSuites(suites);
 testng
.run();


 
}


 
public static List<String> getClassNames() {


 
return Arrays.asList("testngpackage.TestNG_Grouping", "testngpackage.TestNG_ClassDemo1", "testngpackage.TestNG_ClassDemo2");


 
}
}


I don't want to pass the Class name in 'readScenarioName' method, so I didn't use that.

While executing the above code, I got the below output:



rows
: 1000
cols
: 26
Header value above the TRUE column: 'Contacts'


TRUE found on the row
2, from the column 0



Printing the suite
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite thread-count="10" name="Test Suite">
 
<test name="Test">
   
<classes>
     
<class name="testngpackage.TestNG_Grouping">
       
<methods>

         
<include name="cars_sedan"/>
         
<include name="train_Local"/>

         
<include name="flight_Domestic"/>
       
</methods>
      </
class> <!-- testngpackage.TestNG_Grouping -->
     
<class name="testngpackage.TestNG_ClassDemo1">
       
<methods>
         
<include name="cars_sedan"/>

         
<include name="train_Local"/>

         
<include name="flight_Domestic"/>
       
</methods>
      </
class> <!-- testngpackage.TestNG_ClassDemo1 -->

     
<class name="testngpackage.TestNG_ClassDemo2">

       
<methods>
         
<include name="cars_sedan"/>

         
<include name="train_Local"/>
         
<include name="flight_Domestic"/>
       
</methods>
      </
class> <!-- testngpackage.TestNG_ClassDemo2 -->

   
</classes>
  </
test> <!-- Test -->
</suite> <!-- Test Suite -->


[TestNG] Running:
 
Command line suite


This is Cars Sedan method
This is Flight Domestic method
This is Train Local method
This is Test Method from TestNGClassDemo1
This is Test Method from TestNGClassDemo2


===============================================
Test Suite
Total tests run: 5, Failures: 0, Skips: 0
===============================================




I have a problem in this output:

Actual Output:
This is Cars Sedan method
This is Flight Domestic method
This is Train Local method
This is Test Method from TestNGClassDemo1
This is Test Method from TestNGClassDemo2


I have three class files: "TestNG_Grouping",  "TestNG_ClassDemo1" and "TestNG_ClassDemo2"

I am passing 3 Method names from excel: "cars_sedan", "train_Local" and "flight_Domestic", these 3 methods are available only in "TestNG_Grouping" class file with @Test annotation.

Other 2 class files: "TestNG_ClassDemo1" class file contains a method in the name of  "test1_Demo1"  (This is Test Method from TestNGClassDemo1)
and "TestNG_ClassDemo2" class file contains a method in the name of  "test1_Demo2" (This is Test Method from TestNGClassDemo2)
with @Test annotation.

Passed Method names found a match in "TestNG_Grouping" class file, so it is executing only those 3 methods (this is fine), but there is no match found in other two class files: "TestNG_ClassDemo1" and "TestNG_ClassDemo2", so it is executing all the methods from those class files (this is the problem), if there is no match found in Class file it should NOT execute any methods even if it is under @Test annotation.

But I have to pass all the Class file names through "getClassNames" method, this is my requirement.

My Expected output should be as below:

Expected Output:
This is Cars Sedan method
This is Flight Domestic method
This is Train Local method

Please help me on this.
















On Friday, August 18, 2017 at 8:27:46 AM UTC+5:30, Krishnan wrote:

On Friday, August 18, 2017 at 8:27:46 AM UTC+5:30, Krishnan wrote:

Krishnan Mahadevan

unread,
Aug 19, 2017, 11:35:46 AM8/19/17
to testng...@googlegroups.com

Saran,

 

In my opinion, it’s a bug. I have logged this as a bug here: https://github.com/cbeust/testng/issues/1507

 

Feel free to follow that bug.

Reply all
Reply to author
Forward
0 new messages