fix(测试用例): 测试用例详情中,针对测试计划的状态筛选功能完善

This commit is contained in:
Jianguo-Genius 2024-07-25 17:19:52 +08:00 committed by 建国
parent 09a76cf9b0
commit 6ec9bf4963
21 changed files with 393 additions and 87 deletions

View File

@ -0,0 +1,7 @@
package io.metersphere.provider;
import java.util.List;
public interface BaseTestPlanProvider {
List<String> selectTestPlanIdByFunctionCaseAndStatus(String caseId, List<String> statusList);
}

View File

@ -84,18 +84,23 @@
test_plan_functional_case tpfc test_plan_functional_case tpfc
LEFT JOIN test_plan tp ON tpfc.test_plan_id = tp.id LEFT JOIN test_plan tp ON tpfc.test_plan_id = tp.id
LEFT JOIN project p ON tp.project_id = p.id LEFT JOIN project p ON tp.project_id = p.id
WHERE tpfc.functional_case_id = #{request.caseId} <where>
<if test="request.keyword != null"> tpfc.functional_case_id = #{request.caseId}
AND
( <if test="request.keyword != null">
tp.name LIKE concat('%', #{request.keyword},'%') AND
OR tp.num LIKE concat('%', #{request.keyword},'%') (
) tp.name LIKE concat('%', #{request.keyword},'%')
</if> OR tp.num LIKE concat('%', #{request.keyword},'%')
<include refid="planFilters"> )
<property name="filter" value="request.filter"/> </if>
</include> <include refid="planFilters">
order by tpfc.last_exec_time desc) as r group by r.test_plan_id <property name="filter" value="request.filter"/>
</include>
</where>
order by tpfc.last_exec_time desc) as r
group by r.test_plan_id
</select> </select>
<select id="getPlanExecuteHistoryList" resultType="io.metersphere.functional.dto.TestPlanCaseExecuteHistoryDTO"> <select id="getPlanExecuteHistoryList" resultType="io.metersphere.functional.dto.TestPlanCaseExecuteHistoryDTO">
@ -193,8 +198,19 @@
<if test="values != null and values.size() > 0"> <if test="values != null and values.size() > 0">
<choose> <choose>
<when test="key=='planStatus'"> <when test="key=='planStatus'">
AND tp.status in AND
(
tp.status in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/> <include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
<if test="request.includeTestPlanIds != null and request.includeTestPlanIds.size() > 0 ">
OR tpfc.test_plan_id in
<foreach collection="request.includeTestPlanIds" item="testPlanId" open="(" close=")"
separator=",">
#{testPlanId}
</foreach>
</if>
)
</when> </when>
<when test="key=='lastExecResult'"> <when test="key=='lastExecResult'">
AND tpfc.last_exec_result in AND tpfc.last_exec_result in

View File

@ -8,6 +8,8 @@ import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.util.List;
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class AssociatePlanPageRequest extends BaseProviderCondition { public class AssociatePlanPageRequest extends BaseProviderCondition {
@ -26,4 +28,7 @@ public class AssociatePlanPageRequest extends BaseProviderCondition {
@Max(value = 500, message = "每页显示条数不能大于500") @Max(value = 500, message = "每页显示条数不能大于500")
@Schema(description = "每页显示条数") @Schema(description = "每页显示条数")
private int pageSize; private int pageSize;
@Schema(description = "要包含的测试计划ID")
private List<String> includeTestPlanIds;
} }

View File

@ -19,7 +19,9 @@ import io.metersphere.functional.request.FunctionalCaseTestRequest;
import io.metersphere.provider.BaseAssociateApiProvider; import io.metersphere.provider.BaseAssociateApiProvider;
import io.metersphere.provider.BaseAssociateBugProvider; import io.metersphere.provider.BaseAssociateBugProvider;
import io.metersphere.provider.BaseAssociateScenarioProvider; import io.metersphere.provider.BaseAssociateScenarioProvider;
import io.metersphere.provider.BaseTestPlanProvider;
import io.metersphere.request.*; import io.metersphere.request.*;
import io.metersphere.sdk.constants.TestPlanConstants;
import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.dto.sdk.BaseTreeNode; import io.metersphere.system.dto.sdk.BaseTreeNode;
@ -30,7 +32,6 @@ import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils; import org.mybatis.spring.SqlSessionUtils;
import org.redisson.api.IdGenerator;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -54,6 +55,9 @@ public class FunctionalTestCaseService {
@Resource @Resource
private BaseAssociateScenarioProvider associateScenarioProvider; private BaseAssociateScenarioProvider associateScenarioProvider;
@Resource
private BaseTestPlanProvider baseTestPlanProvider;
@Resource @Resource
SqlSessionFactory sqlSessionFactory; SqlSessionFactory sqlSessionFactory;
@ -260,9 +264,27 @@ public class FunctionalTestCaseService {
* @return List<FunctionalCaseTestPlanDTO> * @return List<FunctionalCaseTestPlanDTO>
*/ */
public List<FunctionalCaseTestPlanDTO> hasAssociatePlanPage(AssociatePlanPageRequest request) { public List<FunctionalCaseTestPlanDTO> hasAssociatePlanPage(AssociatePlanPageRequest request) {
this.initDefaultFilter(request);
return extFunctionalCaseTestMapper.getPlanList(request); return extFunctionalCaseTestMapper.getPlanList(request);
} }
private void initDefaultFilter(AssociatePlanPageRequest request) {
if (request.getFilter() != null && request.getFilter().get("planStatus") != null) {
List<String> statusList = new ArrayList<>(request.getFilter().get("planStatus"));
if (statusList.contains(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
statusList.remove(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED);
}
if (statusList.size() < 3 && baseTestPlanProvider != null) {
//目前未归档的测试计划只有3中类型所以这里判断如果是3个的话等于直接查询未归档
request.setIncludeTestPlanIds(baseTestPlanProvider.selectTestPlanIdByFunctionCaseAndStatus(request.getCaseId(), statusList));
}
}
}
public List<TestPlanCaseExecuteHistoryDTO> getTestPlanCaseExecuteHistory(String caseId) { public List<TestPlanCaseExecuteHistoryDTO> getTestPlanCaseExecuteHistory(String caseId) {
List<TestPlanCaseExecuteHistoryDTO> planExecuteHistoryList = extFunctionalCaseTestMapper.getPlanExecuteHistoryList(caseId, null); List<TestPlanCaseExecuteHistoryDTO> planExecuteHistoryList = extFunctionalCaseTestMapper.getPlanExecuteHistoryList(caseId, null);
for (TestPlanCaseExecuteHistoryDTO planCaseExecuteHistoryDTO : planExecuteHistoryList) { for (TestPlanCaseExecuteHistoryDTO planCaseExecuteHistoryDTO : planExecuteHistoryList) {

View File

@ -0,0 +1,16 @@
package io.metersphere.functional.provider;
import io.metersphere.provider.BaseTestPlanProvider;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service("TEST-PLAN")
public class TestPlanProvider implements BaseTestPlanProvider {
@Override
public List<String> selectTestPlanIdByFunctionCaseAndStatus(String caseId, List<String> statusList) {
return new ArrayList<>();
}
}

View File

@ -0,0 +1,20 @@
package io.metersphere.plan;
import io.metersphere.plan.service.TestPlanManagementService;
import io.metersphere.provider.BaseTestPlanProvider;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("TEST-PLAN")
public class TestPlanProvider implements BaseTestPlanProvider {
@Resource
private TestPlanManagementService testPlanManagementService;
@Override
public List<String> selectTestPlanIdByFunctionCaseAndStatus(String caseId, List<String> statusList) {
return testPlanManagementService.selectTestPlanIdByFuncCaseIdAndStatus(caseId, statusList);
}
}

View File

@ -76,4 +76,6 @@ public interface ExtTestPlanApiCaseMapper {
List<TestPlanApiCase> getPlanApiCaseNotDeletedByCollectionIds(@Param("collectionIds") List<String> collectionIds); List<TestPlanApiCase> getPlanApiCaseNotDeletedByCollectionIds(@Param("collectionIds") List<String> collectionIds);
List<TestPlanResourceExecResultDTO> selectDistinctExecResult(String projectId); List<TestPlanResourceExecResultDTO> selectDistinctExecResult(String projectId);
List<TestPlanResourceExecResultDTO> selectDistinctExecResultByTestPlanIds(@Param("testPlanIds") List<String> testPlanIds);
} }

View File

@ -736,4 +736,27 @@
where test_plan.project_id = #{projectId} where test_plan.project_id = #{projectId}
AND test_plan.status != 'ARCHIVED' AND test_plan.status != 'ARCHIVED'
</select> </select>
<select id="selectDistinctExecResultByTestPlanIds"
resultType="io.metersphere.plan.dto.TestPlanResourceExecResultDTO">
select distinct resource.test_plan_id AS testPlanId,
CASE
WHEN resource.last_exec_result = 'BLOCKED'
THEN 'COMPLETED'
WHEN resource.last_exec_result = 'FAKE_ERROR'
THEN 'COMPLETED'
WHEN resource.last_exec_result = 'ERROR'
THEN 'COMPLETED'
WHEN resource.last_exec_result = 'SUCCESS'
THEN 'COMPLETED'
ELSE 'PENDING'
END AS execResult,
test_plan.group_id AS testPlanGroupId
from test_plan_api_case resource
INNER JOIN test_plan ON test_plan.id = resource.test_plan_id
where test_plan.id IN
<foreach collection="testPlanIds" item="testPlanId" separator="," open="(" close=")">
#{testPlanId}
</foreach>
AND test_plan.status != 'ARCHIVED'
</select>
</mapper> </mapper>

View File

@ -72,4 +72,6 @@ public interface ExtTestPlanApiScenarioMapper {
List<TestPlanApiScenario> getPlanScenarioCaseNotDeletedByCollectionIds(@Param("collectionIds") List<String> collectionIds); List<TestPlanApiScenario> getPlanScenarioCaseNotDeletedByCollectionIds(@Param("collectionIds") List<String> collectionIds);
List<TestPlanResourceExecResultDTO> selectDistinctExecResult(String projectId); List<TestPlanResourceExecResultDTO> selectDistinctExecResult(String projectId);
List<TestPlanResourceExecResultDTO> selectDistinctExecResultByTestPlanIds(@Param("testPlanIds") List<String> testPlanIds);
} }

View File

@ -504,6 +504,29 @@
where test_plan.project_id = #{projectId} where test_plan.project_id = #{projectId}
AND test_plan.status != 'ARCHIVED' AND test_plan.status != 'ARCHIVED'
</select> </select>
<select id="selectDistinctExecResultByTestPlanIds"
resultType="io.metersphere.plan.dto.TestPlanResourceExecResultDTO">
select distinct resource.test_plan_id AS testPlanId,
CASE
WHEN resource.last_exec_result = 'BLOCKED'
THEN 'COMPLETED'
WHEN resource.last_exec_result = 'FAKE_ERROR'
THEN 'COMPLETED'
WHEN resource.last_exec_result = 'ERROR'
THEN 'COMPLETED'
WHEN resource.last_exec_result = 'SUCCESS'
THEN 'COMPLETED'
ELSE 'PENDING'
END AS execResult,
test_plan.group_id AS testPlanGroupId
from test_plan_api_scenario resource
INNER JOIN test_plan ON test_plan.id = resource.test_plan_id
where test_plan.id IN
<foreach collection="testPlanIds" item="testPlanId" separator="," open="(" close=")">
#{testPlanId}
</foreach>
AND test_plan.status != 'ARCHIVED'
</select>
<update id="batchUpdateExecutor"> <update id="batchUpdateExecutor">

View File

@ -69,4 +69,8 @@ public interface ExtTestPlanFunctionalCaseMapper {
List<TestPlanFunctionalCase> getPlanCaseNotDeletedByCollectionIds(@Param("collectionIds") List<String> collectionIds); List<TestPlanFunctionalCase> getPlanCaseNotDeletedByCollectionIds(@Param("collectionIds") List<String> collectionIds);
List<TestPlanResourceExecResultDTO> selectDistinctExecResult(String projectId); List<TestPlanResourceExecResultDTO> selectDistinctExecResult(String projectId);
List<String> selectTestPlanIdByFunctionCaseId(String functionalCaseId);
List<TestPlanResourceExecResultDTO> selectDistinctExecResultByTestPlanIds(@Param("testPlanIds") List<String> testPlanIds);
} }

View File

@ -597,4 +597,33 @@
where test_plan.project_id = #{projectId} where test_plan.project_id = #{projectId}
AND test_plan.status != 'ARCHIVED' AND test_plan.status != 'ARCHIVED'
</select> </select>
<select id="selectTestPlanIdByFunctionCaseId" resultType="java.lang.String">
SELECT DISTINCT test_plan_id
FROM test_plan_functional_case
WHERE functional_case_id = #{0}
</select>
<select id="selectDistinctExecResultByTestPlanIds"
resultType="io.metersphere.plan.dto.TestPlanResourceExecResultDTO">
select distinct resource.test_plan_id AS testPlanId,
CASE
WHEN resource.last_exec_result = 'BLOCKED'
THEN 'COMPLETED'
WHEN resource.last_exec_result = 'FAKE_ERROR'
THEN 'COMPLETED'
WHEN resource.last_exec_result = 'ERROR'
THEN 'COMPLETED'
WHEN resource.last_exec_result = 'SUCCESS'
THEN 'COMPLETED'
ELSE 'PENDING'
END AS execResult,
test_plan.group_id AS testPlanGroupId
from test_plan_functional_case resource
INNER JOIN test_plan ON test_plan.id = resource.test_plan_id
where test_plan.id IN
<foreach collection="testPlanIds" item="testPlanId" separator="," open="(" close=")">
#{testPlanId}
</foreach>
AND test_plan.status != 'ARCHIVED'
</select>
</mapper> </mapper>

View File

@ -118,10 +118,15 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
@Resource @Resource
private ExtApiTestCaseMapper extApiTestCaseMapper; private ExtApiTestCaseMapper extApiTestCaseMapper;
public List<TestPlanResourceExecResultDTO> selectDistinctExecResult(String projectId) { public List<TestPlanResourceExecResultDTO> selectDistinctExecResultByProjectId(String projectId) {
return extTestPlanApiCaseMapper.selectDistinctExecResult(projectId); return extTestPlanApiCaseMapper.selectDistinctExecResult(projectId);
} }
@Override
public List<TestPlanResourceExecResultDTO> selectDistinctExecResultByTestPlanIds(List<String> testPlanIds) {
return extTestPlanApiCaseMapper.selectDistinctExecResultByTestPlanIds(testPlanIds);
}
@Override @Override
public void deleteBatchByTestPlanId(List<String> testPlanIdList) { public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
TestPlanApiCaseExample example = new TestPlanApiCaseExample(); TestPlanApiCaseExample example = new TestPlanApiCaseExample();

View File

@ -110,10 +110,15 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
private TestPlanConfigService testPlanConfigService; private TestPlanConfigService testPlanConfigService;
@Override @Override
public List<TestPlanResourceExecResultDTO> selectDistinctExecResult(String projectId) { public List<TestPlanResourceExecResultDTO> selectDistinctExecResultByProjectId(String projectId) {
return extTestPlanApiScenarioMapper.selectDistinctExecResult(projectId); return extTestPlanApiScenarioMapper.selectDistinctExecResult(projectId);
} }
@Override
public List<TestPlanResourceExecResultDTO> selectDistinctExecResultByTestPlanIds(List<String> testPlanIds) {
return extTestPlanApiScenarioMapper.selectDistinctExecResultByTestPlanIds(testPlanIds);
}
@Override @Override
public void deleteBatchByTestPlanId(List<String> testPlanIdList) { public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample(); TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();

View File

@ -76,9 +76,10 @@ public class TestPlanBaseUtilsService {
} }
public String calculateTestPlanStatus(List<String> resultList) { public String calculateTestPlanStatus(List<String> resultList) {
//同时包含两种状态进行中 List<String> calculateList = resultList.stream().distinct().toList();
if (resultList.size() == 1) { //目前只有三个状态如果同时包含多种状态(进行中/未开始进行中/已完成已完成/未开始进行中/未开始/已完成),根据算法可得测试计划都会是进行中
if (resultList.contains(TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED)) { if (calculateList.size() == 1) {
if (calculateList.contains(TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED)) {
return TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED; return TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED;
} else } else
return TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED; return TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED;

View File

@ -64,7 +64,12 @@ public class TestPlanBugService extends TestPlanResourceService {
} }
@Override @Override
public List<TestPlanResourceExecResultDTO> selectDistinctExecResult(String projectId) { public List<TestPlanResourceExecResultDTO> selectDistinctExecResultByProjectId(String projectId) {
return List.of();
}
@Override
public List<TestPlanResourceExecResultDTO> selectDistinctExecResultByTestPlanIds(List<String> testPlanIds) {
return List.of(); return List.of();
} }

View File

@ -139,10 +139,15 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
private TestPlanApiScenarioMapper testPlanApiScenarioMapper; private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
@Override @Override
public List<TestPlanResourceExecResultDTO> selectDistinctExecResult(String projectId) { public List<TestPlanResourceExecResultDTO> selectDistinctExecResultByProjectId(String projectId) {
return extTestPlanFunctionalCaseMapper.selectDistinctExecResult(projectId); return extTestPlanFunctionalCaseMapper.selectDistinctExecResult(projectId);
} }
@Override
public List<TestPlanResourceExecResultDTO> selectDistinctExecResultByTestPlanIds(List<String> testPlanIds) {
return extTestPlanFunctionalCaseMapper.selectDistinctExecResultByTestPlanIds(testPlanIds);
}
@Override @Override
public long copyResource(String originalTestPlanId, String newTestPlanId, Map<String, String> oldCollectionIdToNewCollectionId, String operator, long operatorTime) { public long copyResource(String originalTestPlanId, String newTestPlanId, Map<String, String> oldCollectionIdToNewCollectionId, String operator, long operatorTime) {
List<TestPlanFunctionalCase> copyList = new ArrayList<>(); List<TestPlanFunctionalCase> copyList = new ArrayList<>();

View File

@ -9,6 +9,7 @@ import io.metersphere.plan.dto.TestPlanGroupCountDTO;
import io.metersphere.plan.dto.TestPlanResourceExecResultDTO; import io.metersphere.plan.dto.TestPlanResourceExecResultDTO;
import io.metersphere.plan.dto.request.TestPlanTableRequest; import io.metersphere.plan.dto.request.TestPlanTableRequest;
import io.metersphere.plan.dto.response.TestPlanResponse; import io.metersphere.plan.dto.response.TestPlanResponse;
import io.metersphere.plan.mapper.ExtTestPlanFunctionalCaseMapper;
import io.metersphere.plan.mapper.ExtTestPlanMapper; import io.metersphere.plan.mapper.ExtTestPlanMapper;
import io.metersphere.plan.mapper.ExtTestPlanModuleMapper; import io.metersphere.plan.mapper.ExtTestPlanModuleMapper;
import io.metersphere.plan.mapper.TestPlanMapper; import io.metersphere.plan.mapper.TestPlanMapper;
@ -22,6 +23,7 @@ import io.metersphere.sdk.util.Translator;
import io.metersphere.system.utils.PageUtils; import io.metersphere.system.utils.PageUtils;
import io.metersphere.system.utils.Pager; import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotEmpty;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils; import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -43,6 +45,8 @@ public class TestPlanManagementService {
@Resource @Resource
private ExtTestPlanModuleMapper extTestPlanModuleMapper; private ExtTestPlanModuleMapper extTestPlanModuleMapper;
@Resource @Resource
private ExtTestPlanFunctionalCaseMapper extTestPlanFunctionalCaseMapper;
@Resource
private TestPlanModuleService testPlanModuleService; private TestPlanModuleService testPlanModuleService;
@Resource @Resource
private TestPlanStatisticsService testPlanStatisticsService; private TestPlanStatisticsService testPlanStatisticsService;
@ -75,6 +79,110 @@ public class TestPlanManagementService {
return PageUtils.setPageInfo(page, this.list(request)); return PageUtils.setPageInfo(page, this.list(request));
} }
public void filterTestPlanIdWithStatus(Map<String, List<String>> testPlanExecMap, List<String> completedTestPlanIds, List<String> preparedTestPlanIds, List<String> underwayTestPlanIds) {
testPlanExecMap.forEach((planId, resultList) -> {
String result = testPlanBaseUtilsService.calculateTestPlanStatus(resultList);
if (StringUtils.equals(result, TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED)) {
completedTestPlanIds.add(planId);
} else if (StringUtils.equals(result, TestPlanConstants.TEST_PLAN_SHOW_STATUS_UNDERWAY)) {
underwayTestPlanIds.add(planId);
} else if (StringUtils.equals(result, TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED)) {
preparedTestPlanIds.add(planId);
}
});
}
public List<String> selectTestPlanIdByFuncCaseIdAndStatus(String functionalCaseId, @NotEmpty List<String> statusList) {
List<String> returnIdList = new ArrayList<>();
List<String> testPlanIdList = extTestPlanFunctionalCaseMapper.selectTestPlanIdByFunctionCaseId(functionalCaseId);
if (CollectionUtils.isEmpty(testPlanIdList)) {
return new ArrayList<>();
}
List<String> completedTestPlanIds = new ArrayList<>();
List<String> preparedTestPlanIds = new ArrayList<>();
List<String> underwayTestPlanIds = new ArrayList<>();
Map<String, TestPlanResourceService> beansOfType = applicationContext.getBeansOfType(TestPlanResourceService.class);
// 将当前项目下未归档的测试计划结果查询出来进行下列符合条件的筛选
List<TestPlanResourceExecResultDTO> execResults = new ArrayList<>();
beansOfType.forEach((k, v) -> execResults.addAll(v.selectDistinctExecResultByTestPlanIds(testPlanIdList)));
Map<String, List<String>> testPlanExecMap = execResults.stream().collect(
Collectors.groupingBy(TestPlanResourceExecResultDTO::getTestPlanId, Collectors.mapping(TestPlanResourceExecResultDTO::getExecResult, Collectors.toList())));
this.filterTestPlanIdWithStatus(testPlanExecMap, completedTestPlanIds, preparedTestPlanIds, underwayTestPlanIds);
if (statusList.contains(TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED)) {
// 已完成
returnIdList.addAll(completedTestPlanIds);
}
if (statusList.contains(TestPlanConstants.TEST_PLAN_SHOW_STATUS_UNDERWAY)) {
// 进行中
returnIdList.addAll(underwayTestPlanIds);
}
if (statusList.contains(TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED)) {
// 未开始
returnIdList.addAll(preparedTestPlanIds);
}
return returnIdList;
}
private List<String> selectTestPlanIdByProjectIdAndStatus(String projectId, @NotEmpty List<String> statusList) {
List<String> innerIdList = new ArrayList<>();
Map<String, TestPlanResourceService> beansOfType = applicationContext.getBeansOfType(TestPlanResourceService.class);
// 将当前项目下未归档的测试计划结果查询出来进行下列符合条件的筛选
List<TestPlanResourceExecResultDTO> execResults = new ArrayList<>();
beansOfType.forEach((k, v) -> execResults.addAll(v.selectDistinctExecResultByProjectId(projectId)));
Map<String, Map<String, List<String>>> testPlanExecMap = testPlanBaseUtilsService.parseExecResult(execResults);
Map<String, Long> groupCountMap = extTestPlanMapper.countByGroupPlan(projectId)
.stream().collect(Collectors.toMap(TestPlanGroupCountDTO::getGroupId, TestPlanGroupCountDTO::getCount));
List<String> completedTestPlanIds = new ArrayList<>();
List<String> preparedTestPlanIds = new ArrayList<>();
List<String> underwayTestPlanIds = new ArrayList<>();
testPlanExecMap.forEach((groupId, planMap) -> {
if (StringUtils.equalsIgnoreCase(groupId, TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
this.filterTestPlanIdWithStatus(planMap, completedTestPlanIds, preparedTestPlanIds, underwayTestPlanIds);
} else {
long itemPlanCount = groupCountMap.getOrDefault(groupId, 0L);
List<String> itemStatusList = new ArrayList<>();
if (itemPlanCount > planMap.size()) {
// 存在未执行或者没有用例的测试计划 此时这种测试计划的状态为未开始
itemStatusList.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED);
}
planMap.forEach((planId, resultList) -> {
itemStatusList.add(testPlanBaseUtilsService.calculateTestPlanStatus(resultList));
});
String groupStatus = testPlanBaseUtilsService.calculateStatusByChildren(itemStatusList);
if (StringUtils.equals(groupStatus, TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED)) {
completedTestPlanIds.add(groupId);
} else if (StringUtils.equals(groupStatus, TestPlanConstants.TEST_PLAN_SHOW_STATUS_UNDERWAY)) {
underwayTestPlanIds.add(groupId);
} else if (StringUtils.equals(groupStatus, TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED)) {
preparedTestPlanIds.add(groupId);
}
}
});
testPlanExecMap = null;
if (statusList.contains(TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED)) {
// 已完成
innerIdList.addAll(completedTestPlanIds);
}
if (statusList.contains(TestPlanConstants.TEST_PLAN_SHOW_STATUS_UNDERWAY)) {
// 进行中
innerIdList.addAll(underwayTestPlanIds);
}
if (statusList.contains(TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED)) {
// 未开始 有一些测试计划/计划组没有用例 / 测试计划 在上面的计算中无法过滤所以用排除法机型处理
List<String> withoutList = new ArrayList<>();
withoutList.addAll(completedTestPlanIds);
withoutList.addAll(underwayTestPlanIds);
innerIdList.addAll(extTestPlanMapper.selectIdByProjectIdAndWithoutList(projectId, withoutList));
}
return innerIdList;
}
@Autowired @Autowired
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
private void initDefaultFilter(TestPlanTableRequest request) { private void initDefaultFilter(TestPlanTableRequest request) {
@ -92,72 +200,9 @@ public class TestPlanManagementService {
} else if (!request.getFilter().get("status").contains(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) { } else if (!request.getFilter().get("status").contains(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
List<String> statusList = request.getFilter().get("status"); List<String> statusList = request.getFilter().get("status");
request.getFilter().put("status", defaultStatusList); request.getFilter().put("status", defaultStatusList);
//目前未归档的测试计划只有3中类型所以这里判断如果是3个的话等于直接查询未归档
if (statusList.size() < 3) { if (statusList.size() < 3) {
List<String> innerIdList = new ArrayList<>(); request.setInnerIds(this.selectTestPlanIdByProjectIdAndStatus(request.getProjectId(), statusList));
// 条件过滤
Map<String, TestPlanResourceService> beansOfType = applicationContext.getBeansOfType(TestPlanResourceService.class);
// 将当前项目下未归档的测试计划结果查询出来进行下列符合条件的筛选
List<TestPlanResourceExecResultDTO> execResults = new ArrayList<>();
beansOfType.forEach((k, v) -> execResults.addAll(v.selectDistinctExecResult(request.getProjectId())));
Map<String, Map<String, List<String>>> testPlanExecMap = testPlanBaseUtilsService.parseExecResult(execResults);
Map<String, Long> groupCountMap = extTestPlanMapper.countByGroupPlan(request.getProjectId())
.stream().collect(Collectors.toMap(TestPlanGroupCountDTO::getGroupId, TestPlanGroupCountDTO::getCount));
List<String> completedTestPlanIds = new ArrayList<>();
List<String> preparedTestPlanIds = new ArrayList<>();
List<String> underwayTestPlanIds = new ArrayList<>();
testPlanExecMap.forEach((groupId, planMap) -> {
if (StringUtils.equalsIgnoreCase(groupId, TestPlanConstants.TEST_PLAN_DEFAULT_GROUP_ID)) {
planMap.forEach((planId, resultList) -> {
String result = testPlanBaseUtilsService.calculateTestPlanStatus(resultList);
if (StringUtils.equals(result, TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED)) {
completedTestPlanIds.add(planId);
} else if (StringUtils.equals(result, TestPlanConstants.TEST_PLAN_SHOW_STATUS_UNDERWAY)) {
underwayTestPlanIds.add(planId);
} else if (StringUtils.equals(result, TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED)) {
preparedTestPlanIds.add(planId);
}
});
} else {
long itemPlanCount = groupCountMap.getOrDefault(groupId, 0L);
List<String> itemStatusList = new ArrayList<>();
if (itemPlanCount > planMap.size()) {
// 存在未执行或者没有用例的测试计划 此时这种测试计划的状态为未开始
itemStatusList.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED);
}
planMap.forEach((planId, resultList) -> {
itemStatusList.add(testPlanBaseUtilsService.calculateTestPlanStatus(resultList));
});
String groupStatus = testPlanBaseUtilsService.calculateStatusByChildren(itemStatusList);
if (StringUtils.equals(groupStatus, TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED)) {
completedTestPlanIds.add(groupId);
} else if (StringUtils.equals(groupStatus, TestPlanConstants.TEST_PLAN_SHOW_STATUS_UNDERWAY)) {
underwayTestPlanIds.add(groupId);
} else if (StringUtils.equals(groupStatus, TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED)) {
preparedTestPlanIds.add(groupId);
}
}
});
testPlanExecMap = null;
if (statusList.contains(TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED)) {
// 已完成
innerIdList.addAll(completedTestPlanIds);
}
if (statusList.contains(TestPlanConstants.TEST_PLAN_SHOW_STATUS_UNDERWAY)) {
// 进行中
innerIdList.addAll(underwayTestPlanIds);
}
if (statusList.contains(TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED)) {
// 未开始 有一些测试计划/计划组没有用例 / 测试计划 在上面的计算中无法过滤所以用排除法机型处理
List<String> withoutList = new ArrayList<>();
withoutList.addAll(completedTestPlanIds);
withoutList.addAll(underwayTestPlanIds);
innerIdList.addAll(extTestPlanMapper.selectIdByProjectIdAndWithoutList(request.getProjectId(), withoutList));
withoutList = null;
}
request.setInnerIds(innerIdList);
} }
} }

View File

@ -68,7 +68,9 @@ public abstract class TestPlanResourceService extends TestPlanSortService {
public abstract long copyResource(String originalTestPlanId, String newTestPlanId, Map<String, String> oldCollectionIdToNewCollectionId, String operator, long operatorTime); public abstract long copyResource(String originalTestPlanId, String newTestPlanId, Map<String, String> oldCollectionIdToNewCollectionId, String operator, long operatorTime);
public abstract List<TestPlanResourceExecResultDTO> selectDistinctExecResult(String projectId); public abstract List<TestPlanResourceExecResultDTO> selectDistinctExecResultByProjectId(String projectId);
public abstract List<TestPlanResourceExecResultDTO> selectDistinctExecResultByTestPlanIds(List<String> testPlanIds);
/** /**
* 关联用例 * 关联用例

View File

@ -2,6 +2,7 @@ package io.metersphere.plan.controller;
import io.metersphere.plan.dto.request.TestPlanBugPageRequest; import io.metersphere.plan.dto.request.TestPlanBugPageRequest;
import io.metersphere.plan.dto.response.TestPlanBugPageResponse; import io.metersphere.plan.dto.response.TestPlanBugPageResponse;
import io.metersphere.plan.service.TestPlanBugService;
import io.metersphere.project.domain.Project; import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
@ -30,6 +31,8 @@ public class TestPlanBugControllerTests extends BaseTest {
@Resource @Resource
private ProjectMapper projectMapper; private ProjectMapper projectMapper;
@Resource
private TestPlanBugService testPlanBugService;
public static final String TEST_PLAN_BUG_PAGE = "/test-plan/bug/page"; public static final String TEST_PLAN_BUG_PAGE = "/test-plan/bug/page";
@ -98,4 +101,13 @@ public class TestPlanBugControllerTests extends BaseTest {
this.requestGet(TEST_PLAN_DELETE + "/test-plan-id-for-bug"); this.requestGet(TEST_PLAN_DELETE + "/test-plan-id-for-bug");
this.requestGet(TEST_PLAN_DELETE + "/test-plan-id-for-bug-1"); this.requestGet(TEST_PLAN_DELETE + "/test-plan-id-for-bug-1");
} }
@Test
@Order(4)
void emptyFunctionTest() throws Exception {
testPlanBugService.caseExecResultCount("testPlanId");
testPlanBugService.selectDistinctExecResultByTestPlanIds(null);
testPlanBugService.updatePos(null, 0);
testPlanBugService.refreshPos(null);
}
} }

View File

@ -2431,4 +2431,61 @@ public class TestPlanTests extends BaseTest {
testPlanService.deletePlanCollectionResource(List.of("init_collection-delete-4")); testPlanService.deletePlanCollectionResource(List.of("init_collection-delete-4"));
testPlanService.deletePlanCollectionResource(List.of("init_collection-delete-1", "init_collection-delete-2", "init_collection-delete-3")); testPlanService.deletePlanCollectionResource(List.of("init_collection-delete-1", "init_collection-delete-2", "init_collection-delete-3"));
} }
@Test
@Order(310)
void testStatusSelectMethod() {
//initSQL中功能用例idoasis_fc_1 的数据关联到了测试计划
List<String> testPlanStatusList = new ArrayList<>();
testPlanStatusList.add(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED);
testPlanStatusList.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED);
testPlanStatusList.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED);
testPlanStatusList.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_UNDERWAY);
testPlanManagementService.selectTestPlanIdByFuncCaseIdAndStatus("oasis_fc_1", testPlanStatusList);
testPlanStatusList = new ArrayList<>();
testPlanStatusList.add(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED);
testPlanManagementService.selectTestPlanIdByFuncCaseIdAndStatus("oasis_fc_1", testPlanStatusList);
testPlanStatusList = new ArrayList<>();
testPlanStatusList.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_PREPARED);
testPlanManagementService.selectTestPlanIdByFuncCaseIdAndStatus("oasis_fc_1", testPlanStatusList);
testPlanStatusList = new ArrayList<>();
testPlanStatusList.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED);
testPlanManagementService.selectTestPlanIdByFuncCaseIdAndStatus("oasis_fc_1", testPlanStatusList);
testPlanStatusList = new ArrayList<>();
testPlanStatusList.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_UNDERWAY);
testPlanManagementService.selectTestPlanIdByFuncCaseIdAndStatus("oasis_fc_1", testPlanStatusList);
testPlanStatusList = new ArrayList<>();
testPlanStatusList.add(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED);
testPlanStatusList.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED);
testPlanStatusList.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_UNDERWAY);
testPlanManagementService.selectTestPlanIdByFuncCaseIdAndStatus("oasis_fc_1", testPlanStatusList);
//测试不存在的数据
testPlanManagementService.selectTestPlanIdByFuncCaseIdAndStatus(IDGenerator.nextStr(), testPlanStatusList);
Map<String, List<String>> testPlanExecMap = new HashMap<>();
testPlanExecMap.put("test1", new ArrayList<>() {{
this.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED);
}});
testPlanExecMap.put("test2", new ArrayList<>() {{
this.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_UNDERWAY);
}});
testPlanExecMap.put("test3", new ArrayList<>() {{
this.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_UNDERWAY);
this.add(TestPlanConstants.TEST_PLAN_SHOW_STATUS_COMPLETED);
}});
List<String> completedTestPlanIds = new ArrayList<>();
List<String> preparedTestPlanIds = new ArrayList<>();
List<String> underwayTestPlanIds = new ArrayList<>();
testPlanManagementService.filterTestPlanIdWithStatus(testPlanExecMap, completedTestPlanIds, preparedTestPlanIds, underwayTestPlanIds);
Assertions.assertEquals(1, completedTestPlanIds.size());
Assertions.assertEquals("test1", completedTestPlanIds.getFirst());
Assertions.assertEquals(1, preparedTestPlanIds.size());
Assertions.assertEquals("test2", preparedTestPlanIds.getFirst());
Assertions.assertEquals(1, underwayTestPlanIds.size());
Assertions.assertEquals("test3", underwayTestPlanIds.getFirst());
}
} }