简体   繁体   中英

Set .properties file to testng.xml

I have a data.properties file with the following lines :

data.login=login
data.password=password

and I have a simple test(with testng):

@Test
@Parameters({"data.login","data.password"})
public void testSimpleExample(String login, String password) throws Exception {
    Assert.assertTrue(login.equals("login"));
    Assert.assertTrue(password.equals("password"));
}

In testng.xml file I can write next strings :

<parameter name="data.login" value="login" />
<parameter name="data.password" value="password" />

but I want to use my data.properties file. Can I somehow set this file into testng.xml and use parameters from this properties file ? Of course without using next code :

Properties properties = new Properties();
properties.load(....);
    ....
properties.getProperty("data.login");

Here, it is the perfect use case for a data provider .

@DataProvider
public Object[][] dp() {
  Properties properties = new Properties();
  properties.load(....);
  ....
  String login = properties.getProperty("data.login");
  String password = properties.getProperty("data.password");
  return new Object[][] { new Object[]{login, password} };
}

@Test(dataProvider = "dp")
public void testSimpleExample(String login, String password) throws Exception {
    Assert.assertTrue(login.equals("login"));
    Assert.assertTrue(password.equals("password"));
}

Here's another way of doing it, if you don't want to make use of the data provider approach that @juherr has called out.

Properties file represents a Key/Value pair, so essentially its a map. So you do the following :

  1. Ensure you are using TestNG v6.11 (or) higher.
  2. Use the @Parameters annotation as if you are going to get the values from your TestNG suite xml file.
  3. Build a org.testng.IAlterSuiteListener implementation wherein you read your properties file, extract out the map, and then inject this map as parameters into your XmlSuite object.
  4. You wire in this listener that you created in (3) either via the <listeners> tag in your suite xml (or) via a Service loader mechanism.

Now you can continue to work with the @Parameters annotation, but all of your properties are injected dynamically.

Here's a sample of all this in action.

TestClass looks like below

package com.rationaleemotions.stackoverflow.qn46224926;

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

public class TestClass {
    @Test
    @Parameters("name")
    public void testMethod(String name) {
        System.err.println("Hello " + name);
    }
}

The IAlterSuiteListener implementation looks like below:

package com.rationaleemotions.stackoverflow.qn46224926;

import org.testng.IAlterSuiteListener;
import org.testng.xml.XmlSuite;

import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class PropertyInjectorListener implements IAlterSuiteListener {
    @Override
    public void alter(List<XmlSuite> suites) {
        XmlSuite suite = suites.get(0);
        Properties properties = new Properties();
        try {
            properties.load(new FileReader("src/test/resources/46224926/qn46224926.properties"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        Map<String, String> params = new HashMap<>();
        for (Map.Entry<Object, Object> each : properties.entrySet()) {
            params.put(each.getKey().toString(), each.getValue().toString());

        }
        suite.setParameters(params);
    }
}

A sample properties file can look like below:

name=Jack

The suite xml file would look like below:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="46224926_Suite" verbose="2">
    <listeners>
        <listener class-name="com.rationaleemotions.stackoverflow.qn46224926.PropertyInjectorListener"/>
    </listeners>
    <test name="46224926_test">
        <classes>
            <class name="com.rationaleemotions.stackoverflow.qn46224926.TestClass"/>
        </classes>
    </test>
</suite>

When you run this, you should see an output as below:

...
... TestNG 6.12 by Cédric Beust (cedric@beust.com)
...
Hello Jack
PASSED: testMethod("Jack")

===============================================
    46224926_test
    Tests run: 1, Failures: 0, Skips: 0
===============================================

===============================================
46224926_Suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

As you can see, the suite xml file does not contain any <parameters> tag at all. But the @Test method still assumes that it will get parameter values via the @Parameters annotation. Since our listener takes care of reading all the properties and injecting them as a parameter map, TestNG does not complain.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM