diff --git a/test-common/src/main/java/com/test/common/utils/MySQLExecutor.java b/test-common/src/main/java/com/test/common/utils/MySQLExecutor.java index 0313a01..7dfe516 100644 --- a/test-common/src/main/java/com/test/common/utils/MySQLExecutor.java +++ b/test-common/src/main/java/com/test/common/utils/MySQLExecutor.java @@ -21,9 +21,10 @@ public class MySQLExecutor { * @param url 数据库 URL * @param user 数据库用户名 * @param password 数据库密码 + * @param columnNameList 所有列名集合 * @return 查询结果(每行数据为一个 Map) */ - public static List> executeQuery(String sql, String url, String user, String password) { + public static List> executeQuery(String sql, String url, String user, String password, List columnNameList) { List> result = new ArrayList<>(); try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement()) { @@ -40,6 +41,9 @@ public class MySQLExecutor { String columnName = metaData.getColumnLabel(i); Object columnValue = resultSet.getObject(i); row.put(columnName, columnValue); + if (i == 1) { + columnNameList.add(columnName); + } } result.add(row); } diff --git a/test-test/src/main/java/com/test/test/domain/qo/SqlResult.java b/test-test/src/main/java/com/test/test/domain/qo/SqlResult.java new file mode 100644 index 0000000..52ee9bc --- /dev/null +++ b/test-test/src/main/java/com/test/test/domain/qo/SqlResult.java @@ -0,0 +1,23 @@ +package com.test.test.domain.qo; + +import lombok.Data; + +import java.util.List; +import java.util.Map; + +/** + * @author liangdaliang + * @Description:sql结果对象 + * @date 2025-02-21 09:54 + */ +@Data +public class SqlResult { + /** + * 列名 + */ + private List columnNameList; + /** + * 结果数据 + */ + private List> resultMapList; +} diff --git a/test-test/src/main/java/com/test/test/service/impl/TestCaseServiceImpl.java b/test-test/src/main/java/com/test/test/service/impl/TestCaseServiceImpl.java index 9fc35a0..842f45a 100644 --- a/test-test/src/main/java/com/test/test/service/impl/TestCaseServiceImpl.java +++ b/test-test/src/main/java/com/test/test/service/impl/TestCaseServiceImpl.java @@ -4,13 +4,16 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.test.common.utils.DateUtils; import com.test.common.utils.JMeterUtil; +import com.test.common.utils.MySQLExecutor; import com.test.common.utils.StringUtils; import com.test.test.domain.TestCase; import com.test.test.domain.TestCaseResult; import com.test.test.domain.TestCaseStep; +import com.test.test.domain.TestDatasource; import com.test.test.domain.qo.*; import com.test.test.mapper.TestCaseMapper; import com.test.test.mapper.TestCaseResultMapper; +import com.test.test.mapper.TestDatasourceMapper; import com.test.test.service.ITestCaseService; import com.test.test.service.ITestCaseStepService; import jakarta.annotation.Resource; @@ -18,6 +21,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import java.lang.reflect.Type; import java.util.ArrayList; @@ -39,6 +43,8 @@ public class TestCaseServiceImpl implements ITestCaseService private TestCaseMapper testCaseMapper; @Resource private TestCaseResultMapper testCaseResultMapper; + @Resource + private TestDatasourceMapper testDatasourceMapper; @Autowired private ITestCaseStepService testCaseStepService; @@ -141,6 +147,11 @@ public class TestCaseServiceImpl implements ITestCaseService } } else if (testCaseStep.getType() == 2L) { // 数据库接口处理 + boolean dateSourceTestResult = doDateSourceRequestTest(testCase, testCaseStep); + if (!dateSourceTestResult) { + log.error("数据源用例步骤:{}执行失败!", testCaseStep.getName()); + return false; + } } else if (testCaseStep.getType() == 3L) { // 循环节点处理 boolean pollTestResult = doPollRequestTest(testCase, testCaseStep, jmeterHomePath); @@ -216,6 +227,67 @@ public class TestCaseServiceImpl implements ITestCaseService return true; } + /** + * 处理数据源接口测试 + * @param testCase + * @param testCaseStep + * @return 成功或失败 + */ + private boolean doDateSourceRequestTest(TestCase testCase, TestCaseStep testCaseStep) { + try { + String assignment = testCaseStep.getAssignment(); // 参数提取 + String assertion = testCaseStep.getAssertion(); // 校验规则 + TestCaseResult testCaseResult = new TestCaseResult(); + testCaseResult.setExecuteTime(DateUtils.getNowDate()); + Long startTime = System.currentTimeMillis(); + TestDatasource testDatasource = testDatasourceMapper.selectTestDatasourceById(testCaseStep.getDatasourceId()); + Long useTime = System.currentTimeMillis() - startTime; + testCaseResult.setUseTime(useTime); + if (testDatasource == null) { + log.error("根据数据源id:{}无法查询到数据源信息", testCaseStep.getDatasourceId()); + return false; + } + String url = "jdbc:mysql://"+ testDatasource.getHost() +":"+ testDatasource.getPort() +"/" + testDatasource.getDbName(); + List columnNameList = new ArrayList<>(); + // 获取所有sql查询集合对象 + List> resultMapList = MySQLExecutor.executeQuery(testCaseStep.getSqlCommand(), url, testDatasource.getUsername(), testDatasource.getPassword(), columnNameList); + testCaseResult.setCaseId(testCase.getId()); + testCaseResult.setStepId(testCaseStep.getId()); + if (!CollectionUtils.isEmpty(resultMapList)) { + SqlResult sqlResult = new SqlResult(); + sqlResult.setColumnNameList(columnNameList); + sqlResult.setResultMapList(resultMapList); + Gson gson = new Gson(); + testCaseResult.setSqlResult(gson.toJson(sqlResult)); + // 处理参数提取 + Map assignmentResultMap = new HashMap<>(); + String assignmentResult = this.dealDataSourceTestCaseStepAssignment(resultMapList, assignmentResultMap, assignment); + testCaseResult.setAssignment(assignmentResult); + // 根据提取结果处理校验规则 + String assertionResult = this.dealTestCaseStepAssertion(assignmentResultMap, assertion); + testCaseResult.setAssertion(assertionResult); + if ("fail".equals(assignmentResultMap.get("assertionResult"))) { + testCaseResult.setStatus("失败"); + testCaseResultMapper.insertTestCaseResult(testCaseResult); + return false; + } else { + testCaseResult.setStatus("成功"); + testCaseResultMapper.insertTestCaseResult(testCaseResult); + } + } else { + testCaseResult.setAssignment(assignment); + testCaseResult.setAssertion(assertion); + testCaseResult.setStatus("失败"); + testCaseResultMapper.insertTestCaseResult(testCaseResult); + return false; + } + } catch (Exception e) { + log.error("数据源请求测试发生异常: ", e); + return false; + } + return true; + } + /** * 处理循环节点接口测试 * @param testCase @@ -253,6 +325,12 @@ public class TestCaseServiceImpl implements ITestCaseService } } else if (testCaseStepChild.getType() == 2L) { // 数据库接口处理 + boolean dateSourceTestResult = doDateSourceRequestTest(testCase, testCaseStepChild); + if (!dateSourceTestResult) { + log.error("子数据源用例步骤:{}执行失败!", testCaseStepChild.getName()); + pollResult = false; + break; + } } } if (!pollResult) { @@ -288,7 +366,7 @@ public class TestCaseServiceImpl implements ITestCaseService private boolean doLoopRequestTest(TestCase testCase, TestCaseStep testCaseStep, String jmeterHomePath) { try { // 先查出所有子节点测试步骤 - String breakError = testCaseStep.getBreakError(); +// String breakError = testCaseStep.getBreakError(); long interval = testCaseStep.getInterval() == null ? 0 : testCaseStep.getInterval();; long loopCountCount = testCaseStep.getCount(); TestCaseResult testCaseResult = new TestCaseResult(); @@ -324,6 +402,11 @@ public class TestCaseServiceImpl implements ITestCaseService } } else if (testCaseStepChild.getType() == 2L) { // 数据库接口处理 + boolean dateSourceTestResult = doDateSourceRequestTest(testCase, testCaseStepChild); + if (!dateSourceTestResult) { + log.error("子数据源用例步骤:{}执行失败!", testCaseStepChild.getName()); + break; + } } index ++; } @@ -398,6 +481,45 @@ public class TestCaseServiceImpl implements ITestCaseService } } + /** + * 处理数据源响应字段提取 + * @param resultMapList + * @param assignmentResultMap + * @param assignment + * @return 处理后的提取结果 + */ + private String dealDataSourceTestCaseStepAssignment(List> resultMapList, Map assignmentResultMap, String assignment) { + if (!StringUtils.isEmpty(assignment) && !"[]".equals(assignment)) { + Gson gson = new Gson(); + String responseBody = gson.toJson(resultMapList); + Type ruleListType = new TypeToken>() {}.getType(); + // 将 JSON 字符串解析为 List + List rules = gson.fromJson(assignment, ruleListType); + List ruleResultList = new ArrayList<>(); + for (ExtractionRule rule : rules) { + ExtractionRuleResult ruleResult = new ExtractionRuleResult(); + BeanUtils.copyProperties(rule, ruleResult); + String type = rule.getType(); + String content = rule.getContent(); + String path = rule.getPath(); + if ("${RESULT_DATA}".equals(content)) { + if (type.startsWith("JSON")) { + if (!path.startsWith("$.")) { + path = "$." + path; + } + String value = JMeterUtil.extractFieldValue(responseBody, path); + ruleResult.setValue(value); + } + } + assignmentResultMap.put(rule.getName(), ruleResult.getValue()); + ruleResultList.add(ruleResult); + } + return gson.toJson(ruleResultList); + } else { + return assignment; + } + } + /** * 校验测试用例步骤是否通过 * @param assignmentResultMap