TestNG 的 @DataProvider 支援從多種數據源讀取測試數據:Excel、XML、YAML、CSV 等。本文以 XML + DOM4J 解析 為例,實現靈活的數據驅動測試。
<?xml version="1.0" encoding="UTF-8"?>
<data>
<testmethod1>
<input>1</input>
<button>2</button>
</testmethod1>
<testmethod1>
<input>3</input>
<button>4</button>
</testmethod1>
<testmethod2>
<input>3</input>
<button>4</button>
</testmethod2>
<testmethod3>
<input>3</input>
<button>4</button>
</testmethod3>
<testmethod4>
<input>3</input>
<button>4</button>
</testmethod4>
</data>
public class ParserXml {
public List<Map<String, Map<String, String>>> parseXml(String fileName) {
List<Map<String, Map<String, String>>> result = new ArrayList<>();
File inputXml = new File(fileName);
SAXReader reader = new SAXReader();
try {
Document doc = reader.read(inputXml);
Element root = doc.getRootElement();
for (Iterator<Element> it = root.elementIterator(); it.hasNext(); ) {
Element methodNode = it.next(); // 如 testmethod1
Map<String, String> params = new HashMap<>();
for (Iterator<Element> paramIt = methodNode.elementIterator(); paramIt.hasNext(); ) {
Element paramNode = paramIt.next(); // 如 input, button
params.put(paramNode.getName(), paramNode.getText());
}
Map<String, Map<String, String>> entry = new HashMap<>();
entry.put(methodNode.getName(), params);
result.add(entry);
}
} catch (DocumentException e) {
e.printStackTrace();
}
return result;
}
}
public class TestData {
private List<Map<String, Map<String, String>>> xmlData;
public TestData() {
ParserXml parser = new ParserXml();
xmlData = parser.parseXml(new File("src/com/test/TestData.xml").getAbsolutePath());
}
@DataProvider
public Object[][] providerMethod(Method method) {
String methodName = method.getName();
List<Map<String, String>> matched = new ArrayList<>();
// 篩選匹配當前測試方法的數據組
for (Map<String, Map<String, String>> entry : xmlData) {
if (entry.containsKey(methodName)) {
matched.add(entry.get(methodName));
}
}
// 轉換為 Object[][] 格式
Object[][] data = new Object[matched.size()][];
for (int i = 0; i < matched.size(); i++) {
data[i] = new Object[] { matched.get(i) }; // 每行一個 Map
}
return data;
}
}
public class TestDataProvider extends TestData {
@Test(dataProvider = "providerMethod")
public void testmethod1(Map<?, ?> param) {
System.out.println("method1 received: " + param.get("input"));
}
@Test(dataProvider = "providerMethod")
public void testmethod2(Map<?, ?> param) {
System.out.println("method2 received: " + param.get("input"));
}
@Test(dataProvider = "providerMethod")
public void testmethod3(Map<?, ?> param) {
System.out.println("method3 received: " + param.get("input"));
}
@Test // 無 DataProvider,正常執行一次
public void testmethod4() {
System.out.println("method4 received: 4");
}
}
method1 received: 1
method1 received: 3
method2 received: 3
method3 received: 3
method4 received: 4
PASSED: testmethod1({input=1, button=2})
PASSED: testmethod1({input=3, button=4})
PASSED: testmethod2({input=3, button=4})
PASSED: testmethod3({input=3, button=4})
PASSED: testmethod4
===============================================
Default test
Tests run: 5, Failures: 0, Skips: 0
===============================================
testmethod1) 與測試方法名對應Map,通過 @Test(dataProvider) 自動注入dataProvider 的方法正常執行一次@Test(threadPoolSize=5, invocationCount=10) 實現併發壓測<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>