0

I have a parameterized method(readConfig_1(String path)) in a class which I need to run before the tests in a TestNG Suite. Is there a way that I can call this method and define the parameter for the same in the TestNG.xml file?

Here's the Parameterized Method, I have written which actually needs a path to where the XML file is stored.

public static void readConfig_1(String configXmlPath) 
{

            browser = CoreLib.fGetNodeText(configXmlPath, "config",
                    "browser");
             env = CoreLib.fGetNodeText(configXmlPath, "config", "env");
             release = CoreLib.fGetNodeText(configXmlPath, "config", "release");
            serverName = CoreLib.fGetNodeText(configXmlPath, env,
                    "serverName");
             host = CoreLib.fGetNodeText(configXmlPath, env, "host");
            userName = CoreLib.fGetNodeText(configXmlPath, env, "userName");
            passWord = CoreLib.fGetNodeText(configXmlPath, env, "passWord");
            portNumber = CoreLib.fGetNodeText(configXmlPath, env,
                    "portNumber");
            schema = CoreLib.fGetNodeText(configXmlPath, env, "schema");
            url = CoreLib.fGetNodeText(configXmlPath, env, "url");
            screenShotForPass=CoreLib.fGetNodeText(configXmlPath, env, "SCreenShotForPass");

            screenShotForFail=CoreLib.fGetNodeText(configXmlPath, env, "SCreenShotForFail");


            CoreLib.LOGGER.info("****************************************************");
            CoreLib.LOGGER.info("           Configuration Details                    ");
            CoreLib.LOGGER.info("****************************************************");

            CoreLib.LOGGER.info("Browser ::" + browser);
            CoreLib.LOGGER.info("env ::" + env);
            CoreLib.LOGGER.info("serverName ::" + serverName);
            CoreLib.LOGGER.info("host ::" + host);
            CoreLib.LOGGER.info("userName ::" + userName);
            CoreLib.LOGGER.info("passWord ::" + passWord);
            CoreLib.LOGGER.info("portNumber ::" + portNumber);
            CoreLib.LOGGER.info("schema ::" + schema);
            CoreLib.LOGGER.info("url::" + url);
            CoreLib.LOGGER.info("ScreenSnapShotForPass::"+screenShotForPass );
            CoreLib.LOGGER.info("ScreenSnapShotForFail::"+screenShotForFail );

        }

In this TestNG Suite seen below, I need to call the above method passing a parameter to it before it can go ahead and run the tests written in the other classes.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Smoke Suite" parallel="false" preserve-order="true">

    <listeners>
        <listener class-name="com.healthcare.reports.MyListener"></listener>
    </listeners>



    <test name="XYZ Tests">
        <classes>

            <class name="com.healthcare.utility.Config">
                <methods>
                    <include name="readConfig_1"></include>
                </methods>
            </class>

            <class name="com.healthcare.businessLib.xyz.AddUserTests" />

        </classes>

    </test>


</suite> 

By this I intend to restrict a TestNG Suite to read a particular Config.XML file which will have it's own values such as Env, URL, browser etc., set before the tests can be executed. Is there a way I can achieve this?


----Added 11/24/2017-----

---- I thought adding the readConfig_1 to a @BeforeClass annotation would resolve the problem. But there's more to it-----

My Listener Class has **@onStart** annotation which needs the config file to be run on the start of the Suite. As you see below my Listener Class has the variables release_1 coming from Config file.

 public class MyListener implements ITestListener, ISuiteListener {

        // This belongs to ISuiteListener and will execute before the Suite start

        ReportLib report=new ReportLib();

        @Override
        public void onStart(ISuite arg0) {

            Config.readConfig_1(configXlsPath);
            ExportTestResults export = new ExportTestResults();
            export.exportExcelHeader(Config.release_1);
            CoreLib.fCreateLogger(Config.release_1);

        }

But if I put it in @BeforeClass in a TestClass these variables(Config.release_1) are returning null as they would be running before the test class. So I need the readconfig_1 to run before or with the Listener class and unable to add a parameter to the onStart(ISuite arg0).

Tried a few things by :

  1. Running the readConfig_1() in the TestNG.XML as the first method even before the listener class could be called.

  2. putting a @BeforeClass annotation in the Listener class with readConfig_1() method parameterized in it- hoping that the readConfig would be called before the onStart() is executed.

    public class MyListener2 implements ITestListener, ISuiteListener {
    
        ReportLib report=new ReportLib();
    
        @BeforeClass
        @Parameters("configXlsPath")
        public void beforeSuite(String configXlsPath)
        {
            Config.readConfig_1(configXlsPath);
            System.out.println("In Before Class(Listener_2)"+ Config.release_1);
        }
    
    
        @Override
        public void onStart(ISuite arg0) {
    
            ExportTestResults export = new ExportTestResults();
            System.out.println("In onStart(Listener_2)"+ Config.release_1);
            export.exportExcelHeader(Config.release_1);
            CoreLib.fCreateLogger(Config.release_1);
    
        }
    

    }

But none worked. Is there a way around this now?

Thanks in advance.

S K
  • 308
  • 2
  • 6
  • 20
  • you can take some help from [here](http://www.seleniumeasy.com/testng-tutorials/parameterization-in-testng) – Ali Azam Nov 22 '17 at 05:14
  • Please read why [a screenshot of code is a bad idea](https://meta.stackoverflow.com/questions/303812/discourage-screenshots-of-code-and-or-errors). Paste the code and properly format it instead. – JeffC Nov 22 '17 at 05:53
  • @JeffC - Sure, I will do that in some time. Thanks for the suggestion. – S K Nov 22 '17 at 06:04
  • @SK Should you be including a config method as a test? Will it not mess up the report? Try making it a before method. – Grasshopper Nov 22 '17 at 07:19
  • @SK I pushed an answer for your question. Please implement that and let me know if it is best fit or not for your need. – Ali Azam Nov 22 '17 at 14:09
  • @Grasshopper yeah.. This is how I was trying to implement it. But with all the suggestions, I think I will put in a BeforeClass Method. Thanks. – S K Nov 22 '17 at 15:36
  • @AliAzam All the answers below works but I think putting it in a BeforeClass works best for my case. Thanks for the help. – S K Nov 22 '17 at 15:38
  • @SK I also used it in BeforeClass method and it works fine here. But I saw your question that you would like to run on Before Test method. So I am updating this to work on precisely – Ali Azam Nov 22 '17 at 16:15
  • @AliAzam Grasshopper: I tried putting it in BeforeClass and I realized that I am creating an excel header and also Logger which needs the 'env' variable from the Cofig file and running the readConfig method in Testclass does mess up my report. So I need some suggestion around this. – S K Nov 24 '17 at 18:07

3 Answers3

1

Yes, you can do this. Firstly, add @Parameters("configXmlPath") annotation to your test class. configXmlPath parameter must also be defined in testng.xml file like <parameter name = "configXmlPath" value="Whateverthevalueis"/> this. Here is an example.

import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class YourTest {
   @Test
   @Parameters("configXmlPath")
   public void test1(String configXmlPath) {
      System.out.println("Parameterized value is : " + configXmlPath);
   }
}

Then, in your testng.xml define parameter like this:

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name = "Suite1">
   <test name = "test1">

      <parameter name = "configXmlPath" value="Whateverthevalueis"/> 

     <classes>
         <class name = "YourTest" />
      </classes>

    </test>
</suite>
Oguz Ozcan
  • 1,497
  • 13
  • 21
  • I have checked with all the solutions and putting it in BeforeClass works best. Thanks for the suggestions. – S K Nov 22 '17 at 15:45
  • I apologize for unmarking this as a solution to my problem. But there's more to the problem itself. Thank you for your suggestions. – S K Nov 24 '17 at 17:54
1

In your java method , use @BeforeClass and @Parameters annotation ,

@BeforeClass
@Parameters({"configXlsPath"})
public static void readConfig_1(@Optional("addaDefaultPathValue") String configXlsPath)

In your xml , add a parameter tag after tests tag.

<test name="Purchaser Tests">
 <parameter name="configXlsPath" value="target/path/to/xmlFile">
Manmohan_singh
  • 1,776
  • 3
  • 20
  • 29
  • Wouldn't it be better to use BeforeSuite or BeforeTest – Grasshopper Nov 22 '17 at 05:53
  • Have worked with BeforeSuite , null parameters are passed to the class methods. BeforeTest will reset the value after execution of each @Test annotated method. As per convention, configuration file should be loaded once . so BeforeClass is the right candidate annotation. – Manmohan_singh Nov 22 '17 at 06:04
1

You need to define your Parameterized Method under @BeforeClass annotations and should be inside the test class or inherited from other class.

I was also dealing with the same issue and resolved this in the below ways:

import org.testng.annotations.BeforeClass;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class AddUserTests {

    @BeforeClass(alwaysRun = true)
    @Parameters("configXmlPath")
    public void readConfig_1(String configXmlPath){
      System.out.println("File path : "+ configXmlPath);

       /*
            You can use the configXmlPath value to 
            your code that goes here
       */      
    }

    @Test
    public void test_1(){
        //Test Code 
    }

    @Test
    public void test_2(){
        //Test Code     
    }       
}

You need to define and set your parameter value in the xml file like

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Smoke Suite" parallel="false" preserve-order="true">

    <listeners>
        <listener class-name="com.healthcare.reports.MyListener"></listener>
    </listeners>

    <test name="XYZ Tests">
      <parameter name="configXmlPath" value="USE_ABSOLUTE_PATH_HERE"/> 
        <classes>
            <class name="com.healthcare.businessLib.xyz.AddUserTests" />
        </classes>

    </test>

</suite>

Please use the absolute path [i.e,C://Config.XML] of the config file instead of USE_ABSOLUTE_PATH_HERE

Ali Azam
  • 2,047
  • 1
  • 16
  • 25