本文目录导读:

- Excel数据驱动测试(TestNG + Apache POI)
- YAML配置驱动(Spring Boot + SnakeYAML)
- CSV数据驱动(OpenCSV)
- 数据库数据驱动(JDBC)
- JSON数据驱动(Jackson)
- 最佳实践建议
我来为您提供几个Java数据驱动开发的典型案例,涵盖不同场景:
Excel数据驱动测试(TestNG + Apache POI)
数据准备(test-data.xlsx)
| 用例编号 | 用户名 | 密码 | 期望结果 |
|---------|---------|---------|---------|
| TC001 | admin | 123456 | 成功 |
| TC002 | user1 | wrong | 失败 |
| TC003 | empty | 123456 | 失败 |
代码实现
import org.apache.poi.ss.usermodel.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
public class ExcelDataDrivenTest {
@DataProvider(name = "loginData")
public Object[][] getLoginData() throws Exception {
List<Object[]> data = new ArrayList<>();
FileInputStream file = new FileInputStream("test-data.xlsx");
Workbook workbook = WorkbookFactory.create(file);
Sheet sheet = workbook.getSheetAt(0);
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
String username = row.getCell(0).getStringCellValue();
String password = row.getCell(1).getStringCellValue();
String expected = row.getCell(2).getStringCellValue();
data.add(new Object[]{username, password, expected});
}
workbook.close();
return data.toArray(new Object[0][]);
}
@Test(dataProvider = "loginData")
public void testLogin(String username, String password, String expected) {
System.out.println("Testing: " + username + "/" + password + " -> Expected: " + expected);
// 实际测试逻辑
}
}
YAML配置驱动(Spring Boot + SnakeYAML)
application-config.yml
database:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: secret
api:
endpoints:
- name: user-service
url: http://api.example.com/users
timeout: 5000
- name: order-service
url: http://api.example.com/orders
timeout: 3000
features:
- name: search
enabled: true
params:
maxResults: 100
cacheEnabled: true
配置类实现
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private DatabaseConfig database;
private List<ApiEndpoint> api;
private List<Feature> features;
// Getters and Setters
public static class DatabaseConfig {
private String url;
private String username;
private String password;
// getters/setters
}
public static class ApiEndpoint {
private String name;
private String url;
private int timeout;
// getters/setters
}
public static class Feature {
private String name;
private boolean enabled;
private Map<String, Object> params;
// getters/setters
}
}
// 使用配置
@Service
public class ConfigDrivenService {
@Autowired
private AppConfig appConfig;
public void executeFeatures() {
for (AppConfig.Feature feature : appConfig.getFeatures()) {
if (feature.isEnabled()) {
System.out.println("Executing feature: " + feature.getName());
// 根据配置执行逻辑
}
}
}
}
CSV数据驱动(OpenCSV)
test-cases.csv
username,password,age,role
admin,secret,30,admin
user1,pass123,25,user
guest,guest123,20,guest
CSV读取工具类
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
public class CsvDataProvider {
public static List<UserTestData> loadTestData(String csvPath) {
List<UserTestData> testDataList = new ArrayList<>();
try (CSVReader reader = new CSVReaderBuilder(new FileReader(csvPath))
.withSkipLines(1) // 跳过标题行
.build()) {
String[] line;
while ((line = reader.readNext()) != null) {
UserTestData data = new UserTestData();
data.setUsername(line[0]);
data.setPassword(line[1]);
data.setAge(Integer.parseInt(line[2]));
data.setRole(line[3]);
testDataList.add(data);
}
} catch (Exception e) {
e.printStackTrace();
}
return testDataList;
}
}
class UserTestData {
private String username;
private String password;
private int age;
private String role;
// getters/setters
}
数据库数据驱动(JDBC)
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class DatabaseDataProvider {
public List<TestCase> loadTestCasesFromDB() {
List<TestCase> testCases = new ArrayList<>();
String sql = "SELECT * FROM test_cases WHERE status = 'ACTIVE'";
try (Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/testdb", "root", "password");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
TestCase tc = new TestCase();
tc.setId(rs.getInt("id"));
tc.setName(rs.getString("name"));
tc.setInputData(rs.getString("input_data"));
tc.setExpectedResult(rs.getString("expected_result"));
testCases.add(tc);
}
} catch (SQLException e) {
e.printStackTrace();
}
return testCases;
}
}
class TestCase {
private int id;
private String name;
private String inputData;
private String expectedResult;
// getters/setters
}
JSON数据驱动(Jackson)
test-data.json
{
"loginTests": [
{
"username": "admin",
"password": "correct_password",
"expectedStatus": 200,
"expectedMessage": "Login successful"
},
{
"username": "wrong_user",
"password": "wrong_password",
"expectedStatus": 401,
"expectedMessage": "Authentication failed"
}
],
"searchTests": [
{
"keyword": "java",
"expectedResults": 10,
"pageSize": 20
}
]
}
Jackson解析
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.util.List;
public class JsonDataProvider {
public static TestDataCollection loadTestData(String jsonPath) throws Exception {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(new File(jsonPath), TestDataCollection.class);
}
}
class TestDataCollection {
private List<LoginTest> loginTests;
private List<SearchTest> searchTests;
// getters/setters
}
class LoginTest {
private String username;
private String password;
private int expectedStatus;
private String expectedMessage;
// getters/setters
}
class SearchTest {
private String keyword;
private int expectedResults;
private int pageSize;
// getters/setters
}
最佳实践建议
-
选择合适的数据格式:
- 小规模数据:CSV/Excel
- 复杂结构:JSON/YAML
- 大量数据:数据库
-
数据隔离:
- 测试数据与代码分离
- 使用环境变量管理敏感信息
-
异常处理:
try { // 数据加载逻辑 } catch (DataLoadException e) { // 降级处理:使用默认数据或跳过测试 logger.error("Data load failed, using defaults", e); } -
缓存机制:
@Cacheable(value = "testData", key = "#dataType") public Object loadData(String dataType) { // 从第三方源加载数据 }
这些案例展示了Java数据驱动的常见模式,可以根据实际需求组合使用。