diff --git a/test-common/pom.xml b/test-common/pom.xml index 147a906..281613a 100644 --- a/test-common/pom.xml +++ b/test-common/pom.xml @@ -52,13 +52,13 @@ org.apache.commons commons-lang3 - + com.fasterxml.jackson.core jackson-databind - + com.alibaba.fastjson2 @@ -119,6 +119,35 @@ jakarta.servlet-api + + + org.apache.jmeter + ApacheJMeter_core + 5.4.3 + + + org.apache.jmeter + ApacheJMeter_components + 5.4.3 + + + org.apache.jmeter + ApacheJMeter_http + 5.4.3 + + + junit + junit + 4.13.1 + test + + + com.google.code.gson + gson + 2.10.1 + + + - \ No newline at end of file + diff --git a/test-common/src/main/java/com/test/common/utils/JMeterUtil.java b/test-common/src/main/java/com/test/common/utils/JMeterUtil.java new file mode 100644 index 0000000..1d8bec9 --- /dev/null +++ b/test-common/src/main/java/com/test/common/utils/JMeterUtil.java @@ -0,0 +1,421 @@ +package com.test.common.utils; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import org.apache.jmeter.config.Arguments; +import org.apache.jmeter.config.gui.ArgumentsPanel; +import org.apache.jmeter.control.LoopController; +import org.apache.jmeter.control.gui.LoopControlPanel; +import org.apache.jmeter.control.gui.TestPlanGui; +import org.apache.jmeter.engine.StandardJMeterEngine; +import org.apache.jmeter.protocol.http.control.Header; +import org.apache.jmeter.protocol.http.control.HeaderManager; +import org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui; +import org.apache.jmeter.protocol.http.gui.HeaderPanel; +import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy; +import org.apache.jmeter.reporters.ResultCollector; +import org.apache.jmeter.reporters.Summariser; +import org.apache.jmeter.samplers.SampleSaveConfiguration; +import org.apache.jmeter.save.SaveService; +import org.apache.jmeter.testelement.TestElement; +import org.apache.jmeter.testelement.TestPlan; +import org.apache.jmeter.testelement.property.BooleanProperty; +import org.apache.jmeter.testelement.property.ObjectProperty; +import org.apache.jmeter.testelement.property.StringProperty; +import org.apache.jmeter.threads.ThreadGroup; +import org.apache.jmeter.threads.gui.ThreadGroupGui; +import org.apache.jmeter.util.JMeterUtils; +import org.apache.jorphan.collections.HashTree; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; +import java.io.FileOutputStream; +import java.lang.reflect.Type; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author liangdaliang + * @Description:JMeterter工具类 + * @date 2025-02-12 9:12 + */ +public class JMeterUtil { + + /** + * 生成jmeter测试执行计划并获取执行结果 + * @param id + * @param url + * @param port + * @param method + * @param paramJson + * @param requestHeader + * @param jmeterHomePath + * @return + */ + public static String getJmeterResult(Long id, String url, int port, String method, String paramJson, String requestHeader, String jmeterHomePath) { + String result = ""; + try { + // 1. 初始化 JMeter + JMeterUtils.loadJMeterProperties(jmeterHomePath + "/bin/jmeter.properties"); + JMeterUtils.setJMeterHome(jmeterHomePath); + JMeterUtils.initLocale(); + + // 2. 创建测试计划 + TestPlan testPlan = createTestPlan("Dynamic Test Plan"); + + // 3. 创建线程组 + ThreadGroup threadGroup = createThreadGroup(1, 1); + + // 4. 创建 HTTP 请求 + HTTPSamplerProxy httpSampler = null; + if ("POST".equals(method)) { + httpSampler = createPostHttpSampler( + url, // 请求地址 + port, + paramJson // 请求参数 + ); + } else { + httpSampler = createGetHttpSampler( + url, // 请求地址 + port, + paramJson // 请求参数 + ); + } + // 5. 创建请求头管理器 + Map headerMap = new HashMap<>(); + if (!StringUtils.isEmpty(requestHeader)) { + Gson gson = new Gson(); + // 定义 Map 的类型 + Type type = new TypeToken>() {}.getType(); + // 将 JSON 字符串转换为 Map + headerMap = gson.fromJson(requestHeader, type); + } + HeaderManager headerManager = createHeaderManager(headerMap); + + // 6. 获取结果:如汇总报告、查看结果树 + String replayLogPath = jmeterHomePath + "/replay_result"+ id +".log"; + List resultCollector = getResultCollector(replayLogPath); + + // 7. 构建测试树 + HashTree testPlanTree = new HashTree(); + HashTree threadGroupTree = testPlanTree.add(testPlan); + threadGroupTree.add(threadGroup); + threadGroupTree.add(httpSampler); + threadGroupTree.add(headerManager); + threadGroupTree.add(resultCollector); + + // 8. 保存测试计划为 JMX 文件 + File jmxFile = new File(jmeterHomePath + "/dynamic_test_plan"+ id +".jmx"); + SaveService.saveTree(testPlanTree, new FileOutputStream(jmxFile)); + + // 9. 运行 JMeter 测试 + File resultFile = new File(jmeterHomePath + "/replay_result"+ id +".log"); + if (resultFile.exists()) { + resultFile.delete(); + } + StandardJMeterEngine jmeter = new StandardJMeterEngine(); + jmeter.configure(testPlanTree); + jmeter.run(); + while (jmeter.isActive()) { + System.out.println("JMeter isActive!"); + Thread.sleep(1000); // 每隔 1 秒检查一次 + } + // 10. 获取响应结果 + result = getResultMessageFromFile(jmeterHomePath + "/replay_result"+ id +".log"); + + System.out.println("JMeter 测试执行完成!"); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 创建测试计划 + * @param name + * @return + */ + private static TestPlan createTestPlan(String name) { + TestPlan testPlan = new TestPlan(name); + testPlan.setProperty(TestElement.TEST_CLASS, TestPlan.class.getName()); + testPlan.setProperty(TestElement.GUI_CLASS, TestPlanGui.class.getName()); + testPlan.setUserDefinedVariables((Arguments) new ArgumentsPanel().createTestElement()); + return testPlan; + } + + /** + * 创建线程组 + * @param numThreads + * @param loops + * @return + */ + private static ThreadGroup createThreadGroup(int numThreads, int loops) { + ThreadGroup threadGroup = new ThreadGroup(); + threadGroup.setName("Thread Group"); + threadGroup.setNumThreads(numThreads); + threadGroup.setRampUp(1); + threadGroup.setSamplerController(createLoopController(loops)); + threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName()); + threadGroup.setProperty(TestElement.GUI_CLASS, ThreadGroupGui.class.getName()); + return threadGroup; + } + + /** + * 创建轮询控制器 + * @param loops + * @return + */ + private static LoopController createLoopController(int loops) { + LoopController loopController = new LoopController(); + loopController.setLoops(loops); + loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName()); + loopController.setProperty(TestElement.GUI_CLASS, LoopControlPanel.class.getName()); + loopController.initialize(); + return loopController; + } + + /** + * 创建get请求方式 + * @param urlString + * @param port + * @param requestJson + * @return + * @throws MalformedURLException + */ + private static HTTPSamplerProxy createGetHttpSampler(String urlString, int port, String requestJson) throws MalformedURLException { + URL url = new URL(urlString); + // 提取域名(不包括端口号) + String domain = url.getHost(); + // 提取路径(不包括查询参数和片段标识符) + String path = url.getPath(); + HTTPSamplerProxy httpSampler = new HTTPSamplerProxy(); + httpSampler.setName("HTTP Request Test"); + httpSampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName()); + httpSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName()); + httpSampler.setDomain(domain); // 提取域名 + httpSampler.setPath(path); // 提取路径 + httpSampler.setPort(port); + httpSampler.setMethod("GET"); + httpSampler.setConnectTimeout("5000"); + httpSampler.setUseKeepAlive(true); + + // 添加请求参数 + Map parameters = new HashMap<>(); + if (!StringUtils.isEmpty(requestJson)) { + Gson gson = new Gson(); + // 定义 Map 的类型 + Type type = new TypeToken>() {}.getType(); + // 将 JSON 字符串转换为 Map + parameters = gson.fromJson(requestJson, type); + path += "?"; + path += mapToQueryString(parameters); + httpSampler.setPath(path); // 提取路径 + } + + return httpSampler; + } + + /** + * 构建get请求查询参数 + * @param params + * @return + */ + public static String mapToQueryString(Map params) { + StringBuilder queryString = new StringBuilder(); + for (Map.Entry entry : params.entrySet()) { + if (!queryString.isEmpty()) { + queryString.append("&"); + } + // 对键和值进行 URL 编码 + String encodedKey = URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8); + String encodedValue = URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8); + queryString.append(encodedKey).append("=").append(encodedValue); + } + return queryString.toString(); + } + + /** + * 创建post请求方式 + * @param urlString + * @param port + * @param requestJson + * @return + * @throws MalformedURLException + */ + private static HTTPSamplerProxy createPostHttpSampler(String urlString, int port, String requestJson) throws MalformedURLException { + URL url = new URL(urlString); + // 提取域名(不包括端口号) + String domain = url.getHost(); + // 提取路径(不包括查询参数和片段标识符) + String path = url.getPath(); +// int portTest = url.getPort(); + HTTPSamplerProxy httpSampler = new HTTPSamplerProxy(); + httpSampler.setName("POST JSON Request"); + httpSampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName()); + httpSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName()); + httpSampler.setDomain(domain); + httpSampler.setPath(path); + httpSampler.setPort(port); + httpSampler.setMethod("POST"); + httpSampler.setConnectTimeout("5000"); + httpSampler.setUseKeepAlive(true); + + // 设置请求头为 JSON + httpSampler.setPostBodyRaw(true); // 使用原始请求体 + httpSampler.addNonEncodedArgument("", requestJson, ""); + + return httpSampler; + } + + /** + * 创建http请求头管理器 + * @param headerMap + * @return + */ + private static HeaderManager createHeaderManager(Map headerMap) { + HeaderManager headerManager = new HeaderManager(); + headerManager.setName("HTTP Header Manager"); + headerManager.setProperty(TestElement.TEST_CLASS, HeaderManager.class.getName()); + headerManager.setProperty(TestElement.GUI_CLASS, HeaderPanel.class.getName()); + + // 添加默认 Content-Type 请求头 + if (!headerMap.containsKey("Content-Type")) { + Header contentTypeHeader = new Header(); + contentTypeHeader.setName("Content-Type"); + contentTypeHeader.setValue("application/json; charset=UTF-8"); + headerManager.add(contentTypeHeader); + } + + // 遍历 headerMap,动态添加请求头 + for (Map.Entry entry : headerMap.entrySet()) { + Header header = new Header(); + header.setName(entry.getKey()); // 请求头名称 + header.setValue(entry.getValue()); // 请求头值 + headerManager.add(header); + } + + return headerManager; + } + + /*** + * 监听结果树 + * @param replayLogPath 将结果保存到文件中,这个是文件的路径 + * @return + */ + private static List getResultCollector(String replayLogPath) { + // 察看结果数 + List resultCollectors = new ArrayList<>(); + Summariser summariser = new Summariser("速度"); + ResultCollector resultCollector = new ResultCollector(summariser); + resultCollector.setProperty(new BooleanProperty("ResultCollector.error_logging", false)); + resultCollector.setProperty(new ObjectProperty("saveConfig", getSampleSaveConfig())); + resultCollector.setProperty(new StringProperty("TestElement.gui_class", "org.apache.jmeter.visualizers.ViewResultsFullVisualizer")); + resultCollector.setProperty(new StringProperty("TestElement.name", "察看结果树")); + resultCollector.setProperty(new StringProperty("TestElement.enabled", "true")); + resultCollector.setProperty(new StringProperty("filename", replayLogPath)); + resultCollectors.add(resultCollector); + + // 结果汇总 +// ResultCollector resultTotalCollector = new ResultCollector(); +// resultTotalCollector.setProperty(new BooleanProperty("ResultCollector.error_logging", false)); +// resultTotalCollector.setProperty(new ObjectProperty("saveConfig", getSampleSaveConfig())); +// resultTotalCollector.setProperty(new StringProperty("TestElement.gui_class", "org.apache.jmeter.visualizers.SummaryReport")); +// resultTotalCollector.setProperty(new StringProperty("TestElement.name", "汇总报告")); +// resultTotalCollector.setProperty(new StringProperty("TestElement.enabled", "true")); +// resultTotalCollector.setProperty(new StringProperty("filename", "")); +// resultCollectors.add(resultTotalCollector); + + return resultCollectors; + } + + /** + * 配置采样结果信息 + * @return + */ + private static SampleSaveConfiguration getSampleSaveConfig() { + SampleSaveConfiguration sampleSaveConfiguration = new SampleSaveConfiguration(); + sampleSaveConfiguration.setTime(true); + sampleSaveConfiguration.setLatency(true); + sampleSaveConfiguration.setTimestamp(true); + sampleSaveConfiguration.setSuccess(true); + sampleSaveConfiguration.setLabel(true); + sampleSaveConfiguration.setCode(true); + sampleSaveConfiguration.setMessage(true); + sampleSaveConfiguration.setThreadName(true); + sampleSaveConfiguration.setDataType(true); + sampleSaveConfiguration.setEncoding(true); + sampleSaveConfiguration.setAssertions(true); + sampleSaveConfiguration.setSubresults(true); + sampleSaveConfiguration.setResponseData(true); + sampleSaveConfiguration.setSamplerData(true); + sampleSaveConfiguration.setAsXml(true); + sampleSaveConfiguration.setFieldNames(true); + sampleSaveConfiguration.setResponseHeaders(true); + sampleSaveConfiguration.setRequestHeaders(false); + sampleSaveConfiguration.setAssertionResultsFailureMessage(true); + //sampleSaveConfiguration.setsserAtionsResultsToSave(0); assertionsResultsToSave + sampleSaveConfiguration.setBytes(true); + sampleSaveConfiguration.setSentBytes(true); + sampleSaveConfiguration.setUrl(true); + sampleSaveConfiguration.setThreadCounts(true); + sampleSaveConfiguration.setIdleTime(true); + sampleSaveConfiguration.setConnectTime(true); + return sampleSaveConfiguration; + } + + /** + * 从结果文件读取响应内容 + * @param filePath + * @return + */ + private static String getResultMessageFromFile(String filePath) { + File file = new File(filePath); + if (!file.exists()) { + return null; + } + try { + // 1. 创建DocumentBuilderFactory对象 + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + // 2. 创建DocumentBuilder对象 + DocumentBuilder builder = factory.newDocumentBuilder(); + // 3. 解析XML文件,获取Document对象 + Document document = builder.parse(new File(filePath)); + // 4. 获取所有节点 + NodeList httpSampleList = document.getElementsByTagName("httpSample"); + Node httpSampleNode = httpSampleList.item(0); + if (httpSampleNode.getNodeType() == Node.ELEMENT_NODE) { + Element httpSampleElement = (Element) httpSampleNode; + // 提取子节点的内容 + NodeList responseDataList = httpSampleElement.getElementsByTagName("responseData"); + if (responseDataList.getLength() > 0) { + Element responseDataElement = (Element) responseDataList.item(0); + return responseDataElement.getTextContent(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static void main(String[] args) { + String paramJson = "{\"md5Value\":\"value1\",\"fileName\":\"value2\"}"; + paramJson = "{\"name\":\"John\",\"city\":\"New York\",\"age\":30}"; + String requestHeader = "{\"Content-Type\":\"application/json; charset=UTF-8\",\"Authorization\":\"Bearer token123\"}"; + String jmeterHomePath = "D:/apache-jmeter-5.4.3"; +// String result = getJmeterResult("http://127.0.0.1:3000/api/items/add", 3000, "POST", paramJson, requestHeader, jmeterHomePath); + String result = getJmeterResult(123L, "http://127.0.0.1:3000/api/items/user", 3000, "GET", paramJson, requestHeader, jmeterHomePath); + System.out.println(result); + } +} diff --git a/test-test/src/main/java/com/test/test/domain/TestCaseStep.java b/test-test/src/main/java/com/test/test/domain/TestCaseStep.java new file mode 100644 index 0000000..10ba209 --- /dev/null +++ b/test-test/src/main/java/com/test/test/domain/TestCaseStep.java @@ -0,0 +1,131 @@ +package com.test.test.domain; + +import com.test.common.core.domain.BaseEntity; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import com.test.common.annotation.Excel; + +/** + * 用例步骤对象 test_case_step + * + * @author liangdl + * @date 2025-02-11 + */ +@Setter +@Getter +@ToString +public class TestCaseStep extends BaseEntity { + + private static final long serialVersionUID = 1L; + + /** 步骤id */ + private Long id; + + /** 父节点id */ + @Excel(name = "父节点id") + private Long parentId; + + /** 用例id */ + @Excel(name = "用例id") + private Long caseId; + + /** 步骤名 */ + @Excel(name = "步骤名") + private String name; + + /** 执行顺序 */ + @Excel(name = "执行顺序") + private Long stepNum; + + /** 步骤类型(http接口:1,数据源:2,循环:3,轮询:4) */ + @Excel(name = "步骤类型", readConverterExp = "h=ttp接口:1,数据源:2,循环:3,轮询:4") + private Long type; + + /** http 请求方法(get or post) */ + @Excel(name = "http 请求方法(get or post)") + private String requestMethod; + + /** http 请求路径 */ + @Excel(name = "http 请求路径") + private String requestUrl; + + /** http 请求体 */ + @Excel(name = "http 请求体") + private String requestBody; + + /** http 请求头 */ + @Excel(name = "http 请求头") + private String requestHeader; + + /** http 查询参数 */ + @Excel(name = "http 查询参数") + private String requestParams; + + /** http 关联服务id */ + @Excel(name = "http 关联服务id") + private Long apiHttpId; + + /** http 请求主机 */ + @Excel(name = "http 请求主机") + private String apiHost; + + /** http 请求端口号 */ + @Excel(name = "http 请求端口号") + private String apiPort; + + /** http 请求协议(http, https) */ + @Excel(name = "http 请求协议(http, https)") + private String apiProtocol; + + /** sql 命令 */ + @Excel(name = "sql 命令") + private String sqlCommand; + + /** 循环次数 */ + @Excel(name = "循环次数") + private Long count; + + /** 循环并行开关 */ + @Excel(name = "循环并行开关") + private Integer async; + + /** 轮询间隔 */ + @Excel(name = "轮询间隔") + private Long interval; + + /** 轮询失败判定条件选择 */ + @Excel(name = "轮询失败判定条件选择") + private String breakError; + + /** 请求预处理 */ + @Excel(name = "请求预处理") + private String preScript; + + /** 响应预处理 */ + @Excel(name = "响应预处理") + private String postScript; + + /** 参数提取 + [{ + "name": "变量名", + "type": "提取方式", + "content": "提取对象", + "path": "提取表达式", + }] */ + @Excel(name = "参数提取") + private String assignment; + + /** 校验规则 + [{ + "name": "描述", + "source": "对象", + "fn": "条件", + "target": "内容" + }] */ + @Excel(name = "校验规则") + private String assertion; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; +} diff --git a/test-test/src/main/java/com/test/test/mapper/TestCaseStepMapper.java b/test-test/src/main/java/com/test/test/mapper/TestCaseStepMapper.java new file mode 100644 index 0000000..44525c7 --- /dev/null +++ b/test-test/src/main/java/com/test/test/mapper/TestCaseStepMapper.java @@ -0,0 +1,61 @@ +package com.test.test.mapper; + +import java.util.List; +import com.test.test.domain.TestCaseStep; + +/** + * 用例步骤Mapper接口 + * + * @author liangdl + * @date 2025-02-11 + */ +public interface TestCaseStepMapper +{ + /** + * 查询用例步骤 + * + * @param id 用例步骤主键 + * @return 用例步骤 + */ + public TestCaseStep selectTestCaseStepById(Long id); + + /** + * 查询用例步骤列表 + * + * @param testCaseStep 用例步骤 + * @return 用例步骤集合 + */ + public List selectTestCaseStepList(TestCaseStep testCaseStep); + + /** + * 新增用例步骤 + * + * @param testCaseStep 用例步骤 + * @return 结果 + */ + public int insertTestCaseStep(TestCaseStep testCaseStep); + + /** + * 修改用例步骤 + * + * @param testCaseStep 用例步骤 + * @return 结果 + */ + public int updateTestCaseStep(TestCaseStep testCaseStep); + + /** + * 删除用例步骤 + * + * @param id 用例步骤主键 + * @return 结果 + */ + public int deleteTestCaseStepById(Long id); + + /** + * 批量删除用例步骤 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteTestCaseStepByIds(Long[] ids); +} diff --git a/test-test/src/main/java/com/test/test/service/ITestCaseStepService.java b/test-test/src/main/java/com/test/test/service/ITestCaseStepService.java new file mode 100644 index 0000000..a6da036 --- /dev/null +++ b/test-test/src/main/java/com/test/test/service/ITestCaseStepService.java @@ -0,0 +1,71 @@ +package com.test.test.service; + +import com.test.test.domain.TestCaseStep; + +import java.util.List; + +/** + * 用例步骤Service接口 + * + * @author liangdl + * @date 2025-02-11 + */ +public interface ITestCaseStepService +{ + /** + * 查询用例步骤 + * + * @param id 用例步骤主键 + * @return 用例步骤 + */ + public TestCaseStep selectTestCaseStepById(Long id); + + /** + * 查询用例步骤列表 + * + * @param testCaseStep 用例步骤 + * @return 用例步骤集合 + */ + public List selectTestCaseStepList(TestCaseStep testCaseStep); + + /** + * 新增用例步骤 + * + * @param testCaseStep 用例步骤 + * @return 结果 + */ + public int insertTestCaseStep(TestCaseStep testCaseStep); + + /** + * 修改用例步骤 + * + * @param testCaseStep 用例步骤 + * @return 结果 + */ + public int updateTestCaseStep(TestCaseStep testCaseStep); + + /** + * 批量删除用例步骤 + * + * @param ids 需要删除的用例步骤主键集合 + * @return 结果 + */ + public int deleteTestCaseStepByIds(Long[] ids); + + /** + * 删除用例步骤信息 + * + * @param id 用例步骤主键 + * @return 结果 + */ + public int deleteTestCaseStepById(Long id); + + /** + * 执行jmeter用例步骤计划 + * + * @param id 用例步骤主键 + * @param jmeterHomePath jmeter安装路径 + * @return 结果 + */ + public String executeJmeterTestCaseStepById(Long id, String jmeterHomePath); +} diff --git a/test-test/src/main/java/com/test/test/service/impl/TestCaseStepServiceImpl.java b/test-test/src/main/java/com/test/test/service/impl/TestCaseStepServiceImpl.java new file mode 100644 index 0000000..94eacb9 --- /dev/null +++ b/test-test/src/main/java/com/test/test/service/impl/TestCaseStepServiceImpl.java @@ -0,0 +1,128 @@ +package com.test.test.service.impl; + +import com.test.common.utils.DateUtils; +import com.test.common.utils.JMeterUtil; +import com.test.test.domain.TestCaseStep; +import com.test.test.mapper.TestCaseStepMapper; +import com.test.test.service.ITestCaseStepService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 用例步骤Service业务层处理 + * + * @author test + * @date 2025-02-11 + */ +@Slf4j +@Service +public class TestCaseStepServiceImpl implements ITestCaseStepService +{ + @Resource + private TestCaseStepMapper testCaseStepMapper; + + /** + * 查询用例步骤 + * + * @param id 用例步骤主键 + * @return 用例步骤 + */ + @Override + public TestCaseStep selectTestCaseStepById(Long id) + { + return testCaseStepMapper.selectTestCaseStepById(id); + } + + /** + * 查询用例步骤列表 + * + * @param testCaseStep 用例步骤 + * @return 用例步骤 + */ + @Override + public List selectTestCaseStepList(TestCaseStep testCaseStep) + { + return testCaseStepMapper.selectTestCaseStepList(testCaseStep); + } + + /** + * 新增用例步骤 + * + * @param testCaseStep 用例步骤 + * @return 结果 + */ + @Override + public int insertTestCaseStep(TestCaseStep testCaseStep) + { + testCaseStep.setCreateTime(DateUtils.getNowDate()); + return testCaseStepMapper.insertTestCaseStep(testCaseStep); + } + + /** + * 修改用例步骤 + * + * @param testCaseStep 用例步骤 + * @return 结果 + */ + @Override + public int updateTestCaseStep(TestCaseStep testCaseStep) + { + testCaseStep.setUpdateTime(DateUtils.getNowDate()); + return testCaseStepMapper.updateTestCaseStep(testCaseStep); + } + + /** + * 批量删除用例步骤 + * + * @param ids 需要删除的用例步骤主键 + * @return 结果 + */ + @Override + public int deleteTestCaseStepByIds(Long[] ids) + { + return testCaseStepMapper.deleteTestCaseStepByIds(ids); + } + + /** + * 删除用例步骤信息 + * + * @param id 用例步骤主键 + * @return 结果 + */ + @Override + public int deleteTestCaseStepById(Long id) + { + return testCaseStepMapper.deleteTestCaseStepById(id); + } + + /** + * 执行jmeter用例步骤计划 + * + * @param id 用例步骤主键 + * @param jmeterHomePath jmeter安装路径 + * @return 结果 + */ + @Override + public String executeJmeterTestCaseStepById(Long id, String jmeterHomePath) { + TestCaseStep testCaseStep = testCaseStepMapper.selectTestCaseStepById(id); + if (testCaseStep == null) { + log.error("根据主键id:{}未查询到用例步骤计划", id); + return null; + } + String result = null; + String url = testCaseStep.getRequestUrl(); + String method = testCaseStep.getRequestMethod().toUpperCase(); + if (!method.equals("GET") && !method.equals("POST")) { + log.error("不支持的请求方式:{}", method); + return null; + } + String requestHeader = testCaseStep.getRequestHeader(); + result = JMeterUtil.getJmeterResult(id, url, Integer.parseInt(testCaseStep.getApiPort()), testCaseStep.getRequestMethod(), testCaseStep.getRequestParams(), requestHeader, jmeterHomePath); + + return result; + } + +} diff --git a/test-test/src/main/resources/mapper/test/TestCaseStepMapper.xml b/test-test/src/main/resources/mapper/test/TestCaseStepMapper.xml new file mode 100644 index 0000000..328ea3f --- /dev/null +++ b/test-test/src/main/resources/mapper/test/TestCaseStepMapper.xml @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select id, parent_id, case_id, name, step_num, type, request_method, request_url, request_body, request_header, request_params, api_http_id, api_host, api_port, api_protocol, sql_command, count, async, interval, break_error, pre_script, post_script, assignment, assertion, del_flag, create_by, create_time, update_by, update_time from test_case_step + + + + + + + + insert into test_case_step + + parent_id, + case_id, + name, + step_num, + type, + request_method, + request_url, + request_body, + request_header, + request_params, + api_http_id, + api_host, + api_port, + api_protocol, + sql_command, + count, + async, + interval, + break_error, + pre_script, + post_script, + assignment, + assertion, + del_flag, + create_by, + create_time, + update_by, + update_time, + + + #{parentId}, + #{caseId}, + #{name}, + #{stepNum}, + #{type}, + #{requestMethod}, + #{requestUrl}, + #{requestBody}, + #{requestHeader}, + #{requestParams}, + #{apiHttpId}, + #{apiHost}, + #{apiPort}, + #{apiProtocol}, + #{sqlCommand}, + #{count}, + #{async}, + #{interval}, + #{breakError}, + #{preScript}, + #{postScript}, + #{assignment}, + #{assertion}, + #{delFlag}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + + + + + update test_case_step + + parent_id = #{parentId}, + case_id = #{caseId}, + name = #{name}, + step_num = #{stepNum}, + type = #{type}, + request_method = #{requestMethod}, + request_url = #{requestUrl}, + request_body = #{requestBody}, + request_header = #{requestHeader}, + request_params = #{requestParams}, + api_http_id = #{apiHttpId}, + api_host = #{apiHost}, + api_port = #{apiPort}, + api_protocol = #{apiProtocol}, + sql_command = #{sqlCommand}, + count = #{count}, + async = #{async}, + interval = #{interval}, + break_error = #{breakError}, + pre_script = #{preScript}, + post_script = #{postScript}, + assignment = #{assignment}, + assertion = #{assertion}, + del_flag = #{delFlag}, + create_by = #{createBy}, + create_time = #{createTime}, + update_by = #{updateBy}, + update_time = #{updateTime}, + + where id = #{id} + + + + delete from test_case_step where id = #{id} + + + + delete from test_case_step where id in + + #{id} + + +