feat(测试计划): 测试计划统计接口开发
This commit is contained in:
parent
bc912a6fad
commit
72bd8d6b44
|
@ -59,6 +59,14 @@ public class TestPlanController {
|
|||
return testPlanManagementService.page(request);
|
||||
}
|
||||
|
||||
@PostMapping("/rage")
|
||||
@Operation(summary = "测试计划-测试计划统计")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
public TestPlanCoverageDTO rage(@Validated @RequestBody TestPlanCoverageRequest request) {
|
||||
return testPlanService.rageByProjectIdAndTimestamp(request.getProjectId(), request.getStartTime(), request.getEndTime());
|
||||
}
|
||||
|
||||
@GetMapping("/group-list/{projectId}")
|
||||
@Operation(summary = "测试计划-测试计划组查询")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ)
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package io.metersphere.plan.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
@Data
|
||||
public class TestPlanCoverageRequest {
|
||||
|
||||
@Schema(description = "固定时间天数")
|
||||
private int dayNumber = 0;
|
||||
|
||||
@Schema(description = "自定义开始时间")
|
||||
private long startTime = 0;
|
||||
|
||||
@Schema(description = "自定义结束时间")
|
||||
private long endTime = 0;
|
||||
|
||||
@Schema(description = "项目ID")
|
||||
@NotBlank
|
||||
private String projectId;
|
||||
|
||||
|
||||
public long getStartTime() {
|
||||
if (startTime == 0 && dayNumber > 0) {
|
||||
LocalDate now = LocalDate.now();
|
||||
LocalDate localDate = now.minusDays(dayNumber);
|
||||
LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MIN);//当天零点
|
||||
return localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
|
||||
} else {
|
||||
return startTime;
|
||||
}
|
||||
}
|
||||
|
||||
public long getEndTime() {
|
||||
if (endTime == 0 && dayNumber > 0) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
return now.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
|
||||
} else {
|
||||
return endTime;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package io.metersphere.plan.dto.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TestPlanCoverageDTO {
|
||||
/**
|
||||
* 未执行
|
||||
* 已执行
|
||||
*/
|
||||
private int unExecute = 0;
|
||||
private int executed = 0;
|
||||
|
||||
/**
|
||||
* 通过
|
||||
* 未通过
|
||||
*/
|
||||
private int passed = 0;
|
||||
private int notPassed = 0;
|
||||
|
||||
/**
|
||||
* 已完成
|
||||
* 进行中
|
||||
* 未开始
|
||||
* 已归档
|
||||
*/
|
||||
private int finished = 0;
|
||||
private int running = 0;
|
||||
private int prepared = 0;
|
||||
private int archived = 0;
|
||||
|
||||
public void archivedAutoIncrement() {
|
||||
archived++;
|
||||
}
|
||||
|
||||
public void notStartedAutoIncrement() {
|
||||
prepared++;
|
||||
unExecute++;
|
||||
notPassed++;
|
||||
}
|
||||
|
||||
public void successAutoIncrement() {
|
||||
executed++;
|
||||
passed++;
|
||||
finished++;
|
||||
}
|
||||
|
||||
public void unSuccessAutoIncrement() {
|
||||
executed++;
|
||||
notPassed++;
|
||||
finished++;
|
||||
}
|
||||
|
||||
public void testPlanRunningAutoIncrement() {
|
||||
unExecute++;
|
||||
notPassed++;
|
||||
running++;
|
||||
}
|
||||
}
|
|
@ -82,4 +82,6 @@ public interface ExtTestPlanApiCaseMapper {
|
|||
List<TestPlanResourceExecResultDTO> selectDistinctExecResultByTestPlanIds(@Param("testPlanIds") List<String> testPlanIds);
|
||||
|
||||
Integer countByPlanIds(@Param("planIds") List<String> planIds);
|
||||
|
||||
List<TestPlanResourceExecResultDTO> selectDistinctLastExecResultByTestPlanIds(@Param("testPlanIds") List<String> testPlanIds);
|
||||
}
|
||||
|
|
|
@ -892,6 +892,23 @@
|
|||
</foreach>
|
||||
AND test_plan.status != 'ARCHIVED'
|
||||
</select>
|
||||
|
||||
<select id="selectDistinctLastExecResultByTestPlanIds"
|
||||
resultType="io.metersphere.plan.dto.TestPlanResourceExecResultDTO">
|
||||
select distinct resource.test_plan_id AS testPlanId,
|
||||
CASE
|
||||
WHEN resource.last_exec_result is null
|
||||
THEN 'PENDING'
|
||||
WHEN resource.last_exec_result = '-'
|
||||
THEN 'PENDING'
|
||||
ELSE resource.last_exec_result
|
||||
END AS execResult
|
||||
from test_plan_api_case resource
|
||||
where resource.test_plan_id IN
|
||||
<foreach collection="testPlanIds" item="testPlanId" separator="," open="(" close=")">
|
||||
#{testPlanId}
|
||||
</foreach>
|
||||
</select>
|
||||
<select id="getBatchRunInfoByIds" resultType="io.metersphere.plan.dto.TestPlanApiCaseBatchRunDTO">
|
||||
SELECT t.id as id, t.test_plan_collection_id as test_plan_collection_id, atc.name as name, atc.id as caseId
|
||||
FROM test_plan_api_case t
|
||||
|
|
|
@ -79,4 +79,6 @@ public interface ExtTestPlanApiScenarioMapper {
|
|||
List<TestPlanApiScenarioBatchRunDTO> getBatchRunInfoByIds(@Param("ids") List<String> ids);
|
||||
|
||||
Integer countByPlanIds(@Param("planIds") List<String> planIds);
|
||||
|
||||
List<TestPlanResourceExecResultDTO> selectDistinctLastExecResultByTestPlanIds(@Param("testPlanIds") List<String> testPlanIds);
|
||||
}
|
||||
|
|
|
@ -663,4 +663,20 @@
|
|||
</foreach>
|
||||
</where>
|
||||
</select>
|
||||
<select id="selectDistinctLastExecResultByTestPlanIds"
|
||||
resultType="io.metersphere.plan.dto.TestPlanResourceExecResultDTO">
|
||||
select distinct resource.test_plan_id AS testPlanId,
|
||||
CASE
|
||||
WHEN resource.last_exec_result is null
|
||||
THEN 'PENDING'
|
||||
WHEN resource.last_exec_result = '-'
|
||||
THEN 'PENDING'
|
||||
ELSE resource.last_exec_result
|
||||
END AS execResult
|
||||
from test_plan_api_scenario resource
|
||||
where resource.test_plan_id IN
|
||||
<foreach collection="testPlanIds" item="testPlanId" separator="," open="(" close=")">
|
||||
#{testPlanId}
|
||||
</foreach>
|
||||
</select>
|
||||
</mapper>
|
|
@ -87,4 +87,6 @@ public interface ExtTestPlanFunctionalCaseMapper {
|
|||
Collection<String> selectIdsByModuleIds(@Param("request") TestPlanCaseMinderRequest request, @Param("minderModuleIds") List<String> minderModuleIds);
|
||||
|
||||
Collection<String> selectIdsByRootIds(@Param("rootIds") List<String> rootIds, @Param("testPlanId") String testPlanId);
|
||||
|
||||
List<TestPlanResourceExecResultDTO> selectDistinctLastExecResultByTestPlanIds(@Param("testPlanIds") List<String> testPlanIds);
|
||||
}
|
||||
|
|
|
@ -780,5 +780,21 @@
|
|||
</foreach>
|
||||
and functional_case.module_id = 'root'
|
||||
</select>
|
||||
<select id="selectDistinctLastExecResultByTestPlanIds"
|
||||
resultType="io.metersphere.plan.dto.TestPlanResourceExecResultDTO">
|
||||
select distinct resource.test_plan_id AS testPlanId,
|
||||
CASE
|
||||
WHEN resource.last_exec_result is null
|
||||
THEN 'PENDING'
|
||||
WHEN resource.last_exec_result = '-'
|
||||
THEN 'PENDING'
|
||||
ELSE resource.last_exec_result
|
||||
END AS execResult
|
||||
from test_plan_functional_case resource
|
||||
where resource.test_plan_id IN
|
||||
<foreach collection="testPlanIds" item="testPlanId" separator="," open="(" close=")">
|
||||
#{testPlanId}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -93,4 +93,6 @@ public interface ExtTestPlanMapper {
|
|||
* @return List<SelectOption>
|
||||
*/
|
||||
List<SelectOption> getPlanBugList(@Param("projectId") String projectId, @Param("type") String type, @Param("platforms") List<String> platform, @Param("statusList") List<String> statusList);
|
||||
|
||||
List<TestPlan> selectIdAndStatusByProjectIdAndCreateTimeRangeAndType(@Param("projectId") String projectId, @Param("startTime") long startTime, @Param("endTime") long endTime, @Param("type") String testPlanTypePlan);
|
||||
}
|
||||
|
|
|
@ -868,6 +868,13 @@
|
|||
AND test_plan.create_time BETWEEN #{startTime} AND #{endTime}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectIdAndStatusByProjectIdAndCreateTimeRangeAndType" resultType="io.metersphere.plan.domain.TestPlan">
|
||||
SELECT id, status
|
||||
FROM test_plan
|
||||
WHERE project_id = #{projectId}
|
||||
AND create_time BETWEEN #{startTime} AND #{endTime}
|
||||
AND type = #{type}
|
||||
</select>
|
||||
<select id="getPlanBugList" resultType="io.metersphere.plugin.platform.dto.SelectOption">
|
||||
select distinct bug.id as `value`, bug.status as `text`
|
||||
from test_plan
|
||||
|
|
|
@ -145,6 +145,11 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
|
|||
return extTestPlanApiCaseMapper.selectDistinctExecResultByTestPlanIds(testPlanIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TestPlanResourceExecResultDTO> selectDistinctLastExecResultByTestPlanIds(List<String> testPlanIds) {
|
||||
return extTestPlanApiCaseMapper.selectDistinctLastExecResultByTestPlanIds(testPlanIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
|
||||
TestPlanApiCaseExample example = new TestPlanApiCaseExample();
|
||||
|
|
|
@ -133,6 +133,11 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
|
|||
return extTestPlanApiScenarioMapper.selectDistinctExecResultByTestPlanIds(testPlanIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TestPlanResourceExecResultDTO> selectDistinctLastExecResultByTestPlanIds(List<String> testPlanIds) {
|
||||
return extTestPlanApiScenarioMapper.selectDistinctLastExecResultByTestPlanIds(testPlanIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
|
||||
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
|
||||
|
|
|
@ -73,6 +73,11 @@ public class TestPlanBugService extends TestPlanResourceService {
|
|||
return List.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TestPlanResourceExecResultDTO> selectDistinctLastExecResultByTestPlanIds(List<String> testPlanIds) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getNextOrder(String testPlanId) {
|
||||
|
|
|
@ -143,6 +143,11 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
|
|||
return extTestPlanFunctionalCaseMapper.selectDistinctExecResultByTestPlanIds(testPlanIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TestPlanResourceExecResultDTO> selectDistinctLastExecResultByTestPlanIds(List<String> testPlanIds) {
|
||||
return extTestPlanFunctionalCaseMapper.selectDistinctLastExecResultByTestPlanIds(testPlanIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long copyResource(String originalTestPlanId, String newTestPlanId, Map<String, String> oldCollectionIdToNewCollectionId, String operator, long operatorTime) {
|
||||
List<TestPlanFunctionalCase> copyList = new ArrayList<>();
|
||||
|
|
|
@ -642,11 +642,7 @@ public class TestPlanReportService {
|
|||
|
||||
long beforeFlush = System.currentTimeMillis();
|
||||
sqlSession.flushStatements();
|
||||
long beforeClose = System.currentTimeMillis();
|
||||
System.out.println("flush time: " + (beforeClose - beforeFlush));
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
long afterFlush = System.currentTimeMillis();
|
||||
System.out.println("close time: " + (afterFlush - beforeClose));
|
||||
|
||||
return TestPlanReportDetailCaseDTO.builder()
|
||||
.functionCaseCount(funcCaseCount.get()).apiCaseCount(apiCaseCount.get()).apiScenarioCount(apiScenarioCount.get()).bugCount(bugCount.get()).build();
|
||||
|
|
|
@ -9,7 +9,10 @@ import io.metersphere.bug.service.BugStatusService;
|
|||
import io.metersphere.dto.BugProviderDTO;
|
||||
import io.metersphere.plan.domain.TestPlan;
|
||||
import io.metersphere.plan.domain.TestPlanCollectionExample;
|
||||
import io.metersphere.plan.dto.*;
|
||||
import io.metersphere.plan.dto.TestPlanCaseBugDTO;
|
||||
import io.metersphere.plan.dto.TestPlanCollectionDTO;
|
||||
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
|
||||
import io.metersphere.plan.dto.TestPlanResourceExecResultDTO;
|
||||
import io.metersphere.plan.dto.request.BaseCollectionAssociateRequest;
|
||||
import io.metersphere.plan.dto.request.BasePlanCaseBatchRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanCaseAssociateBugRequest;
|
||||
|
@ -104,6 +107,8 @@ public abstract class TestPlanResourceService extends TestPlanSortService {
|
|||
|
||||
public abstract List<TestPlanResourceExecResultDTO> selectDistinctExecResultByTestPlanIds(List<String> testPlanIds);
|
||||
|
||||
public abstract List<TestPlanResourceExecResultDTO> selectDistinctLastExecResultByTestPlanIds(List<String> testPlanIds);
|
||||
|
||||
/**
|
||||
* 关联用例
|
||||
*
|
||||
|
|
|
@ -3,7 +3,9 @@ package io.metersphere.plan.service;
|
|||
import io.metersphere.plan.domain.*;
|
||||
import io.metersphere.plan.dto.TestPlanCollectionDTO;
|
||||
import io.metersphere.plan.dto.TestPlanExecuteHisDTO;
|
||||
import io.metersphere.plan.dto.TestPlanResourceExecResultDTO;
|
||||
import io.metersphere.plan.dto.request.*;
|
||||
import io.metersphere.plan.dto.response.TestPlanCoverageDTO;
|
||||
import io.metersphere.plan.dto.response.TestPlanDetailResponse;
|
||||
import io.metersphere.plan.dto.response.TestPlanOperationResponse;
|
||||
import io.metersphere.plan.dto.response.TestPlanStatisticsResponse;
|
||||
|
@ -37,6 +39,7 @@ import io.metersphere.system.uid.NumGenerator;
|
|||
import io.metersphere.system.utils.BatchProcessUtils;
|
||||
import io.metersphere.system.utils.ServiceUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
|
@ -1012,4 +1015,65 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
testPlanReportService.updateExecuteTimeAndStatus(testPlanReportId);
|
||||
}
|
||||
}
|
||||
|
||||
public TestPlanCoverageDTO rageByProjectIdAndTimestamp(@NotBlank String projectId, long startTime, long endTime) {
|
||||
TestPlanCoverageDTO returnDTO = new TestPlanCoverageDTO();
|
||||
TestPlanExample testPlanExample = new TestPlanExample();
|
||||
testPlanExample.createCriteria().andProjectIdEqualTo(projectId).andCreateTimeBetween(startTime, endTime).andTypeEqualTo(TestPlanConstants.TEST_PLAN_TYPE_PLAN);
|
||||
List<TestPlan> testPlanList = extTestPlanMapper.selectIdAndStatusByProjectIdAndCreateTimeRangeAndType(projectId, startTime, endTime, TestPlanConstants.TEST_PLAN_TYPE_PLAN);
|
||||
|
||||
List<String> notArchivedList = new ArrayList<>();
|
||||
testPlanList.forEach(item -> {
|
||||
if (StringUtils.equalsIgnoreCase(item.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
|
||||
returnDTO.archivedAutoIncrement();
|
||||
} else {
|
||||
notArchivedList.add(item.getId());
|
||||
}
|
||||
});
|
||||
|
||||
// 将当前项目下未归档的测试计划结果查询出来,进行下列符合条件的筛选
|
||||
Map<String, TestPlanResourceService> beansOfType = applicationContext.getBeansOfType(TestPlanResourceService.class);
|
||||
|
||||
// 批量处理
|
||||
SubListUtils.dealForSubList(notArchivedList, SubListUtils.DEFAULT_BATCH_SIZE, dealList -> {
|
||||
TestPlanConfigExample testPlanConfigExample = new TestPlanConfigExample();
|
||||
testPlanConfigExample.createCriteria().andTestPlanIdIn(dealList);
|
||||
List<TestPlanConfig> testPlanConfigList = testPlanConfigMapper.selectByExample(testPlanConfigExample);
|
||||
Map<String, TestPlanConfig> testPlanConfigMap = testPlanConfigList.stream().collect(Collectors.toMap(TestPlanConfig::getTestPlanId, v -> v));
|
||||
|
||||
|
||||
List<TestPlanResourceExecResultDTO> execResults = new ArrayList<>();
|
||||
beansOfType.forEach((k, v) -> execResults.addAll(v.selectDistinctLastExecResultByTestPlanIds(dealList)));
|
||||
Map<String, List<String>> testPlanExecResultMap = execResults.stream().collect(Collectors.groupingBy(TestPlanResourceExecResultDTO::getTestPlanId, Collectors.mapping(TestPlanResourceExecResultDTO::getExecResult, Collectors.toList())));
|
||||
|
||||
for (String testPlanId : dealList) {
|
||||
List<String> executeResultList = testPlanExecResultMap.get(testPlanId);
|
||||
if (CollectionUtils.isEmpty(executeResultList)) {
|
||||
// 未运行
|
||||
returnDTO.notStartedAutoIncrement();
|
||||
} else {
|
||||
List<String> calculateList = executeResultList.stream().distinct().toList();
|
||||
//目前只有三个状态。如果同时包含多种状态(进行中/未开始、进行中/已完成、已完成/未开始、进行中/未开始/已完成),根据算法可得测试计划都会是进行中
|
||||
if (calculateList.size() == 1) {
|
||||
if (calculateList.contains(ResultStatus.SUCCESS.name())) {
|
||||
returnDTO.successAutoIncrement();
|
||||
} else if (calculateList.contains(ExecStatus.PENDING.name())) {
|
||||
returnDTO.notStartedAutoIncrement();
|
||||
} else {
|
||||
returnDTO.unSuccessAutoIncrement();
|
||||
}
|
||||
} else {
|
||||
if (calculateList.contains(ExecStatus.PENDING.name())) {
|
||||
// 存在还未完成的用例,测试计划为进行中
|
||||
returnDTO.testPlanRunningAutoIncrement();
|
||||
} else {
|
||||
returnDTO.unSuccessAutoIncrement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
return returnDTO;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import io.metersphere.functional.mapper.FunctionalCaseMapper;
|
|||
import io.metersphere.plan.constants.TestPlanResourceConfig;
|
||||
import io.metersphere.plan.domain.*;
|
||||
import io.metersphere.plan.dto.request.*;
|
||||
import io.metersphere.plan.dto.response.TestPlanCoverageDTO;
|
||||
import io.metersphere.plan.dto.response.TestPlanOperationResponse;
|
||||
import io.metersphere.plan.dto.response.TestPlanResponse;
|
||||
import io.metersphere.plan.dto.response.TestPlanStatisticsResponse;
|
||||
|
@ -1650,6 +1651,25 @@ public class TestPlanTests extends BaseTest {
|
|||
Assertions.assertTrue(statisticsResponses.getFirst().getScheduleConfig() == null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(62)
|
||||
public void testPlanRage() throws Exception {
|
||||
if (StringUtils.isAnyBlank(groupTestPlanId7, groupTestPlanId15)) {
|
||||
this.testPlanAddTest();
|
||||
}
|
||||
|
||||
TestPlanCoverageRequest request = new TestPlanCoverageRequest();
|
||||
request.setProjectId(project.getId());
|
||||
request.setDayNumber(7);
|
||||
|
||||
MvcResult mvcResult = this.requestPostWithOkAndReturn("/test-plan/rage", request);
|
||||
TestPlanCoverageDTO coverageDTO = this.getResultData(mvcResult, TestPlanCoverageDTO.class);
|
||||
Assertions.assertEquals(coverageDTO.getUnExecute() + coverageDTO.getExecuted(), coverageDTO.getPassed() + coverageDTO.getNotPassed());
|
||||
Assertions.assertEquals(coverageDTO.getFinished() + coverageDTO.getRunning() + coverageDTO.getPrepared(), coverageDTO.getPassed() + coverageDTO.getNotPassed());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(81)
|
||||
public void copyTestPlan() throws Exception {
|
||||
|
|
Loading…
Reference in New Issue