diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/ApiExecuteResourceType.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/ApiExecuteResourceType.java index 0997596e07..522f5f838a 100644 --- a/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/ApiExecuteResourceType.java +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/constants/ApiExecuteResourceType.java @@ -6,6 +6,5 @@ package io.metersphere.sdk.constants; * @CreateTime: 2023-12-08 10:53 */ public enum ApiExecuteResourceType { - API_DEBUG, API, API_CASE, API_SCENARIO - // todo plan api + API_DEBUG, API, API_CASE, API_SCENARIO, TEST_PLAN_API_CASE, TEST_PLAN_API_SCENARIO } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/invoker/GetRunScriptServiceRegister.java b/backend/services/api-test/src/main/java/io/metersphere/api/invoker/GetRunScriptServiceRegister.java new file mode 100644 index 0000000000..f39cf55e58 --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/invoker/GetRunScriptServiceRegister.java @@ -0,0 +1,25 @@ +package io.metersphere.api.invoker; + +import io.metersphere.api.service.GetRunScriptService; +import io.metersphere.sdk.constants.ApiExecuteResourceType; + +import java.util.HashMap; +import java.util.Map; + +/** + * @Author: jianxing + * @CreateTime: 2024-02-06 20:48 + */ +public class GetRunScriptServiceRegister { + + private static final Map getRunScriptServiceMap = new HashMap<>(); + + + public static void register(ApiExecuteResourceType apiExecuteResourceType, GetRunScriptService getRunScriptService) { + getRunScriptServiceMap.put(apiExecuteResourceType, getRunScriptService); + } + + public static GetRunScriptService getRunScriptService(ApiExecuteResourceType apiExecuteResourceType) { + return getRunScriptServiceMap.get(apiExecuteResourceType); + } +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/listener/MessageListener.java b/backend/services/api-test/src/main/java/io/metersphere/api/listener/MessageListener.java index 618e295c21..a4923d5555 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/listener/MessageListener.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/listener/MessageListener.java @@ -57,10 +57,10 @@ public class MessageListener { } else { ApiExecuteResourceType resourceType = EnumValidator.validateEnum(ApiExecuteResourceType.class, dto.getResourceType()); boolean isStop = switch (resourceType) { - case API_CASE -> + case API_CASE, TEST_PLAN_API_CASE -> StringUtils.equals(apiReportMapper.selectByPrimaryKey(dto.getReportId()).getExecStatus(), ExecStatus.STOPPED.name()) && deleteQueue(dto.getQueueId()); - case API_SCENARIO -> + case API_SCENARIO, TEST_PLAN_API_SCENARIO -> StringUtils.equals(apiScenarioReportMapper.selectByPrimaryKey(dto.getReportId()).getExecStatus(), ExecStatus.STOPPED.name()) && deleteQueue(dto.getQueueId()); default -> false; diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiExecuteResourceService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiExecuteResourceService.java index 0c8d93b784..1355348819 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiExecuteResourceService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiExecuteResourceService.java @@ -1,9 +1,8 @@ package io.metersphere.api.service; +import io.metersphere.api.invoker.GetRunScriptServiceRegister; import io.metersphere.api.service.definition.ApiReportService; -import io.metersphere.api.service.definition.ApiTestCaseService; import io.metersphere.api.service.scenario.ApiScenarioReportService; -import io.metersphere.api.service.scenario.ApiScenarioRunService; import io.metersphere.sdk.constants.ApiExecuteResourceType; import io.metersphere.sdk.constants.ExecStatus; import io.metersphere.sdk.dto.api.task.GetRunScriptRequest; @@ -31,10 +30,6 @@ public class ApiExecuteResourceService { @Resource private ApiScenarioReportService apiScenarioReportService; @Resource - private ApiScenarioRunService apiScenarioRunService; - @Resource - private ApiTestCaseService apiTestCaseService; - @Resource private StringRedisTemplate stringRedisTemplate; @@ -45,17 +40,17 @@ public class ApiExecuteResourceService { LogUtils.info("生成并获取执行脚本: {}", key); ApiExecuteResourceType apiExecuteResourceType = EnumValidator.validateEnum(ApiExecuteResourceType.class, request.getResourceType()); + switch (apiExecuteResourceType) { - case API_SCENARIO -> { - apiScenarioReportService.updateReportStatus(reportId, ExecStatus.RUNNING.name()); - return apiScenarioRunService.getRunScript(request); - } - case API_CASE -> { - apiReportService.updateReportStatus(reportId, ExecStatus.RUNNING.name()); - return apiTestCaseService.getRunScript(request); - } + case API_SCENARIO, TEST_PLAN_API_SCENARIO -> + apiScenarioReportService.updateReportStatus(reportId, ExecStatus.RUNNING.name()); + case API_CASE, TEST_PLAN_API_CASE -> + apiReportService.updateReportStatus(reportId, ExecStatus.RUNNING.name()); default -> throw new MSException("不支持的资源类型: " + request.getResourceType()); } + + GetRunScriptService getRunScriptService = GetRunScriptServiceRegister.getRunScriptService(apiExecuteResourceType); + return getRunScriptService.getRunScript(request); } public String getRunScript(String reportId, String testId) { diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/GetRunScriptService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/GetRunScriptService.java new file mode 100644 index 0000000000..37c5477eb0 --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/GetRunScriptService.java @@ -0,0 +1,15 @@ +package io.metersphere.api.service; + +import io.metersphere.sdk.dto.api.task.GetRunScriptRequest; +import io.metersphere.sdk.dto.api.task.GetRunScriptResult; + +/** + * @Author: jianxing + * @CreateTime: 2024-02-06 20:47 + */ +public interface GetRunScriptService { + /** + * 解析并返回执行脚本 + */ + GetRunScriptResult getRunScript(GetRunScriptRequest request); +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java index 8ace5250eb..afada81e2a 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java @@ -7,10 +7,12 @@ import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest; import io.metersphere.api.dto.debug.ApiResourceRunRequest; import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.request.ApiTransferRequest; +import io.metersphere.api.invoker.GetRunScriptServiceRegister; import io.metersphere.api.mapper.*; import io.metersphere.api.service.ApiCommonService; import io.metersphere.api.service.ApiExecuteService; import io.metersphere.api.service.ApiFileResourceService; +import io.metersphere.api.service.GetRunScriptService; import io.metersphere.api.utils.ApiDataUtils; import io.metersphere.functional.domain.FunctionalCaseTestExample; import io.metersphere.functional.mapper.FunctionalCaseTestMapper; @@ -59,7 +61,7 @@ import java.util.stream.Stream; @Service @Transactional(rollbackFor = Exception.class) -public class ApiTestCaseService extends MoveNodeService { +public class ApiTestCaseService extends MoveNodeService implements GetRunScriptService { public static final String PRIORITY = "Priority"; public static final String STATUS = "Status"; @@ -108,6 +110,10 @@ public class ApiTestCaseService extends MoveNodeService { @Resource private FunctionalCaseTestMapper functionalCaseTestMapper; + public ApiTestCaseService() { + GetRunScriptServiceRegister.register(ApiExecuteResourceType.API_CASE, this); + } + private static final String CASE_TABLE = "api_test_case"; private static final int MAX_TAG_SIZE = 10; @@ -204,7 +210,7 @@ public class ApiTestCaseService extends MoveNodeService { return requestStr; } - private ApiTestCase checkResourceExist(String id) { + public ApiTestCase checkResourceExist(String id) { ApiTestCase testCase = apiTestCaseMapper.selectByPrimaryKey(id); if (testCase == null) { throw new MSException(Translator.get("api_test_case_not_exist")); @@ -736,7 +742,7 @@ public class ApiTestCaseService extends MoveNodeService { return doExecute(taskRequest, runRequest, request.getApiDefinitionId(), request.getEnvironmentId()); } - private TaskRequestDTO doExecute(TaskRequestDTO taskRequest, ApiResourceRunRequest runRequest, String apiDefinitionId, String envId) { + public TaskRequestDTO doExecute(TaskRequestDTO taskRequest, ApiResourceRunRequest runRequest, String apiDefinitionId, String envId) { ApiParamConfig apiParamConfig = apiExecuteService.getApiParamConfig(taskRequest.getTaskItem().getReportId(), taskRequest.getTaskInfo().getProjectId()); @@ -753,11 +759,16 @@ public class ApiTestCaseService extends MoveNodeService { /** * 获取执行脚本 */ + @Override public GetRunScriptResult getRunScript(GetRunScriptRequest request) { + ApiTestCase apiTestCase = apiTestCaseMapper.selectByPrimaryKey(request.getTaskItem().getResourceId()); + return getRunScript(request, apiTestCase); + } + + public GetRunScriptResult getRunScript(GetRunScriptRequest request, ApiTestCase apiTestCase) { TaskItem taskItem = request.getTaskItem(); - ApiTestCase apiTestCase = apiTestCaseMapper.selectByPrimaryKey(taskItem.getResourceId()); ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(apiTestCase.getApiDefinitionId()); - ApiTestCaseBlob apiTestCaseBlob = apiTestCaseBlobMapper.selectByPrimaryKey(taskItem.getResourceId()); + ApiTestCaseBlob apiTestCaseBlob = apiTestCaseBlobMapper.selectByPrimaryKey(apiTestCase.getId()); ApiParamConfig apiParamConfig = apiExecuteService.getApiParamConfig(taskItem.getReportId(), apiTestCase.getProjectId()); AbstractMsTestElement msTestElement = ApiDataUtils.parseObject(new String(apiTestCaseBlob.getRequest()), AbstractMsTestElement.class); @@ -804,14 +815,7 @@ public class ApiTestCaseService extends MoveNodeService { public ApiTestCaseRecord initApiReport(ApiTestCase apiTestCase, String reportId, String poolId, String userId) { // 初始化报告 - ApiReport apiReport = getApiReport(userId); - apiReport.setId(reportId); - apiReport.setTriggerMode(TaskTriggerMode.MANUAL.name()); - apiReport.setName(apiTestCase.getName() + "_" + DateUtils.getTimeString(System.currentTimeMillis())); - apiReport.setRunMode(ApiBatchRunMode.PARALLEL.name()); - apiReport.setPoolId(poolId); - apiReport.setEnvironmentId(apiTestCase.getEnvironmentId()); - apiReport.setProjectId(apiTestCase.getProjectId()); + ApiReport apiReport = getApiReport(apiTestCase, reportId, poolId, userId); // 创建报告和用例的关联关系 ApiTestCaseRecord apiTestCaseRecord = getApiTestCaseRecord(apiTestCase, apiReport); @@ -822,7 +826,19 @@ public class ApiTestCaseService extends MoveNodeService { return apiTestCaseRecord; } - private ApiReportStep getApiReportStep(ApiTestCase apiTestCase, String reportId, long sort) { + public ApiReport getApiReport(ApiTestCase apiTestCase, String reportId, String poolId, String userId) { + ApiReport apiReport = getApiReport(userId); + apiReport.setId(reportId); + apiReport.setTriggerMode(TaskTriggerMode.MANUAL.name()); + apiReport.setName(apiTestCase.getName() + "_" + DateUtils.getTimeString(System.currentTimeMillis())); + apiReport.setRunMode(ApiBatchRunMode.PARALLEL.name()); + apiReport.setPoolId(poolId); + apiReport.setEnvironmentId(apiTestCase.getEnvironmentId()); + apiReport.setProjectId(apiTestCase.getProjectId()); + return apiReport; + } + + public ApiReportStep getApiReportStep(ApiTestCase apiTestCase, String reportId, long sort) { ApiReportStep apiReportStep = new ApiReportStep(); apiReportStep.setReportId(reportId); apiReportStep.setStepId(apiTestCase.getId()); @@ -862,7 +878,7 @@ public class ApiTestCaseService extends MoveNodeService { public TaskInfo getTaskInfo(String projectId, String runModule) { TaskInfo taskInfo = apiExecuteService.getTaskInfo(projectId); - taskInfo.setResourceType(ApiResourceType.API_CASE.name()); + taskInfo.setResourceType(ApiExecuteResourceType.API_CASE.name()); taskInfo.setRunMode(runModule); taskInfo.setNeedParseScript(false); return taskInfo; diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioRunService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioRunService.java index 80c8653cbd..a3c34baf31 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioRunService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioRunService.java @@ -10,6 +10,7 @@ import io.metersphere.api.dto.request.MsScenario; import io.metersphere.api.dto.request.controller.MsScriptElement; import io.metersphere.api.dto.request.http.MsHTTPElement; import io.metersphere.api.dto.scenario.*; +import io.metersphere.api.invoker.GetRunScriptServiceRegister; import io.metersphere.api.mapper.ApiScenarioBlobMapper; import io.metersphere.api.mapper.ApiScenarioMapper; import io.metersphere.api.mapper.ApiScenarioReportMapper; @@ -17,6 +18,7 @@ import io.metersphere.api.parser.step.StepParser; import io.metersphere.api.parser.step.StepParserFactory; import io.metersphere.api.service.ApiCommonService; import io.metersphere.api.service.ApiExecuteService; +import io.metersphere.api.service.GetRunScriptService; import io.metersphere.api.service.definition.ApiDefinitionModuleService; import io.metersphere.api.service.definition.ApiDefinitionService; import io.metersphere.api.service.definition.ApiTestCaseService; @@ -30,10 +32,7 @@ import io.metersphere.project.dto.environment.http.HttpConfigModuleMatchRule; import io.metersphere.project.dto.environment.http.SelectModule; import io.metersphere.project.service.EnvironmentGroupService; import io.metersphere.project.service.EnvironmentService; -import io.metersphere.sdk.constants.ApiBatchRunMode; -import io.metersphere.sdk.constants.ApiExecuteRunMode; -import io.metersphere.sdk.constants.ExecStatus; -import io.metersphere.sdk.constants.TaskTriggerMode; +import io.metersphere.sdk.constants.*; import io.metersphere.sdk.dto.api.task.*; import io.metersphere.sdk.util.DateUtils; import io.metersphere.sdk.util.JSON; @@ -55,7 +54,7 @@ import java.util.stream.Collectors; @Service @Transactional(rollbackFor = Exception.class) -public class ApiScenarioRunService { +public class ApiScenarioRunService implements GetRunScriptService { @Resource private ApiScenarioMapper apiScenarioMapper; @Resource @@ -85,6 +84,10 @@ public class ApiScenarioRunService { @Resource private ApiExecutionSetService apiExecutionSetService; + public ApiScenarioRunService() { + GetRunScriptServiceRegister.register(ApiExecuteResourceType.API_SCENARIO, this); + } + public TaskRequestDTO run(String id, String reportId, String userId) { ApiScenarioDetail apiScenarioDetail = getForRun(id); @@ -260,12 +263,15 @@ public class ApiScenarioRunService { * 解析并返回执行脚本等信息 */ public GetRunScriptResult getRunScript(GetRunScriptRequest request) { + return getRunScript(request, request.getTaskItem().getResourceId()); + } + + public GetRunScriptResult getRunScript(GetRunScriptRequest request, String id) { + ApiScenarioDetail apiScenarioDetail = getForRun(id); TaskItem taskItem = request.getTaskItem(); - String id = taskItem.getResourceId(); ApiRunModeConfigDTO runModeConfig = request.getRunModeConfig(); String reportId = taskItem.getReportId(); - ApiScenarioDetail apiScenarioDetail = getForRun(id); if (apiScenarioDetail == null) { if (runModeConfig.isIntegratedReport()) { // 用例不存在,则在执行集合中删除 diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java index 841ec2dafb..e81d0b64bf 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java @@ -1289,7 +1289,7 @@ public class ApiScenarioService extends MoveNodeService { } } - private ApiScenario checkResourceExist(String id) { + public ApiScenario checkResourceExist(String id) { return ServiceUtils.checkResourceExist(apiScenarioMapper.selectByPrimaryKey(id), "permission.system_api_scenario.name"); } diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java index 2a07650c73..03e9f33426 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java @@ -350,7 +350,8 @@ public class ApiDefinitionControllerTests extends BaseTest { return JSON.parseObject(ApiDataUtils.toJSONString(msHTTPElement)); } - private ApiDefinitionAddRequest createApiDefinitionAddRequest() { + public static ApiDefinitionAddRequest createApiDefinitionAddRequest() { + ExtBaseProjectVersionMapper extBaseProjectVersionMapper = CommonBeanFactory.getBean(ExtBaseProjectVersionMapper.class); // 创建并返回一个 ApiDefinitionAddRequest 对象,用于测试 String defaultVersion = extBaseProjectVersionMapper.getDefaultVersion(DEFAULT_PROJECT_ID); ApiDefinitionAddRequest request = new ApiDefinitionAddRequest(); @@ -369,7 +370,7 @@ public class ApiDefinitionControllerTests extends BaseTest { return request; } - private List createCustomFields() { + private static List createCustomFields() { List list = new ArrayList<>(); ApiDefinitionCustomField customField = new ApiDefinitionCustomField(); customField.setFieldId("custom-field"); diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java index bf371494ec..4123c04363 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java @@ -47,6 +47,7 @@ import io.metersphere.sdk.file.FileRequest; import io.metersphere.sdk.mapper.EnvironmentGroupMapper; import io.metersphere.sdk.mapper.EnvironmentMapper; import io.metersphere.sdk.util.BeanUtils; +import io.metersphere.sdk.util.CommonBeanFactory; import io.metersphere.sdk.util.JSON; import io.metersphere.system.base.BaseTest; import io.metersphere.system.controller.handler.ResultHolder; @@ -343,16 +344,7 @@ public class ApiScenarioControllerTests extends BaseTest { initTestData(); // @@请求成功 - ApiScenarioAddRequest request = new ApiScenarioAddRequest(); - request.setProjectId(DEFAULT_PROJECT_ID); - request.setDescription("desc"); - request.setName("test name"); - request.setModuleId("default"); - request.setGrouped(false); - request.setEnvironmentId(envId); - request.setTags(List.of("tag1", "tag2")); - request.setPriority("P0"); - request.setStatus(ApiScenarioStatus.COMPLETED.name()); + ApiScenarioAddRequest request = getApiScenarioAddRequest(); List steps = getApiScenarioStepRequests(); Map steptDetailMap = new HashMap<>(); steptDetailMap.put(steps.get(1).getId(), getMsHttpElementParam()); @@ -403,6 +395,20 @@ public class ApiScenarioControllerTests extends BaseTest { requestPostPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_ADD, DEFAULT_ADD, request); } + public static ApiScenarioAddRequest getApiScenarioAddRequest() { + ApiScenarioAddRequest request = new ApiScenarioAddRequest(); + request.setProjectId(DEFAULT_PROJECT_ID); + request.setDescription("desc"); + request.setName("test name"); + request.setModuleId("default"); + request.setGrouped(false); + request.setEnvironmentId(envId); + request.setTags(List.of("tag1", "tag2")); + request.setPriority("P0"); + request.setStatus(ApiScenarioStatus.COMPLETED.name()); + return request; + } + private Object getMsHttpElementParam() { return getMsHttpElementStr(MsHTTPElementTest.getMsHttpElement()); } @@ -446,7 +452,15 @@ public class ApiScenarioControllerTests extends BaseTest { } } - private ScenarioConfig getScenarioConfig() { + public ScenarioConfig getScenarioConfig() { + ScenarioConfig scenarioConfig = getSimpleScenarioConfig(); + ScenarioVariable scenarioVariable = new ScenarioVariable(); + scenarioVariable.setCsvVariables(getCsvVariables()); + scenarioConfig.setVariable(scenarioVariable); + return scenarioConfig; + } + + public ScenarioConfig getSimpleScenarioConfig() { ScenarioConfig scenarioConfig = new ScenarioConfig(); MsAssertionConfig msAssertionConfig = new MsAssertionConfig(); MsScriptAssertion scriptAssertion = new MsScriptAssertion(); @@ -462,9 +476,6 @@ public class ApiScenarioControllerTests extends BaseTest { scenarioOtherConfig.setFailureStrategy(ScenarioOtherConfig.FailureStrategy.CONTINUE.name()); scenarioOtherConfig.setEnableCookieShare(true); scenarioConfig.setOtherConfig(scenarioOtherConfig); - ScenarioVariable scenarioVariable = new ScenarioVariable(); - scenarioVariable.setCsvVariables(getCsvVariables()); - scenarioConfig.setVariable(scenarioVariable); return scenarioConfig; } @@ -480,7 +491,7 @@ public class ApiScenarioControllerTests extends BaseTest { fileMetadataId = fileMetadataService.upload(fileUploadRequest, "admin", file); } - public List getCsvVariables() { + public static List getCsvVariables() { List csvVariables = new ArrayList<>(); CsvVariable csvVariable = new CsvVariable(); csvVariable.setId(UUID.randomUUID().toString()); @@ -498,6 +509,7 @@ public class ApiScenarioControllerTests extends BaseTest { csvVariable.setName("csv-关联的"); file = new ApiFile(); file.setFileId(fileMetadataId); + FileMetadataService fileMetadataService = CommonBeanFactory.getBean(FileMetadataService.class); FileMetadata fileMetadata = fileMetadataService.selectById(fileMetadataId); file.setFileName(fileMetadata.getOriginalName()); file.setLocal(false); diff --git a/backend/services/api-test/src/test/resources/dml/init_permission_test.sql b/backend/services/api-test/src/test/resources/dml/init_permission_test.sql deleted file mode 100644 index ec90568c9c..0000000000 --- a/backend/services/api-test/src/test/resources/dml/init_permission_test.sql +++ /dev/null @@ -1,14 +0,0 @@ --- 初始化用于权限测试的组织用户 -INSERT INTO user(id, name, email, password, create_time, update_time, language, last_organization_id, phone, source, - last_project_id, create_user, update_user, deleted) -VALUES ('PROJECT', 'PROJECT', 'PROJECT@fit2cloud.com', MD5('metersphere'), - UNIX_TIMESTAMP() * 1000, - UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin', 'admin', false); - --- 初始化一个用于权限测试的用户组,这里默认使用 PROJECT 作为ID,如果是组织和项目级别类似,便于根据权限的前缀找到对应测试的用户组 -INSERT INTO user_role (id, name, description, internal, type, create_time, update_time, create_user, scope_id) -VALUES ('PROJECT', '项目级别权限校验', '', 1, 'PROJECT', 1620674220005, 1620674220000, 'admin', 'global'); - --- 初始化用户和组的关系 -INSERT INTO user_role_relation (id, user_id, role_id, source_id, organization_id, create_time, create_user) -SELECT 'PROJECT', 'PROJECT', 'PROJECT', id, organization_id, 1684747668375, 'admin' FROM project WHERE num = 100001; diff --git a/backend/services/bug-management/src/test/resources/dml/init_permission_test.sql b/backend/services/bug-management/src/test/resources/dml/init_permission_test.sql deleted file mode 100644 index ec90568c9c..0000000000 --- a/backend/services/bug-management/src/test/resources/dml/init_permission_test.sql +++ /dev/null @@ -1,14 +0,0 @@ --- 初始化用于权限测试的组织用户 -INSERT INTO user(id, name, email, password, create_time, update_time, language, last_organization_id, phone, source, - last_project_id, create_user, update_user, deleted) -VALUES ('PROJECT', 'PROJECT', 'PROJECT@fit2cloud.com', MD5('metersphere'), - UNIX_TIMESTAMP() * 1000, - UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin', 'admin', false); - --- 初始化一个用于权限测试的用户组,这里默认使用 PROJECT 作为ID,如果是组织和项目级别类似,便于根据权限的前缀找到对应测试的用户组 -INSERT INTO user_role (id, name, description, internal, type, create_time, update_time, create_user, scope_id) -VALUES ('PROJECT', '项目级别权限校验', '', 1, 'PROJECT', 1620674220005, 1620674220000, 'admin', 'global'); - --- 初始化用户和组的关系 -INSERT INTO user_role_relation (id, user_id, role_id, source_id, organization_id, create_time, create_user) -SELECT 'PROJECT', 'PROJECT', 'PROJECT', id, organization_id, 1684747668375, 'admin' FROM project WHERE num = 100001; diff --git a/backend/services/case-management/src/test/resources/application.properties b/backend/services/case-management/src/test/resources/application.properties index 9672c9ecb7..89bfe68a43 100644 --- a/backend/services/case-management/src/test/resources/application.properties +++ b/backend/services/case-management/src/test/resources/application.properties @@ -63,6 +63,9 @@ spring.messages.basename=i18n/commons,i18n/api,i18n/bug,i18n/case,i18n/plan,i18n # actuator management.endpoints.web.exposure.include=* management.endpoints.enabled-by-default=false +# 单元测试初始化权限 sql +spring.sql.init.mode=always +spring.sql.init.schema-locations=classpath*:dml/init_permission_test.sql # redis spring.session.timeout=43200s spring.data.redis.host=${embedded.redis.host} diff --git a/backend/services/case-management/src/test/resources/dml/init_case_review.sql b/backend/services/case-management/src/test/resources/dml/init_case_review.sql index 95c3cddfb2..6e529c0cd8 100644 --- a/backend/services/case-management/src/test/resources/dml/init_case_review.sql +++ b/backend/services/case-management/src/test/resources/dml/init_case_review.sql @@ -47,7 +47,7 @@ VALUES ('CASE_REVIEW_REAL_MODULE_ID', 'project-gyq-case-review-test', '用例评 INSERT INTO user(id, name, email, password, create_time, update_time, language, last_organization_id, phone, source, last_project_id, create_user, update_user, deleted) -VALUES ('gyq_review_test', 'gyq_review_test', 'PROJECT@fit2cloud.com', MD5('metersphere'),UNIX_TIMESTAMP() * 1000,UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin', 'admin', false), +VALUES ('gyq_review_test', 'gyq_review_test', 'gyq_review_test@fit2cloud.com', MD5('metersphere'),UNIX_TIMESTAMP() * 1000,UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin', 'admin', false), ('gyq_review_test2', 'default-Administrator-1', 'admin-default-user@metersphere.io', MD5('metersphere'), UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin', 'admin', false); diff --git a/backend/services/project-management/src/test/resources/dml/init_permission_test.sql b/backend/services/project-management/src/test/resources/dml/init_permission_test.sql deleted file mode 100644 index ec90568c9c..0000000000 --- a/backend/services/project-management/src/test/resources/dml/init_permission_test.sql +++ /dev/null @@ -1,14 +0,0 @@ --- 初始化用于权限测试的组织用户 -INSERT INTO user(id, name, email, password, create_time, update_time, language, last_organization_id, phone, source, - last_project_id, create_user, update_user, deleted) -VALUES ('PROJECT', 'PROJECT', 'PROJECT@fit2cloud.com', MD5('metersphere'), - UNIX_TIMESTAMP() * 1000, - UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin', 'admin', false); - --- 初始化一个用于权限测试的用户组,这里默认使用 PROJECT 作为ID,如果是组织和项目级别类似,便于根据权限的前缀找到对应测试的用户组 -INSERT INTO user_role (id, name, description, internal, type, create_time, update_time, create_user, scope_id) -VALUES ('PROJECT', '项目级别权限校验', '', 1, 'PROJECT', 1620674220005, 1620674220000, 'admin', 'global'); - --- 初始化用户和组的关系 -INSERT INTO user_role_relation (id, user_id, role_id, source_id, organization_id, create_time, create_user) -SELECT 'PROJECT', 'PROJECT', 'PROJECT', id, organization_id, 1684747668375, 'admin' FROM project WHERE num = 100001; diff --git a/backend/services/system-setting/src/test/resources/dml/init_permission_test.sql b/backend/services/system-setting/src/test/resources/dml/init_permission_test.sql index dd7cbdf798..d362dc0595 100644 --- a/backend/services/system-setting/src/test/resources/dml/init_permission_test.sql +++ b/backend/services/system-setting/src/test/resources/dml/init_permission_test.sql @@ -27,3 +27,20 @@ VALUES ('ORGANIZATION', '组织级别权限校验', '', 1, 'ORGANIZATION', 16206 -- 初始化用户和组的关系 INSERT INTO user_role_relation (id, user_id, role_id, source_id, organization_id, create_time, create_user) SELECT 'ORGANIZATION', 'ORGANIZATION', 'ORGANIZATION', id, id, 1684747668375, 'admin' FROM organization WHERE num = 100001; + + +-- 初始化用于项目级别权限测试的用户 +INSERT INTO user(id, name, email, password, create_time, update_time, language, last_organization_id, phone, source, + last_project_id, create_user, update_user, deleted) +VALUES ('PROJECT', 'PROJECT', 'PROJECT@fit2cloud.com', MD5('metersphere'), + UNIX_TIMESTAMP() * 1000, + UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin', 'admin', false); + +-- 初始化一个用于权限测试的用户组,这里默认使用 PROJECT 作为ID,如果是组织和项目级别类似,便于根据权限的前缀找到对应测试的用户组 +INSERT INTO user_role (id, name, description, internal, type, create_time, update_time, create_user, scope_id) +VALUES ('PROJECT', '项目级别权限校验', '', 1, 'PROJECT', 1620674220005, 1620674220000, 'admin', 'global'); + +-- 初始化用户和组的关系 +INSERT INTO user_role_relation (id, user_id, role_id, source_id, organization_id, create_time, create_user) +SELECT 'PROJECT', 'PROJECT', 'PROJECT', id, organization_id, 1684747668375, 'admin' FROM project WHERE num = 100001; + diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java index 3bba947735..ae401c1f2d 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiCaseController.java @@ -10,6 +10,7 @@ import io.metersphere.plan.service.TestPlanApiCaseService; import io.metersphere.plan.service.TestPlanService; import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.sdk.dto.api.task.TaskRequestDTO; import io.metersphere.system.dto.LogInsertModule; import io.metersphere.system.dto.sdk.BaseTreeNode; import io.metersphere.system.log.annotation.Log; @@ -19,15 +20,13 @@ import io.metersphere.system.utils.PageUtils; import io.metersphere.system.utils.Pager; import io.metersphere.system.utils.SessionUtils; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Map; @@ -104,6 +103,16 @@ public class TestPlanApiCaseController { testPlanApiCaseService.batchUpdateExecutor(request); } + @GetMapping("/run/{id}") + @Operation(summary = "用例执行") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE) +// @CheckOwner(resourceId = "#id", resourceType = "test_plan_api_case") todo + public TaskRequestDTO run(@PathVariable String id, + @Schema(description = "报告ID,传了可以实时获取结果,不传则不支持实时获取") + @RequestParam(required = false) String reportId) { + return testPlanApiCaseService.run(id, reportId, SessionUtils.getUserId()); + } + //TODO 批量移动 (计划集内) } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiScenarioController.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiScenarioController.java index 45e92c5b25..8ab05ca3ef 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiScenarioController.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/controller/TestPlanApiScenarioController.java @@ -1,13 +1,28 @@ package io.metersphere.plan.controller; +import io.metersphere.plan.service.TestPlanApiScenarioService; +import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.sdk.dto.api.task.TaskRequestDTO; +import io.metersphere.system.utils.SessionUtils; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import jakarta.annotation.Resource; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; @Tag(name = "测试计划场景用例") @RestController @RequestMapping("/test-plan/api/scenario") public class TestPlanApiScenarioController { + @Resource + private TestPlanApiScenarioService testPlanApiScenarioService; + @GetMapping("/run/{id}") + @Operation(summary = "接口测试-接口场景管理-场景执行") + @RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE) +// @CheckOwner(resourceId = "#id", resourceType = "test_plan_api_scenario") + public TaskRequestDTO run(@PathVariable String id, @RequestParam(required = false) String reportId) { + return testPlanApiScenarioService.run(id, reportId, SessionUtils.getUserId()); + } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java index 674611bfc1..cd4a284874 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiCaseService.java @@ -1,12 +1,15 @@ package io.metersphere.plan.service; -import io.metersphere.api.domain.ApiTestCase; -import io.metersphere.api.domain.ApiTestCaseExample; +import io.metersphere.api.domain.*; import io.metersphere.api.dto.definition.ApiDefinitionDTO; import io.metersphere.api.dto.definition.ApiTestCaseDTO; +import io.metersphere.api.invoker.GetRunScriptServiceRegister; import io.metersphere.api.mapper.ApiTestCaseMapper; +import io.metersphere.api.service.ApiExecuteService; +import io.metersphere.api.service.GetRunScriptService; import io.metersphere.api.service.definition.ApiDefinitionModuleService; import io.metersphere.api.service.definition.ApiDefinitionService; +import io.metersphere.api.service.definition.ApiReportService; import io.metersphere.api.service.definition.ApiTestCaseService; import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO; import io.metersphere.functional.dto.ProjectOptionDTO; @@ -27,12 +30,11 @@ import io.metersphere.project.domain.ProjectExample; import io.metersphere.project.dto.ModuleCountDTO; import io.metersphere.project.dto.MoveNodeSortDTO; import io.metersphere.project.mapper.ProjectMapper; -import io.metersphere.sdk.constants.CaseType; -import io.metersphere.sdk.constants.ModuleConstants; -import io.metersphere.sdk.constants.TestPlanResourceConstants; +import io.metersphere.sdk.constants.*; import io.metersphere.sdk.domain.Environment; import io.metersphere.sdk.domain.EnvironmentExample; import io.metersphere.sdk.exception.MSException; +import io.metersphere.sdk.dto.api.task.*; import io.metersphere.sdk.mapper.EnvironmentMapper; import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.Translator; @@ -40,6 +42,7 @@ import io.metersphere.system.dto.LogInsertModule; import io.metersphere.system.dto.sdk.BaseTreeNode; import io.metersphere.system.service.UserLoginService; import io.metersphere.system.uid.IDGenerator; +import io.metersphere.system.utils.ServiceUtils; import jakarta.annotation.Resource; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -60,7 +63,7 @@ import java.util.stream.Collectors; @Service @Transactional(rollbackFor = Exception.class) -public class TestPlanApiCaseService extends TestPlanResourceService { +public class TestPlanApiCaseService extends TestPlanResourceService implements GetRunScriptService { @Resource private TestPlanMapper testPlanMapper; @@ -73,6 +76,8 @@ public class TestPlanApiCaseService extends TestPlanResourceService { @Resource private ApiTestCaseService apiTestCaseService; @Resource + private ApiReportService apiReportService; + @Resource private ProjectMapper projectMapper; @Resource private EnvironmentMapper environmentMapper; @@ -84,11 +89,17 @@ public class TestPlanApiCaseService extends TestPlanResourceService { @Resource private SqlSessionFactory sqlSessionFactory; @Resource - private TestPlanCollectionMapper testPlanCollectionMapper; + private ApiExecuteService apiExecuteService; @Resource private ApiTestCaseMapper apiTestCaseMapper; @Resource private TestPlanResourceLogService testPlanResourceLogService; + @Resource + private TestPlanCollectionMapper testPlanCollectionMapper; + + public TestPlanApiCaseService() { + GetRunScriptServiceRegister.register(ApiExecuteResourceType.TEST_PLAN_API_CASE, this); + } @Override public void deleteBatchByTestPlanId(List testPlanIdList) { @@ -505,7 +516,6 @@ public class TestPlanApiCaseService extends TestPlanResourceService { } } - /** * 构建测试计划接口用例对象 * @@ -561,4 +571,84 @@ public class TestPlanApiCaseService extends TestPlanResourceService { testPlanResourceLogService.saveSortLog(testPlan, request.getMoveId(), new ResourceLogInsertModule(TestPlanResourceConstants.RESOURCE_API_CASE, logInsertModule)); return response; } + + public TaskRequestDTO run(String id, String reportId, String userId) { + TestPlanApiCase testPlanApiCase = checkResourceExist(id); + ApiTestCase apiTestCase = apiTestCaseService.checkResourceExist(testPlanApiCase.getApiCaseId()); + + String poolId = "todo"; + ApiRunModeConfigDTO runModeConfig = new ApiRunModeConfigDTO(); + // todo 设置 runModeConfig 配置 + TaskRequestDTO taskRequest = getTaskRequest(reportId, id, apiTestCase.getProjectId(), ApiExecuteRunMode.RUN.name()); + TaskInfo taskInfo = taskRequest.getTaskInfo(); + TaskItem taskItem = taskRequest.getTaskItem(); + taskInfo.setRunModeConfig(runModeConfig); + taskInfo.setSaveResult(true); + taskInfo.setRealTime(true); + + if (StringUtils.isEmpty(taskItem.getReportId())) { + taskInfo.setRealTime(false); + reportId = IDGenerator.nextStr(); + taskItem.setReportId(reportId); + } else { + // 如果传了报告ID,则实时获取结果 + taskInfo.setRealTime(true); + } + + // 初始化报告 + initApiReport(apiTestCase, testPlanApiCase, reportId, poolId, userId); + + return apiExecuteService.execute(taskRequest); + } + + public TestPlanApiCase checkResourceExist(String id) { + return ServiceUtils.checkResourceExist(testPlanApiCaseMapper.selectByPrimaryKey(id), "api_test_case_not_exist"); + } + + /** + * 获取执行脚本 + */ + @Override + public GetRunScriptResult getRunScript(GetRunScriptRequest request) { + TaskItem taskItem = request.getTaskItem(); + TestPlanApiCase testPlanApiCase = testPlanApiCaseMapper.selectByPrimaryKey(taskItem.getResourceId()); + ApiTestCase apiTestCase = apiTestCaseMapper.selectByPrimaryKey(testPlanApiCase.getApiCaseId()); + return apiTestCaseService.getRunScript(request, apiTestCase); + } + + /** + * 预生成用例的执行报告 + * + * @param apiTestCase + * @param poolId + * @param userId + * @return + */ + public ApiTestCaseRecord initApiReport(ApiTestCase apiTestCase, TestPlanApiCase testPlanApiCase, String reportId, String poolId, String userId) { + // 初始化报告 + ApiReport apiReport = apiTestCaseService.getApiReport(apiTestCase, reportId, poolId, userId); + apiReport.setTestPlanCaseId(testPlanApiCase.getTestPlanId()); + + // 创建报告和用例的关联关系 + ApiTestCaseRecord apiTestCaseRecord = apiTestCaseService.getApiTestCaseRecord(apiTestCase, apiReport); + + apiReportService.insertApiReport(List.of(apiReport), List.of(apiTestCaseRecord)); + + //初始化步骤 + apiReportService.insertApiReportStep(List.of(getApiReportStep(apiTestCase, reportId))); + return apiTestCaseRecord; + } + + public ApiReportStep getApiReportStep(ApiTestCase apiTestCase, String reportId) { + ApiReportStep apiReportStep = apiTestCaseService.getApiReportStep(apiTestCase, reportId, 1L); + apiReportStep.setStepType(ApiExecuteResourceType.TEST_PLAN_API_CASE.name()); + return apiReportStep; + } + + public TaskRequestDTO getTaskRequest(String reportId, String resourceId, String projectId, String runModule) { + TaskRequestDTO taskRequest = apiTestCaseService.getTaskRequest(reportId, resourceId, projectId, runModule); + taskRequest.getTaskInfo().setResourceType(ApiExecuteResourceType.TEST_PLAN_API_CASE.name()); + taskRequest.getTaskInfo().setNeedParseScript(true); + return taskRequest; + } } diff --git a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiScenarioService.java b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiScenarioService.java index 3ba3b4994b..7d7ef76787 100644 --- a/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiScenarioService.java +++ b/backend/services/test-plan/src/main/java/io/metersphere/plan/service/TestPlanApiScenarioService.java @@ -1,6 +1,12 @@ package io.metersphere.plan.service; +import io.metersphere.api.domain.ApiScenario; +import io.metersphere.api.domain.ApiScenarioReport; import io.metersphere.api.dto.scenario.ApiScenarioDTO; +import io.metersphere.api.invoker.GetRunScriptServiceRegister; +import io.metersphere.api.service.ApiExecuteService; +import io.metersphere.api.service.GetRunScriptService; +import io.metersphere.api.service.scenario.ApiScenarioRunService; import io.metersphere.api.service.scenario.ApiScenarioService; import io.metersphere.plan.constants.AssociateCaseType; import io.metersphere.plan.domain.TestPlan; @@ -15,13 +21,14 @@ import io.metersphere.plan.dto.request.TestPlanApiScenarioRequest; import io.metersphere.plan.dto.response.TestPlanOperationResponse; import io.metersphere.plan.mapper.*; import io.metersphere.project.dto.MoveNodeSortDTO; -import io.metersphere.sdk.constants.CaseType; -import io.metersphere.sdk.constants.TestPlanResourceConstants; +import io.metersphere.sdk.constants.*; +import io.metersphere.sdk.dto.api.task.*; import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.Translator; import io.metersphere.system.dto.LogInsertModule; import io.metersphere.system.uid.IDGenerator; +import io.metersphere.system.utils.ServiceUtils; import jakarta.annotation.Resource; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.session.ExecutorType; @@ -38,7 +45,7 @@ import java.util.stream.Collectors; @Service @Transactional(rollbackFor = Exception.class) -public class TestPlanApiScenarioService extends TestPlanResourceService { +public class TestPlanApiScenarioService extends TestPlanResourceService implements GetRunScriptService { @Resource private SqlSessionFactory sqlSessionFactory; @Resource @@ -46,13 +53,19 @@ public class TestPlanApiScenarioService extends TestPlanResourceService { @Resource private ExtTestPlanApiScenarioMapper extTestPlanApiScenarioMapper; @Resource - private TestPlanCollectionMapper testPlanCollectionMapper; - @Resource private ApiScenarioService apiScenarioService; @Resource private TestPlanMapper testPlanMapper; @Resource private TestPlanResourceLogService testPlanResourceLogService; + @Resource + private ApiScenarioRunService apiScenarioRunService; + @Resource + private ApiExecuteService apiExecuteService; + + public TestPlanApiScenarioService() { + GetRunScriptServiceRegister.register(ApiExecuteResourceType.TEST_PLAN_API_SCENARIO, this); + } @Override public void deleteBatchByTestPlanId(List testPlanIdList) { @@ -137,7 +150,6 @@ public class TestPlanApiScenarioService extends TestPlanResourceService { scenarioBatchMapper.updateByExampleSelective(record, scenarioCaseExample); } - /** * 未关联接口场景列表 * @@ -167,4 +179,59 @@ public class TestPlanApiScenarioService extends TestPlanResourceService { testPlanResourceLogService.saveSortLog(testPlan, request.getMoveId(), new ResourceLogInsertModule(TestPlanResourceConstants.RESOURCE_API_CASE, logInsertModule)); return response; } + + + public TaskRequestDTO run(String id, String reportId, String userId) { + TestPlanApiScenario testPlanApiScenario = checkResourceExist(id); + ApiScenario apiScenario = apiScenarioService.checkResourceExist(testPlanApiScenario.getApiScenarioId()); + + String poolId = "todo"; + String envId = "todo"; + ApiRunModeConfigDTO runModeConfig = new ApiRunModeConfigDTO(); + // todo 设置 runModeConfig 配置 + TaskRequestDTO taskRequest = getTaskRequest(reportId, id, apiScenario.getProjectId(), ApiExecuteRunMode.RUN.name()); + TaskInfo taskInfo = taskRequest.getTaskInfo(); + TaskItem taskItem = taskRequest.getTaskItem(); + taskInfo.setRunModeConfig(runModeConfig); + taskInfo.setSaveResult(true); + taskInfo.setRealTime(true); + + if (StringUtils.isEmpty(taskItem.getReportId())) { + taskInfo.setRealTime(false); + reportId = IDGenerator.nextStr(); + taskItem.setReportId(reportId); + } else { + // 如果传了报告ID,则实时获取结果 + taskInfo.setRealTime(true); + } + + ApiScenarioReport scenarioReport = apiScenarioRunService.getScenarioReport(userId); + scenarioReport.setId(reportId); + scenarioReport.setTriggerMode(TaskTriggerMode.MANUAL.name()); + scenarioReport.setRunMode(ApiBatchRunMode.PARALLEL.name()); + scenarioReport.setPoolId(poolId); + scenarioReport.setEnvironmentId(envId); + scenarioReport.setTestPlanScenarioId(testPlanApiScenario.getId()); + apiScenarioRunService.initApiReport(apiScenario, scenarioReport); + + return apiExecuteService.execute(taskRequest); + } + + public TestPlanApiScenario checkResourceExist(String id) { + return ServiceUtils.checkResourceExist(testPlanApiScenarioMapper.selectByPrimaryKey(id), "permission.system_api_scenario.name"); + } + + public TaskRequestDTO getTaskRequest(String reportId, String resourceId, String projectId, String runModule) { + TaskRequestDTO taskRequest = apiScenarioRunService.getTaskRequest(reportId, resourceId, projectId, runModule); + taskRequest.getTaskInfo().setResourceType(ApiExecuteResourceType.TEST_PLAN_API_SCENARIO.name()); + taskRequest.getTaskInfo().setNeedParseScript(true); + return taskRequest; + } + + @Override + public GetRunScriptResult getRunScript(GetRunScriptRequest request) { + TaskItem taskItem = request.getTaskItem(); + TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(taskItem.getResourceId()); + return apiScenarioRunService.getRunScript(request, testPlanApiScenario.getApiScenarioId()); + } } diff --git a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiCaseControllerTests.java b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiCaseControllerTests.java index 19d8d0dda7..39c4fe3a15 100644 --- a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiCaseControllerTests.java +++ b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiCaseControllerTests.java @@ -1,8 +1,28 @@ package io.metersphere.plan.controller; +import io.metersphere.api.constants.ApiConstants; +import io.metersphere.api.constants.ApiDefinitionStatus; +import io.metersphere.api.controller.result.ApiResultCode; +import io.metersphere.api.domain.ApiDefinition; +import io.metersphere.api.domain.ApiTestCase; +import io.metersphere.api.dto.definition.ApiDefinitionAddRequest; +import io.metersphere.api.dto.definition.ApiTestCaseAddRequest; +import io.metersphere.api.dto.request.http.MsHTTPElement; +import io.metersphere.api.dto.request.http.body.Body; +import io.metersphere.api.dto.request.http.body.RawBody; +import io.metersphere.api.service.definition.ApiDefinitionService; +import io.metersphere.api.service.definition.ApiTestCaseService; +import io.metersphere.api.utils.ApiDataUtils; import io.metersphere.plan.constants.AssociateCaseType; +import io.metersphere.plan.domain.TestPlanApiCase; import io.metersphere.plan.dto.request.*; +import io.metersphere.plan.mapper.TestPlanApiCaseMapper; import io.metersphere.plan.service.TestPlanApiCaseService; +import io.metersphere.project.mapper.ExtBaseProjectVersionMapper; +import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.sdk.dto.api.task.GetRunScriptRequest; +import io.metersphere.sdk.dto.api.task.TaskItem; +import io.metersphere.sdk.util.CommonBeanFactory; import io.metersphere.sdk.util.JSON; import io.metersphere.system.base.BaseTest; import io.metersphere.system.controller.handler.ResultHolder; @@ -15,25 +35,41 @@ import org.springframework.test.context.jdbc.SqlConfig; import org.springframework.test.web.servlet.MvcResult; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; + +import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class TestPlanApiCaseControllerTests extends BaseTest { - public static final String API_CASE_PAGE = "/test-plan/api/case/page"; - public static final String API_CASE_TREE_COUNT = "/test-plan/api/case/module/count"; - public static final String API_CASE_TREE_MODULE_TREE = "/test-plan/api/case/tree"; - public static final String API_CASE_DISASSOCIATE = "/test-plan/api/case/disassociate"; - public static final String API_CASE_BATCH_DISASSOCIATE = "/test-plan/api/case/batch/disassociate"; - public static final String API_CASE_BATCH_UPDATE_EXECUTOR_URL = "/test-plan/api/case/batch/update/executor"; + private static final String BASE_PATH = "/test-plan/api/case/"; + public static final String API_CASE_PAGE = "page"; + public static final String API_CASE_TREE_COUNT = "module/count"; + public static final String API_CASE_TREE_MODULE_TREE = "tree"; + public static final String API_CASE_DISASSOCIATE = "disassociate"; + public static final String API_CASE_BATCH_DISASSOCIATE = "batch/disassociate"; + public static final String API_CASE_BATCH_UPDATE_EXECUTOR_URL = "batch/update/executor"; + public static final String RUN = "run/{0}"; + public static final String RUN_WITH_REPORT_ID = "run/{0}?reportId={1}"; @Resource private TestPlanApiCaseService testPlanApiCaseService; + @Resource + private ApiTestCaseService apiTestCaseService; + @Resource + private ApiDefinitionService apiDefinitionService; + @Resource + private TestPlanApiCaseMapper testPlanApiCaseMapper; + + private static ApiTestCase apiTestCase; + private static TestPlanApiCase testPlanApiCase; + + @Override + public String getBasePath() { + return BASE_PATH; + } @Test @Order(1) @@ -56,7 +92,6 @@ public class TestPlanApiCaseControllerTests extends BaseTest { Assertions.assertNotNull(resultHolder); } - @Test @Order(2) public void testApiCaseCount() throws Exception { @@ -146,7 +181,7 @@ public class TestPlanApiCaseControllerTests extends BaseTest { @Test @Order(6) - public void testApiCaseAssociate() throws Exception { + public void testApiCaseAssociate() { // api Map> collectionAssociates = new HashMap<>(); List baseCollectionAssociateRequests = new ArrayList<>(); @@ -167,5 +202,83 @@ public class TestPlanApiCaseControllerTests extends BaseTest { collectionAssociates1.put(AssociateCaseType.API_CASE, baseCollectionAssociateRequests1); testPlanApiCaseService.associateCollection("wxxx_2", collectionAssociates1, "wx"); + apiTestCase = initApiData(); + TestPlanApiCase testPlanApiCase = new TestPlanApiCase(); + testPlanApiCase.setApiCaseId(apiTestCase.getId()); + testPlanApiCase.setTestPlanId("wxxx_1"); + testPlanApiCase.setTestPlanCollectionId("wxxx_1"); + testPlanApiCase.setId(UUID.randomUUID().toString()); + testPlanApiCase.setCreateTime(System.currentTimeMillis()); + testPlanApiCase.setCreateUser("admin"); + testPlanApiCase.setPos(0L); + testPlanApiCaseMapper.insert(testPlanApiCase); + this.testPlanApiCase = testPlanApiCase; + // todo 关联的接口测试 + } + + @Test + @Order(7) + public void run() throws Exception { + assertErrorCode(this.requestGet(RUN, testPlanApiCase.getId()), ApiResultCode.RESOURCE_POOL_EXECUTE_ERROR); + assertErrorCode(this.requestGet(RUN_WITH_REPORT_ID, testPlanApiCase.getId(), "reportId"), ApiResultCode.RESOURCE_POOL_EXECUTE_ERROR); + assertErrorCode(this.requestGet(RUN, "11"), NOT_FOUND); + GetRunScriptRequest request = new GetRunScriptRequest(); + TaskItem taskItem = new TaskItem(); + taskItem.setResourceId(testPlanApiCase.getId()); + taskItem.setReportId("reportId"); + request.setTaskItem(taskItem); + testPlanApiCaseService.getRunScript(request); + + requestGetPermissionTest(PermissionConstants.TEST_PLAN_READ_EXECUTE, RUN, testPlanApiCase.getId()); + } + + public ApiTestCase initApiData() { + ApiDefinitionAddRequest apiDefinitionAddRequest = createApiDefinitionAddRequest(); + MsHTTPElement msHttpElement = new MsHTTPElement(); + msHttpElement.setPath("/test"); + msHttpElement.setMethod("GET"); + msHttpElement.setName("name"); + msHttpElement.setEnable(true); + Body body = new Body(); + body.setBodyType(Body.BodyType.RAW.name()); + body.setRawBody(new RawBody()); + msHttpElement.setBody(body); + apiDefinitionAddRequest.setRequest(getTestElementParam(msHttpElement)); + ApiDefinition apiDefinition = apiDefinitionService.create(apiDefinitionAddRequest, "admin"); + apiDefinitionAddRequest.setName(UUID.randomUUID().toString()); + + ApiTestCaseAddRequest caseAddRequest = new ApiTestCaseAddRequest(); + caseAddRequest.setApiDefinitionId(apiDefinition.getId()); + caseAddRequest.setName(UUID.randomUUID().toString()); + caseAddRequest.setProjectId(DEFAULT_PROJECT_ID); + caseAddRequest.setPriority("P0"); + caseAddRequest.setStatus(ApiDefinitionStatus.PROCESSING.name()); + caseAddRequest.setTags(new LinkedHashSet<>(List.of("tag1", "tag2"))); + caseAddRequest.setEnvironmentId("envId"); + caseAddRequest.setRequest(getTestElementParam(msHttpElement)); + return apiTestCaseService.addCase(caseAddRequest, "admin"); + } + + public static ApiDefinitionAddRequest createApiDefinitionAddRequest() { + ExtBaseProjectVersionMapper extBaseProjectVersionMapper = CommonBeanFactory.getBean(ExtBaseProjectVersionMapper.class); + String defaultVersion = extBaseProjectVersionMapper.getDefaultVersion(DEFAULT_PROJECT_ID); + ApiDefinitionAddRequest request = new ApiDefinitionAddRequest(); + request.setName(UUID.randomUUID().toString()); + request.setProtocol(ApiConstants.HTTP_PROTOCOL); + request.setProjectId(DEFAULT_PROJECT_ID); + request.setMethod("POST"); + request.setPath("/api/admin/posts"); + request.setStatus(ApiDefinitionStatus.PROCESSING.name()); + request.setModuleId("default"); + request.setVersionId(defaultVersion); + request.setDescription("描述内容"); + request.setTags(new LinkedHashSet<>(List.of("tag1", "tag2"))); + request.setCustomFields(List.of()); + return request; + } + + + private Object getTestElementParam(MsHTTPElement msHttpElement) { + return JSON.parseObject(ApiDataUtils.toJSONString(msHttpElement)); } } diff --git a/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiScenarioControllerTests.java b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiScenarioControllerTests.java new file mode 100644 index 0000000000..ef26e0b325 --- /dev/null +++ b/backend/services/test-plan/src/test/java/io/metersphere/plan/controller/TestPlanApiScenarioControllerTests.java @@ -0,0 +1,175 @@ +package io.metersphere.plan.controller; + +import io.metersphere.api.constants.ApiScenarioStatus; +import io.metersphere.api.constants.ApiScenarioStepRefType; +import io.metersphere.api.constants.ApiScenarioStepType; +import io.metersphere.api.controller.result.ApiResultCode; +import io.metersphere.api.domain.ApiScenario; +import io.metersphere.api.dto.assertion.MsAssertionConfig; +import io.metersphere.api.dto.request.http.MsHTTPElement; +import io.metersphere.api.dto.request.http.body.Body; +import io.metersphere.api.dto.request.http.body.RawBody; +import io.metersphere.api.dto.scenario.ApiScenarioAddRequest; +import io.metersphere.api.dto.scenario.ApiScenarioStepRequest; +import io.metersphere.api.dto.scenario.ScenarioConfig; +import io.metersphere.api.dto.scenario.ScenarioOtherConfig; +import io.metersphere.api.service.scenario.ApiScenarioService; +import io.metersphere.api.utils.ApiDataUtils; +import io.metersphere.plan.domain.TestPlanApiScenario; +import io.metersphere.plan.mapper.TestPlanApiScenarioMapper; +import io.metersphere.plan.service.TestPlanApiScenarioService; +import io.metersphere.project.api.assertion.MsResponseCodeAssertion; +import io.metersphere.project.api.assertion.MsScriptAssertion; +import io.metersphere.project.mapper.ExtBaseProjectVersionMapper; +import io.metersphere.sdk.constants.MsAssertionCondition; +import io.metersphere.sdk.dto.api.task.GetRunScriptRequest; +import io.metersphere.sdk.dto.api.task.TaskItem; +import io.metersphere.sdk.util.JSON; +import io.metersphere.system.base.BaseTest; +import io.metersphere.system.uid.IDGenerator; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class TestPlanApiScenarioControllerTests extends BaseTest { + + private static final String BASE_PATH = "/test-plan/api/scenario/"; + public static final String RUN = "run/{0}"; + public static final String RUN_WITH_REPORT_ID = "run/{0}?reportId={1}"; + + @Resource + private TestPlanApiScenarioService testPlanApiScenarioService; + @Resource + private ApiScenarioService apiScenarioService; + @Resource + private TestPlanApiScenarioMapper testPlanApiScenarioMapper; + + private static ApiScenario apiScenario; + private static TestPlanApiScenario testPlanApiScenario; + @Resource + private ExtBaseProjectVersionMapper extBaseProjectVersionMapper; + + @Override + public String getBasePath() { + return BASE_PATH; + } + + @Test + @Order(1) + public void associate() { + apiScenario = initApiData(); + TestPlanApiScenario testPlanApiScenario = new TestPlanApiScenario(); + testPlanApiScenario.setApiScenarioId(apiScenario.getId()); + testPlanApiScenario.setTestPlanId("wxxx_1"); + testPlanApiScenario.setTestPlanCollectionId("wxxx_1"); + testPlanApiScenario.setId(UUID.randomUUID().toString()); + testPlanApiScenario.setCreateTime(System.currentTimeMillis()); + testPlanApiScenario.setCreateUser("admin"); + testPlanApiScenario.setPos(0L); + testPlanApiScenarioMapper.insert(testPlanApiScenario); + this.testPlanApiScenario = testPlanApiScenario; + // todo 关联的接口测试 + } + + @Test + @Order(2) + public void run() throws Exception { + assertErrorCode(this.requestGet(RUN, testPlanApiScenario.getId()), ApiResultCode.RESOURCE_POOL_EXECUTE_ERROR); + assertErrorCode(this.requestGet(RUN_WITH_REPORT_ID, testPlanApiScenario.getId(), "reportId"), ApiResultCode.RESOURCE_POOL_EXECUTE_ERROR); + assertErrorCode(this.requestGet(RUN, "11"), NOT_FOUND); + GetRunScriptRequest request = new GetRunScriptRequest(); + TaskItem taskItem = new TaskItem(); + taskItem.setResourceId(testPlanApiScenario.getId()); + taskItem.setReportId("reportId"); + request.setTaskItem(taskItem); + testPlanApiScenarioService.getRunScript(request); + } + + public ApiScenario initApiData() { + ApiScenarioAddRequest request = getApiScenarioAddRequest(); + + ApiScenarioStepRequest stepRequest = new ApiScenarioStepRequest(); + stepRequest.setId(IDGenerator.nextStr()); + stepRequest.setVersionId(extBaseProjectVersionMapper.getDefaultVersion(DEFAULT_PROJECT_ID)); + stepRequest.setConfig(new HashMap<>()); + stepRequest.setEnable(true); + stepRequest.setName(UUID.randomUUID().toString()); + stepRequest.setRefType(ApiScenarioStepRefType.DIRECT.name()); + stepRequest.setStepType(ApiScenarioStepType.CUSTOM_REQUEST.name()); + stepRequest.setProjectId(DEFAULT_PROJECT_ID); + stepRequest.setConfig(new HashMap<>()); + + List steps = List.of(stepRequest); + Map steptDetailMap = new HashMap<>(); + steptDetailMap.put(stepRequest.getId(), getMsHttpElementParam()); + request.setSteps(steps); + request.setStepDetails(steptDetailMap); + request.setScenarioConfig(getScenarioConfig()); + + return apiScenarioService.add(request, "admin"); + } + + public ScenarioConfig getScenarioConfig() { + ScenarioConfig scenarioConfig = new ScenarioConfig(); + MsAssertionConfig msAssertionConfig = new MsAssertionConfig(); + MsScriptAssertion scriptAssertion = new MsScriptAssertion(); + scriptAssertion.setScript("{}"); + scriptAssertion.setName("script"); + msAssertionConfig.setAssertions(List.of(scriptAssertion)); + MsResponseCodeAssertion responseCodeAssertion = new MsResponseCodeAssertion(); + responseCodeAssertion.setExpectedValue("200"); + responseCodeAssertion.setCondition(MsAssertionCondition.EMPTY.name()); + responseCodeAssertion.setName("test"); + scenarioConfig.getAssertionConfig().getAssertions().add(responseCodeAssertion); + ScenarioOtherConfig scenarioOtherConfig = new ScenarioOtherConfig(); + scenarioOtherConfig.setFailureStrategy(ScenarioOtherConfig.FailureStrategy.CONTINUE.name()); + scenarioOtherConfig.setEnableCookieShare(true); + scenarioConfig.setOtherConfig(scenarioOtherConfig); + return scenarioConfig; + } + + public static ApiScenarioAddRequest getApiScenarioAddRequest() { + ApiScenarioAddRequest request = new ApiScenarioAddRequest(); + request.setProjectId(DEFAULT_PROJECT_ID); + request.setDescription("desc"); + request.setName("test name"); + request.setModuleId("default"); + request.setGrouped(false); + request.setEnvironmentId("envID"); + request.setTags(List.of("tag1", "tag2")); + request.setPriority("P0"); + request.setStatus(ApiScenarioStatus.COMPLETED.name()); + return request; + } + + private Object getMsHttpElementParam() { + MsHTTPElement msHTTPElement = new MsHTTPElement(); + msHTTPElement.setPath("/test"); + msHTTPElement.setMethod("GET"); + msHTTPElement.setName("name"); + msHTTPElement.setEnable(true); + Body body = new Body(); + body.setBodyType(Body.BodyType.RAW.name()); + body.setRawBody(new RawBody()); + msHTTPElement.setBody(body); + return getMsHttpElementStr(msHTTPElement); + } + + private Object getMsHttpElementStr(MsHTTPElement msHTTPElement) { + return JSON.parseObject(ApiDataUtils.toJSONString(msHTTPElement)); + } +} diff --git a/backend/services/test-plan/src/test/resources/dml/init_permission_test.sql b/backend/services/test-plan/src/test/resources/dml/init_permission_test.sql deleted file mode 100644 index ec90568c9c..0000000000 --- a/backend/services/test-plan/src/test/resources/dml/init_permission_test.sql +++ /dev/null @@ -1,14 +0,0 @@ --- 初始化用于权限测试的组织用户 -INSERT INTO user(id, name, email, password, create_time, update_time, language, last_organization_id, phone, source, - last_project_id, create_user, update_user, deleted) -VALUES ('PROJECT', 'PROJECT', 'PROJECT@fit2cloud.com', MD5('metersphere'), - UNIX_TIMESTAMP() * 1000, - UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin', 'admin', false); - --- 初始化一个用于权限测试的用户组,这里默认使用 PROJECT 作为ID,如果是组织和项目级别类似,便于根据权限的前缀找到对应测试的用户组 -INSERT INTO user_role (id, name, description, internal, type, create_time, update_time, create_user, scope_id) -VALUES ('PROJECT', '项目级别权限校验', '', 1, 'PROJECT', 1620674220005, 1620674220000, 'admin', 'global'); - --- 初始化用户和组的关系 -INSERT INTO user_role_relation (id, user_id, role_id, source_id, organization_id, create_time, create_user) -SELECT 'PROJECT', 'PROJECT', 'PROJECT', id, organization_id, 1684747668375, 'admin' FROM project WHERE num = 100001;