feat(测试计划): 获取已关联接口用例模块count
This commit is contained in:
parent
fc23684ffb
commit
9ca8b7ac0f
|
@ -21,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Tag(name = "测试计划接口用例")
|
@Tag(name = "测试计划接口用例")
|
||||||
@RestController
|
@RestController
|
||||||
|
@ -40,4 +41,14 @@ public class TestPlanApiCaseController {
|
||||||
StringUtils.isNotBlank(request.getSortString("id")) ? request.getSortString("id") : "create_time desc");
|
StringUtils.isNotBlank(request.getSortString("id")) ? request.getSortString("id") : "create_time desc");
|
||||||
return PageUtils.setPageInfo(page, testPlanApiCaseService.HasRelateApiCaseList(request, false));
|
return PageUtils.setPageInfo(page, testPlanApiCaseService.HasRelateApiCaseList(request, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/module/count")
|
||||||
|
@Operation(summary = "测试计划-已关联功能用例模块数量")
|
||||||
|
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ)
|
||||||
|
@CheckOwner(resourceId = "#request.getTestPlanId()", resourceType = "test_plan")
|
||||||
|
public Map<String, Long> moduleCount(@Validated @RequestBody TestPlanApiCaseRequest request) {
|
||||||
|
return testPlanApiCaseService.moduleCount(request);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author wx
|
* @author wx
|
||||||
*/
|
*/
|
||||||
|
@ -14,4 +16,8 @@ public class TestPlanApiCaseRequest extends ApiTestCasePageRequest {
|
||||||
@Schema(description = "测试计划id", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "测试计划id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@NotBlank(message = "{test_plan.id.not_blank}")
|
@NotBlank(message = "{test_plan.id.not_blank}")
|
||||||
private String testPlanId;
|
private String testPlanId;
|
||||||
|
|
||||||
|
@Schema(description = "计划集id")
|
||||||
|
private List<String> collectionIds;
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.plan.mapper;
|
package io.metersphere.plan.mapper;
|
||||||
|
|
||||||
import io.metersphere.api.dto.definition.ApiDefinitionDTO;
|
import io.metersphere.api.dto.definition.ApiDefinitionDTO;
|
||||||
|
import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO;
|
||||||
import io.metersphere.plan.dto.ResourceSelectParam;
|
import io.metersphere.plan.dto.ResourceSelectParam;
|
||||||
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
||||||
import io.metersphere.plan.dto.request.TestPlanApiCaseRequest;
|
import io.metersphere.plan.dto.request.TestPlanApiCaseRequest;
|
||||||
|
@ -31,4 +32,10 @@ public interface ExtTestPlanApiCaseMapper {
|
||||||
List<ApiDefinitionDTO> list(@Param("request") TestPlanApiRequest request, @Param("isRepeat") boolean isRepeat);
|
List<ApiDefinitionDTO> list(@Param("request") TestPlanApiRequest request, @Param("isRepeat") boolean isRepeat);
|
||||||
|
|
||||||
List<TestPlanApiCasePageResponse> relateApiCaseList(@Param("request") TestPlanApiCaseRequest request, @Param("deleted") boolean deleted);
|
List<TestPlanApiCasePageResponse> relateApiCaseList(@Param("request") TestPlanApiCaseRequest request, @Param("deleted") boolean deleted);
|
||||||
|
|
||||||
|
List<FunctionalCaseModuleCountDTO> countModuleIdByRequest(@Param("request") TestPlanApiCaseRequest request, @Param("deleted") boolean deleted);
|
||||||
|
|
||||||
|
List<String> selectIdByProjectIdAndTestPlanId(@Param("projectId") String projectId, @Param("testPlanId") String testPlanId);
|
||||||
|
|
||||||
|
long caseCount(@Param("request") TestPlanApiCaseRequest request, @Param("deleted") boolean deleted);
|
||||||
}
|
}
|
||||||
|
|
|
@ -449,6 +449,12 @@
|
||||||
#{nodeId}
|
#{nodeId}
|
||||||
</foreach>
|
</foreach>
|
||||||
</if>
|
</if>
|
||||||
|
<if test="request.collectionIds != null and request.collectionIds.size() > 0">
|
||||||
|
and t.test_plan_collection_id in
|
||||||
|
<foreach collection="request.collectionIds" item="collectionId" separator="," open="(" close=")">
|
||||||
|
#{collectionId}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
<include refid="apiCaseFilters">
|
<include refid="apiCaseFilters">
|
||||||
<property name="filter" value="request.filter"/>
|
<property name="filter" value="request.filter"/>
|
||||||
</include>
|
</include>
|
||||||
|
@ -519,4 +525,35 @@
|
||||||
AND a.latest = 1
|
AND a.latest = 1
|
||||||
</if>
|
</if>
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
|
<select id="countModuleIdByRequest" resultType="io.metersphere.functional.dto.FunctionalCaseModuleCountDTO">
|
||||||
|
SELECT a.module_id AS moduleId, count(atc.id) AS dataCount, atc.project_id AS projectId, project.name AS projectName
|
||||||
|
FROM test_plan_api_case t
|
||||||
|
INNER JOIN api_test_case atc ON t.api_case_id = atc.id
|
||||||
|
INNER JOIN api_definition a ON atc.api_definition_id = a.id
|
||||||
|
INNER JOIN project ON atc.project_id = project.id
|
||||||
|
WHERE t.test_plan_id = #{request.testPlanId}
|
||||||
|
AND atc.deleted = #{deleted}
|
||||||
|
<include refid="queryApiCaseWhereCondition"/>
|
||||||
|
GROUP BY module_id
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectIdByProjectIdAndTestPlanId" resultType="java.lang.String">
|
||||||
|
SELECT adm.id, adm.project_id
|
||||||
|
FROM api_definition_module adm
|
||||||
|
WHERE adm.id IN (
|
||||||
|
SELECT ad.module_id FROM api_definition ad LEFT JOIN api_test_case atc on atc.api_definition_id = ad.id LEFT JOIN test_plan_api_case tpac ON tpac.api_case_id = atc.id WHERE tpac.test_plan_id = #{testPlanId} AND atc.deleted = false and atc.project_id = #{projectId}
|
||||||
|
)
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="caseCount"
|
||||||
|
resultType="java.lang.Long">
|
||||||
|
SELECT count(atc.id)
|
||||||
|
FROM test_plan_api_case t
|
||||||
|
LEFT JOIN api_test_case atc ON t.api_case_id = atc.id
|
||||||
|
LEFT JOIN api_definition a on atc.api_definition_id = a.id
|
||||||
|
WHERE t.test_plan_id = #{request.testPlanId}
|
||||||
|
AND atc.deleted = #{deleted}
|
||||||
|
<include refid="queryApiCaseWhereCondition"/>
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
|
@ -2,8 +2,10 @@ package io.metersphere.plan.service;
|
||||||
|
|
||||||
import io.metersphere.api.dto.definition.ApiDefinitionDTO;
|
import io.metersphere.api.dto.definition.ApiDefinitionDTO;
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||||
|
import io.metersphere.api.service.definition.ApiDefinitionModuleService;
|
||||||
import io.metersphere.api.service.definition.ApiDefinitionService;
|
import io.metersphere.api.service.definition.ApiDefinitionService;
|
||||||
import io.metersphere.api.service.definition.ApiTestCaseService;
|
import io.metersphere.api.service.definition.ApiTestCaseService;
|
||||||
|
import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO;
|
||||||
import io.metersphere.plan.domain.TestPlanApiCaseExample;
|
import io.metersphere.plan.domain.TestPlanApiCaseExample;
|
||||||
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
||||||
import io.metersphere.plan.dto.request.TestPlanApiCaseRequest;
|
import io.metersphere.plan.dto.request.TestPlanApiCaseRequest;
|
||||||
|
@ -11,19 +13,21 @@ import io.metersphere.plan.dto.request.TestPlanApiRequest;
|
||||||
import io.metersphere.plan.dto.response.TestPlanApiCasePageResponse;
|
import io.metersphere.plan.dto.response.TestPlanApiCasePageResponse;
|
||||||
import io.metersphere.plan.mapper.ExtTestPlanApiCaseMapper;
|
import io.metersphere.plan.mapper.ExtTestPlanApiCaseMapper;
|
||||||
import io.metersphere.plan.mapper.TestPlanApiCaseMapper;
|
import io.metersphere.plan.mapper.TestPlanApiCaseMapper;
|
||||||
import io.metersphere.plan.mapper.TestPlanCollectionMapper;
|
|
||||||
import io.metersphere.project.domain.Project;
|
import io.metersphere.project.domain.Project;
|
||||||
import io.metersphere.project.domain.ProjectExample;
|
import io.metersphere.project.domain.ProjectExample;
|
||||||
|
import io.metersphere.project.dto.ModuleCountDTO;
|
||||||
import io.metersphere.project.mapper.ProjectMapper;
|
import io.metersphere.project.mapper.ProjectMapper;
|
||||||
import io.metersphere.sdk.constants.ModuleConstants;
|
import io.metersphere.sdk.constants.ModuleConstants;
|
||||||
import io.metersphere.sdk.domain.Environment;
|
import io.metersphere.sdk.domain.Environment;
|
||||||
import io.metersphere.sdk.domain.EnvironmentExample;
|
import io.metersphere.sdk.domain.EnvironmentExample;
|
||||||
import io.metersphere.sdk.mapper.EnvironmentMapper;
|
import io.metersphere.sdk.mapper.EnvironmentMapper;
|
||||||
|
import io.metersphere.sdk.util.BeanUtils;
|
||||||
|
import io.metersphere.sdk.util.Translator;
|
||||||
|
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||||
import io.metersphere.system.service.UserLoginService;
|
import io.metersphere.system.service.UserLoginService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.ibatis.session.SqlSessionFactory;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@ -36,8 +40,6 @@ import java.util.stream.Collectors;
|
||||||
@Service
|
@Service
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public class TestPlanApiCaseService extends TestPlanResourceService {
|
public class TestPlanApiCaseService extends TestPlanResourceService {
|
||||||
@Resource
|
|
||||||
private SqlSessionFactory sqlSessionFactory;
|
|
||||||
@Resource
|
@Resource
|
||||||
private TestPlanApiCaseMapper testPlanApiCaseMapper;
|
private TestPlanApiCaseMapper testPlanApiCaseMapper;
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -53,7 +55,8 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
|
||||||
@Resource
|
@Resource
|
||||||
private UserLoginService userLoginService;
|
private UserLoginService userLoginService;
|
||||||
@Resource
|
@Resource
|
||||||
private TestPlanCollectionMapper testPlanCollectionMapper;
|
private ApiDefinitionModuleService apiDefinitionModuleService;
|
||||||
|
private static final String CASE_MODULE_COUNT_ALL = "all";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
|
public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
|
||||||
|
@ -192,4 +195,47 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
|
||||||
List<Project> projectList = projectMapper.selectByExample(projectExample);
|
List<Project> projectList = projectMapper.selectByExample(projectExample);
|
||||||
return projectList.stream().collect(Collectors.toMap(Project::getId, Project::getName));
|
return projectList.stream().collect(Collectors.toMap(Project::getId, Project::getName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Map<String, Long> moduleCount(TestPlanApiCaseRequest request) {
|
||||||
|
request.setModuleIds(null);
|
||||||
|
List<FunctionalCaseModuleCountDTO> projectModuleCountDTOList = extTestPlanApiCaseMapper.countModuleIdByRequest(request, false);
|
||||||
|
Map<String, List<FunctionalCaseModuleCountDTO>> projectCountMap = projectModuleCountDTOList.stream().collect(Collectors.groupingBy(FunctionalCaseModuleCountDTO::getProjectId));
|
||||||
|
Map<String, Long> projectModuleCountMap = new HashMap<>();
|
||||||
|
projectCountMap.forEach((projectId, moduleCountDTOList) -> {
|
||||||
|
List<ModuleCountDTO> moduleCountDTOS = new ArrayList<>();
|
||||||
|
for (FunctionalCaseModuleCountDTO functionalCaseModuleCountDTO : moduleCountDTOList) {
|
||||||
|
ModuleCountDTO moduleCountDTO = new ModuleCountDTO();
|
||||||
|
BeanUtils.copyBean(moduleCountDTO, functionalCaseModuleCountDTO);
|
||||||
|
moduleCountDTOS.add(moduleCountDTO);
|
||||||
|
}
|
||||||
|
int sum = moduleCountDTOList.stream().mapToInt(FunctionalCaseModuleCountDTO::getDataCount).sum();
|
||||||
|
Map<String, Long> moduleCountMap = getModuleCountMap(projectId, request.getTestPlanId(), moduleCountDTOS);
|
||||||
|
moduleCountMap.forEach((k, v) -> {
|
||||||
|
if (projectModuleCountMap.get(k) == null || projectModuleCountMap.get(k) == 0L) {
|
||||||
|
projectModuleCountMap.put(k, v);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
projectModuleCountMap.put(projectId, (long) sum);
|
||||||
|
});
|
||||||
|
//查出全部用例数量
|
||||||
|
long allCount = extTestPlanApiCaseMapper.caseCount(request, false);
|
||||||
|
projectModuleCountMap.put(CASE_MODULE_COUNT_ALL, allCount);
|
||||||
|
return projectModuleCountMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Long> getModuleCountMap(String projectId, String testPlanId, List<ModuleCountDTO> moduleCountDTOList) {
|
||||||
|
//构建模块树,并计算每个节点下的所有数量(包含子节点)
|
||||||
|
List<BaseTreeNode> treeNodeList = this.getTreeOnlyIdsAndResourceCount(projectId, testPlanId, moduleCountDTOList);
|
||||||
|
//通过广度遍历的方式构建返回值
|
||||||
|
return apiDefinitionModuleService.getIdCountMapByBreadth(treeNodeList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<BaseTreeNode> getTreeOnlyIdsAndResourceCount(String projectId, String testPlanId, List<ModuleCountDTO> moduleCountDTOList) {
|
||||||
|
//节点内容只有Id和parentId
|
||||||
|
List<String> moduleIds = extTestPlanApiCaseMapper.selectIdByProjectIdAndTestPlanId(projectId, testPlanId);
|
||||||
|
List<BaseTreeNode> nodeByNodeIds = apiDefinitionModuleService.getNodeByNodeIds(moduleIds);
|
||||||
|
return apiDefinitionModuleService.buildTreeAndCountResource(nodeByNodeIds, moduleCountDTOList, true, Translator.get("functional_case.module.default.name"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.util.HashMap;
|
||||||
public class TestPlanApiCaseControllerTests extends BaseTest {
|
public class TestPlanApiCaseControllerTests extends BaseTest {
|
||||||
|
|
||||||
public static final String API_CASE_PAGE = "/test-plan/api/case/page";
|
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";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1)
|
@Order(1)
|
||||||
|
@ -41,4 +42,20 @@ public class TestPlanApiCaseControllerTests extends BaseTest {
|
||||||
Assertions.assertNotNull(resultHolder);
|
Assertions.assertNotNull(resultHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(2)
|
||||||
|
public void testApiCaseCount() throws Exception {
|
||||||
|
TestPlanApiCaseRequest request = new TestPlanApiCaseRequest();
|
||||||
|
request.setTestPlanId("wxxx_1");
|
||||||
|
request.setProjectId("wxx_1234");
|
||||||
|
request.setProtocol("HTTP");
|
||||||
|
request.setCurrent(1);
|
||||||
|
request.setPageSize(10);
|
||||||
|
MvcResult mvcResult = this.requestPostWithOkAndReturn(API_CASE_TREE_COUNT, request);
|
||||||
|
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||||
|
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||||
|
Assertions.assertNotNull(resultHolder);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue