Search code examples
javaselenium-webdrivertestng

Setting global variables at runtime for TestNG Suite?


I have written a TestNG Suite in Java that will be ran on another system using a test account. The credentials for this account are stored in a password vault and are obtained through an API. Each of the tests requires this login information, and every test class will call the password vault API. I have this as a step in the setup method of each test class.

I would like to reduce it to just a single API call if possible. Would it be possible to obtain the credentials at the beginning of the suite and pass those to each of the test classes?

I looked at this as a potential solution: How to add parameter at runtime in specific test

I would prefer to not modify the XML in this way, as I found this will expose the login information in TestNG's results report.


Solution

  • Here's how you go about doing it.

    • Build a TestNG listener by implementing the TestNG interface org.testng.ISuiteListener
    • Within its onStart() method, include the logic to retrieve the credentials from the vault and then set them as attributes on the ISuite object (which you get as a parameter to the onStart() method)
        suite.setAttribute("username", 'foo');
        suite.setAttribute("password", "foopassword");
    
    • Now within your test method, you can retrieve the credentials as seen below
    org.testng.ITestResult itr = org.testng.Reporter.getCurrentTestResult();
    org.testng.ISuite currentSuite = itr.getTestContext().getSuite();
    String username = Optional.ofNullable(currentSuite.getAttribute("username"))
            .map(Object::toString)
            .orElseThrow(() -> new IllegalArgumentException("Could not find a valid user name"));
    String password = Optional.ofNullable(currentSuite.getAttribute("password"))
            .map(Object::toString)
            .orElseThrow(() -> new IllegalArgumentException("Could not find a valid password"));
    
    • You can now include a reference to this suite using the <listeners> tag in your suite xml file [ for details refer here ] (or)
    • You can make this listener a mandatory listener which would always get invoked automatically without needing it to be explicitly referenced, by wiring it in as a service loader loaded listener [ for details refer here ]