fix(测试跟踪): 优化测试报告异常数据的处理逻辑
--bug=1024864 --user=宋天阳 【测试跟踪】计划执行中-test-track异常启动-报告Completed后-在计划中增加用例-该报告的通过率会重新计算 https://www.tapd.cn/55049933/s/1356453 --bug=1024861 --user=宋天阳 【测试跟踪】测试计划执行中-查看报告-结束时间显示为开始时间 https://www.tapd.cn/55049933/s/1356455 --bug=1024863 --user=宋天阳 【测试跟踪】执行测试计划中test-track服务重启-报告结束时间显示为开始时间 https://www.tapd.cn/55049933/s/1356456
This commit is contained in:
parent
5a61859424
commit
37dd2127e5
|
@ -14,4 +14,6 @@ public interface ExtTestPlanReportContentMapper {
|
|||
boolean hasRunningReport(@Param("planId") String planId);
|
||||
|
||||
boolean hasRunningReportByPlanIds(@Param("planIds") List<String> planIds);
|
||||
|
||||
boolean isApiBasicCountIsNull(String testPlanReportId);
|
||||
}
|
||||
|
|
|
@ -37,4 +37,10 @@
|
|||
and status = 'RUNNING'
|
||||
order by create_time desc limit 1;
|
||||
</select>
|
||||
|
||||
<select id="isApiBasicCountIsNull" resultType="java.lang.Boolean">
|
||||
SELECT (api_base_count IS NULL OR api_base_count = '') AS apiCountIsNull
|
||||
FROM test_plan_report_content WHERE test_plan_report_id = #{0} limit 1
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
|
|
@ -2,10 +2,14 @@ package io.metersphere.plan.dto;
|
|||
|
||||
|
||||
import io.metersphere.base.domain.TestPlanReportContent;
|
||||
import io.metersphere.commons.constants.PerformanceTestStatus;
|
||||
import io.metersphere.dto.*;
|
||||
import io.metersphere.plan.constant.ApiReportStatus;
|
||||
import io.metersphere.xpack.track.dto.IssuesDao;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -62,4 +66,53 @@ public class TestPlanReportDataStruct extends TestPlanReportContent {
|
|||
|
||||
List<TestPlanUiScenarioDTO> uiAllCases;
|
||||
List<TestPlanUiScenarioDTO> uiFailureCases;
|
||||
|
||||
public boolean hasRunningCase() {
|
||||
//判断是否含有运行中的用例。 方法内针对集合不开流是为了不影响后续业务中使用stream
|
||||
if (CollectionUtils.isNotEmpty(apiAllCases)) {
|
||||
List<TestPlanApiDTO> runningCaseList =
|
||||
apiAllCases.stream().filter(
|
||||
dto -> StringUtils.equalsAnyIgnoreCase(dto.getExecResult(),
|
||||
ApiReportStatus.PENDING.name(),
|
||||
ApiReportStatus.RERUNNING.name(),
|
||||
ApiReportStatus.RUNNING.name())).toList();
|
||||
if (runningCaseList.size() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(scenarioAllCases)) {
|
||||
List<TestPlanScenarioDTO> runningCaseList =
|
||||
scenarioAllCases.stream().filter(
|
||||
dto -> StringUtils.equalsAnyIgnoreCase(dto.getLastResult(),
|
||||
ApiReportStatus.PENDING.name(),
|
||||
ApiReportStatus.RERUNNING.name(),
|
||||
ApiReportStatus.RUNNING.name())).toList();
|
||||
if (runningCaseList.size() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(loadAllCases)) {
|
||||
List<TestPlanLoadCaseDTO> runningCaseList =
|
||||
loadAllCases.stream().filter(
|
||||
dto -> StringUtils.equalsAnyIgnoreCase(dto.getStatus(),
|
||||
PerformanceTestStatus.Starting.name(),
|
||||
PerformanceTestStatus.Running.name(),
|
||||
PerformanceTestStatus.Reporting.name())).toList();
|
||||
if (runningCaseList.size() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(uiAllCases)) {
|
||||
List<TestPlanUiScenarioDTO> runningCaseList =
|
||||
uiAllCases.stream().filter(
|
||||
dto -> StringUtils.equalsAnyIgnoreCase(dto.getLastResult(),
|
||||
ApiReportStatus.PENDING.name(),
|
||||
ApiReportStatus.RERUNNING.name(),
|
||||
ApiReportStatus.RUNNING.name())).toList();
|
||||
if (runningCaseList.size() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import io.metersphere.plan.request.performance.LoadPlanReportDTO;
|
|||
import io.metersphere.plan.request.ui.TestPlanUiExecuteReportDTO;
|
||||
import io.metersphere.plan.request.ui.UiPlanReportRequest;
|
||||
import io.metersphere.plan.service.remote.api.*;
|
||||
import io.metersphere.plan.service.remote.performance.PlanLoadTestReportService;
|
||||
import io.metersphere.plan.service.remote.performance.PlanTestPlanLoadCaseService;
|
||||
import io.metersphere.plan.service.remote.ui.PlanTestPlanUiScenarioCaseService;
|
||||
import io.metersphere.plan.utils.TestPlanReportUtil;
|
||||
|
@ -70,8 +69,6 @@ public class TestPlanReportService {
|
|||
@Resource
|
||||
PlanTestPlanLoadCaseService planTestPlanLoadCaseService;
|
||||
@Resource
|
||||
PlanLoadTestReportService planLoadTestReportService;
|
||||
@Resource
|
||||
ExtTestPlanReportMapper extTestPlanReportMapper;
|
||||
@Resource
|
||||
TestPlanMapper testPlanMapper;
|
||||
|
@ -155,7 +152,7 @@ public class TestPlanReportService {
|
|||
TestPlanReport testPlanReport = testPlanReportMapper.selectByPrimaryKey(testPlanReportDTO.getId());
|
||||
TestPlanReportContentWithBLOBs content = this.selectTestPlanReportContentByReportId(testPlanReportDTO.getId());
|
||||
TestPlanReportDataStruct testPlanReportCountData
|
||||
= testPlanService.buildTestPlanReportStructByTestPlanReport(testPlanReport, content);
|
||||
= testPlanService.buildOldVersionTestPlanReport(testPlanReport, content);
|
||||
if (testPlanReportCountData != null) {
|
||||
testPlanReportDTO.setPassRate(testPlanReportCountData.getPassRate());
|
||||
}
|
||||
|
@ -546,20 +543,27 @@ public class TestPlanReportService {
|
|||
}
|
||||
|
||||
//更新测试计划报告的数据结构
|
||||
private void updateReportStructInfo(TestPlanReportContentWithBLOBs testPlanReportContentWithBLOBs, TestPlanReportDataStruct reportStruct) {
|
||||
public void updateReportStructInfo(TestPlanReportContentWithBLOBs testPlanReportContentWithBLOBs, TestPlanReportDataStruct reportStruct) {
|
||||
//更新BaseCount统计字段和通过率
|
||||
testPlanReportContentWithBLOBs.setPassRate(reportStruct.getPassRate());
|
||||
testPlanReportContentWithBLOBs.setApiBaseCount(JSON.toJSONString(reportStruct));
|
||||
testPlanReportContentMapper.updateByPrimaryKeySelective(testPlanReportContentWithBLOBs);
|
||||
}
|
||||
|
||||
public void testPlanExecuteOver(String testPlanReportId, String finishStatus) {
|
||||
TestPlanReport testPlanReport = this.getTestPlanReport(testPlanReportId);
|
||||
private boolean isTestPlanCountOver(TestPlanReport testPlanReport) {
|
||||
if (testPlanReport != null && StringUtils.equalsAnyIgnoreCase(testPlanReport.getStatus(),
|
||||
"stopped",
|
||||
TestPlanReportStatus.COMPLETED.name(),
|
||||
TestPlanReportStatus.SUCCESS.name(),
|
||||
TestPlanReportStatus.FAILED.name())) {
|
||||
return !extTestPlanReportContentMapper.isApiBasicCountIsNull(testPlanReport.getId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void testPlanExecuteOver(String testPlanReportId, String finishStatus) {
|
||||
TestPlanReport testPlanReport = this.getTestPlanReport(testPlanReportId);
|
||||
if (this.isTestPlanCountOver(testPlanReport)) {
|
||||
return;
|
||||
}
|
||||
boolean isSendMessage = false;
|
||||
|
@ -577,7 +581,7 @@ public class TestPlanReportService {
|
|||
boolean isRerunningTestPlan = BooleanUtils.isTrue(StringUtils.equalsIgnoreCase(testPlanReport.getStatus(), APITestStatus.Rerunning.name()));
|
||||
//测试计划报告结果数据初始化
|
||||
testPlanReport.setStatus(finishStatus);
|
||||
content = this.initTestPlanReportInfo(testPlanReport, isRerunningTestPlan);
|
||||
content = this.countAndSaveTestPlanReport(testPlanReport, isRerunningTestPlan);
|
||||
this.setReportExecuteResult(testPlanReport, finishStatus);
|
||||
} catch (Exception e) {
|
||||
testPlanReport.setStatus(finishStatus);
|
||||
|
@ -605,7 +609,7 @@ public class TestPlanReportService {
|
|||
/**
|
||||
* 统计测试计划报告信息
|
||||
*/
|
||||
public TestPlanReportContentWithBLOBs initTestPlanReportInfo(TestPlanReport testPlanReport, boolean isRerunningTestPlan) throws Exception {
|
||||
public TestPlanReportContentWithBLOBs countAndSaveTestPlanReport(TestPlanReport testPlanReport, boolean isRerunningTestPlan) {
|
||||
long endTime = System.currentTimeMillis();
|
||||
//原逻辑中要判断包含测试计划功能用例时才会赋予结束时间。执行测试计划产生的测试报告,它的结束时间感觉没有这种判断必要。
|
||||
testPlanReport.setEndTime(endTime);
|
||||
|
@ -620,7 +624,7 @@ public class TestPlanReportService {
|
|||
content.setApiBaseCount(null);
|
||||
}
|
||||
TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(testPlanReport.getTestPlanId());
|
||||
TestPlanReportDataStruct apiBaseCountStruct = this.genReportStruct(testPlan, testPlanReport, content, isRerunningTestPlan);
|
||||
TestPlanReportDataStruct apiBaseCountStruct = testPlanService.generateReportStruct(testPlan, testPlanReport, content, isRerunningTestPlan);
|
||||
if (apiBaseCountStruct.getPassRate() == 1) {
|
||||
testPlanReport.setStatus(TestPlanReportStatus.SUCCESS.name());
|
||||
} else if (apiBaseCountStruct.getPassRate() < 1) {
|
||||
|
@ -674,21 +678,6 @@ public class TestPlanReportService {
|
|||
}
|
||||
}
|
||||
|
||||
//构建测试计划报告的数据结构
|
||||
private TestPlanReportDataStruct genReportStruct(TestPlanWithBLOBs testPlan, TestPlanReport testPlanReport, TestPlanReportContentWithBLOBs reportContent, boolean rebuildReport) {
|
||||
TestPlanReportDataStruct returnDTO = null;
|
||||
if (testPlanReport != null && reportContent != null) {
|
||||
try {
|
||||
returnDTO = testPlanService.buildReportStruct(testPlan, testPlanReport, reportContent, rebuildReport);
|
||||
//查找运行环境
|
||||
this.initRunInformation(returnDTO, testPlanReport);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("计算测试计划报告信息出错!", e);
|
||||
}
|
||||
}
|
||||
return returnDTO == null ? new TestPlanReportDataStruct() : returnDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param planReportId 测试计划报告ID
|
||||
* @param resourceRunMode 资源的运行模式,triggerMode非Scedule可以为null
|
||||
|
@ -1066,7 +1055,7 @@ public class TestPlanReportService {
|
|||
}
|
||||
if (this.isDynamicallyGenerateReports(testPlanReportContent) || StringUtils.isNotEmpty(testPlanReportContent.getApiBaseCount())) {
|
||||
TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(testPlanReport.getTestPlanId());
|
||||
testPlanReportDTO = this.genReportStruct(testPlan, testPlanReport, testPlanReportContent, false);
|
||||
testPlanReportDTO = testPlanService.generateReportStruct(testPlan, testPlanReport, testPlanReportContent, false);
|
||||
}
|
||||
testPlanReportDTO.setId(reportId);
|
||||
testPlanReportDTO.setName(testPlanReport.getName());
|
||||
|
|
|
@ -1381,9 +1381,11 @@ public class TestPlanService {
|
|||
/**
|
||||
* @param testPlanReport 测试计划报告
|
||||
* @param testPlanReportContentWithBLOBs 测试计划报告内容
|
||||
* @return
|
||||
*/
|
||||
public TestPlanReportDataStruct buildReportStruct(TestPlanWithBLOBs testPlan, TestPlanReport testPlanReport, TestPlanReportContentWithBLOBs testPlanReportContentWithBLOBs, boolean rebuildReport) {
|
||||
public TestPlanReportDataStruct generateReportStruct(TestPlanWithBLOBs testPlan,
|
||||
TestPlanReport testPlanReport,
|
||||
TestPlanReportContentWithBLOBs testPlanReportContentWithBLOBs,
|
||||
boolean rebuildReport) {
|
||||
TestPlanReportDataStruct testPlanReportStruct = null;
|
||||
if (ObjectUtils.allNotNull(testPlanReport, testPlanReportContentWithBLOBs)) {
|
||||
Map config = null;
|
||||
|
@ -1524,7 +1526,10 @@ public class TestPlanService {
|
|||
report.setApiResult(apiResult);
|
||||
report.setUiResult(uiResult);
|
||||
report.setStartTime(testPlanReport.getCreateTime());
|
||||
if (testPlanReport.getCreateTime() != testPlanReport.getEndTime() && testPlanReport.getEndTime() != 0) {
|
||||
if (!StringUtils.equals(
|
||||
DateUtils.getTimeString(testPlanReport.getCreateTime()),
|
||||
DateUtils.getTimeString(testPlanReport.getEndTime()))
|
||||
&& testPlanReport.getEndTime() != 0) {
|
||||
//防止测试计划报告非正常状态停止时造成的测试时间显示不对
|
||||
report.setEndTime(testPlanReport.getEndTime());
|
||||
}
|
||||
|
@ -2108,11 +2113,15 @@ public class TestPlanService {
|
|||
return projectIds.stream().distinct().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public TestPlanReportDataStruct buildTestPlanReportStructByTestPlanReport(TestPlanReport testPlanReport, TestPlanReportContentWithBLOBs testPlanReportContent) {
|
||||
public TestPlanReportDataStruct buildOldVersionTestPlanReport(TestPlanReport testPlanReport, TestPlanReportContentWithBLOBs testPlanReportContent) {
|
||||
TestPlanWithBLOBs testPlanWithBLOBs = this.testPlanMapper.selectByPrimaryKey(testPlanReport.getTestPlanId());
|
||||
TestPlanReportDataStruct testPlanReportDataStruct = new TestPlanReportDataStruct();
|
||||
try {
|
||||
testPlanReportDataStruct = this.buildReportStruct(testPlanWithBLOBs, testPlanReport, testPlanReportContent, false);
|
||||
testPlanReportDataStruct = this.generateReportStruct(testPlanWithBLOBs, testPlanReport, testPlanReportContent, false);
|
||||
if (StringUtils.isBlank(testPlanReportContent.getApiBaseCount()) && !testPlanReportDataStruct.hasRunningCase()) {
|
||||
//旧版本的测试计划报告,没有重新统计过测试计划报告时,且当不存在运行中的用例,会将结果保存下来
|
||||
testPlanReportService.updateReportStructInfo(testPlanReportContent, testPlanReportDataStruct);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LoggerUtil.error("统计测试计划数据出错!", e);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue