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 hasRunningReport(@Param("planId") String planId);
|
||||||
|
|
||||||
boolean hasRunningReportByPlanIds(@Param("planIds") List<String> planIds);
|
boolean hasRunningReportByPlanIds(@Param("planIds") List<String> planIds);
|
||||||
|
|
||||||
|
boolean isApiBasicCountIsNull(String testPlanReportId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,4 +37,10 @@
|
||||||
and status = 'RUNNING'
|
and status = 'RUNNING'
|
||||||
order by create_time desc limit 1;
|
order by create_time desc limit 1;
|
||||||
</select>
|
</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>
|
</mapper>
|
||||||
|
|
|
@ -2,10 +2,14 @@ package io.metersphere.plan.dto;
|
||||||
|
|
||||||
|
|
||||||
import io.metersphere.base.domain.TestPlanReportContent;
|
import io.metersphere.base.domain.TestPlanReportContent;
|
||||||
|
import io.metersphere.commons.constants.PerformanceTestStatus;
|
||||||
import io.metersphere.dto.*;
|
import io.metersphere.dto.*;
|
||||||
|
import io.metersphere.plan.constant.ApiReportStatus;
|
||||||
import io.metersphere.xpack.track.dto.IssuesDao;
|
import io.metersphere.xpack.track.dto.IssuesDao;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -62,4 +66,53 @@ public class TestPlanReportDataStruct extends TestPlanReportContent {
|
||||||
|
|
||||||
List<TestPlanUiScenarioDTO> uiAllCases;
|
List<TestPlanUiScenarioDTO> uiAllCases;
|
||||||
List<TestPlanUiScenarioDTO> uiFailureCases;
|
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.TestPlanUiExecuteReportDTO;
|
||||||
import io.metersphere.plan.request.ui.UiPlanReportRequest;
|
import io.metersphere.plan.request.ui.UiPlanReportRequest;
|
||||||
import io.metersphere.plan.service.remote.api.*;
|
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.performance.PlanTestPlanLoadCaseService;
|
||||||
import io.metersphere.plan.service.remote.ui.PlanTestPlanUiScenarioCaseService;
|
import io.metersphere.plan.service.remote.ui.PlanTestPlanUiScenarioCaseService;
|
||||||
import io.metersphere.plan.utils.TestPlanReportUtil;
|
import io.metersphere.plan.utils.TestPlanReportUtil;
|
||||||
|
@ -70,8 +69,6 @@ public class TestPlanReportService {
|
||||||
@Resource
|
@Resource
|
||||||
PlanTestPlanLoadCaseService planTestPlanLoadCaseService;
|
PlanTestPlanLoadCaseService planTestPlanLoadCaseService;
|
||||||
@Resource
|
@Resource
|
||||||
PlanLoadTestReportService planLoadTestReportService;
|
|
||||||
@Resource
|
|
||||||
ExtTestPlanReportMapper extTestPlanReportMapper;
|
ExtTestPlanReportMapper extTestPlanReportMapper;
|
||||||
@Resource
|
@Resource
|
||||||
TestPlanMapper testPlanMapper;
|
TestPlanMapper testPlanMapper;
|
||||||
|
@ -155,7 +152,7 @@ public class TestPlanReportService {
|
||||||
TestPlanReport testPlanReport = testPlanReportMapper.selectByPrimaryKey(testPlanReportDTO.getId());
|
TestPlanReport testPlanReport = testPlanReportMapper.selectByPrimaryKey(testPlanReportDTO.getId());
|
||||||
TestPlanReportContentWithBLOBs content = this.selectTestPlanReportContentByReportId(testPlanReportDTO.getId());
|
TestPlanReportContentWithBLOBs content = this.selectTestPlanReportContentByReportId(testPlanReportDTO.getId());
|
||||||
TestPlanReportDataStruct testPlanReportCountData
|
TestPlanReportDataStruct testPlanReportCountData
|
||||||
= testPlanService.buildTestPlanReportStructByTestPlanReport(testPlanReport, content);
|
= testPlanService.buildOldVersionTestPlanReport(testPlanReport, content);
|
||||||
if (testPlanReportCountData != null) {
|
if (testPlanReportCountData != null) {
|
||||||
testPlanReportDTO.setPassRate(testPlanReportCountData.getPassRate());
|
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统计字段和通过率
|
//更新BaseCount统计字段和通过率
|
||||||
testPlanReportContentWithBLOBs.setPassRate(reportStruct.getPassRate());
|
testPlanReportContentWithBLOBs.setPassRate(reportStruct.getPassRate());
|
||||||
testPlanReportContentWithBLOBs.setApiBaseCount(JSON.toJSONString(reportStruct));
|
testPlanReportContentWithBLOBs.setApiBaseCount(JSON.toJSONString(reportStruct));
|
||||||
testPlanReportContentMapper.updateByPrimaryKeySelective(testPlanReportContentWithBLOBs);
|
testPlanReportContentMapper.updateByPrimaryKeySelective(testPlanReportContentWithBLOBs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPlanExecuteOver(String testPlanReportId, String finishStatus) {
|
private boolean isTestPlanCountOver(TestPlanReport testPlanReport) {
|
||||||
TestPlanReport testPlanReport = this.getTestPlanReport(testPlanReportId);
|
|
||||||
if (testPlanReport != null && StringUtils.equalsAnyIgnoreCase(testPlanReport.getStatus(),
|
if (testPlanReport != null && StringUtils.equalsAnyIgnoreCase(testPlanReport.getStatus(),
|
||||||
"stopped",
|
"stopped",
|
||||||
TestPlanReportStatus.COMPLETED.name(),
|
TestPlanReportStatus.COMPLETED.name(),
|
||||||
TestPlanReportStatus.SUCCESS.name(),
|
TestPlanReportStatus.SUCCESS.name(),
|
||||||
TestPlanReportStatus.FAILED.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;
|
return;
|
||||||
}
|
}
|
||||||
boolean isSendMessage = false;
|
boolean isSendMessage = false;
|
||||||
|
@ -577,7 +581,7 @@ public class TestPlanReportService {
|
||||||
boolean isRerunningTestPlan = BooleanUtils.isTrue(StringUtils.equalsIgnoreCase(testPlanReport.getStatus(), APITestStatus.Rerunning.name()));
|
boolean isRerunningTestPlan = BooleanUtils.isTrue(StringUtils.equalsIgnoreCase(testPlanReport.getStatus(), APITestStatus.Rerunning.name()));
|
||||||
//测试计划报告结果数据初始化
|
//测试计划报告结果数据初始化
|
||||||
testPlanReport.setStatus(finishStatus);
|
testPlanReport.setStatus(finishStatus);
|
||||||
content = this.initTestPlanReportInfo(testPlanReport, isRerunningTestPlan);
|
content = this.countAndSaveTestPlanReport(testPlanReport, isRerunningTestPlan);
|
||||||
this.setReportExecuteResult(testPlanReport, finishStatus);
|
this.setReportExecuteResult(testPlanReport, finishStatus);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
testPlanReport.setStatus(finishStatus);
|
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();
|
long endTime = System.currentTimeMillis();
|
||||||
//原逻辑中要判断包含测试计划功能用例时才会赋予结束时间。执行测试计划产生的测试报告,它的结束时间感觉没有这种判断必要。
|
//原逻辑中要判断包含测试计划功能用例时才会赋予结束时间。执行测试计划产生的测试报告,它的结束时间感觉没有这种判断必要。
|
||||||
testPlanReport.setEndTime(endTime);
|
testPlanReport.setEndTime(endTime);
|
||||||
|
@ -620,7 +624,7 @@ public class TestPlanReportService {
|
||||||
content.setApiBaseCount(null);
|
content.setApiBaseCount(null);
|
||||||
}
|
}
|
||||||
TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(testPlanReport.getTestPlanId());
|
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) {
|
if (apiBaseCountStruct.getPassRate() == 1) {
|
||||||
testPlanReport.setStatus(TestPlanReportStatus.SUCCESS.name());
|
testPlanReport.setStatus(TestPlanReportStatus.SUCCESS.name());
|
||||||
} else if (apiBaseCountStruct.getPassRate() < 1) {
|
} 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 planReportId 测试计划报告ID
|
||||||
* @param resourceRunMode 资源的运行模式,triggerMode非Scedule可以为null
|
* @param resourceRunMode 资源的运行模式,triggerMode非Scedule可以为null
|
||||||
|
@ -1066,7 +1055,7 @@ public class TestPlanReportService {
|
||||||
}
|
}
|
||||||
if (this.isDynamicallyGenerateReports(testPlanReportContent) || StringUtils.isNotEmpty(testPlanReportContent.getApiBaseCount())) {
|
if (this.isDynamicallyGenerateReports(testPlanReportContent) || StringUtils.isNotEmpty(testPlanReportContent.getApiBaseCount())) {
|
||||||
TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(testPlanReport.getTestPlanId());
|
TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(testPlanReport.getTestPlanId());
|
||||||
testPlanReportDTO = this.genReportStruct(testPlan, testPlanReport, testPlanReportContent, false);
|
testPlanReportDTO = testPlanService.generateReportStruct(testPlan, testPlanReport, testPlanReportContent, false);
|
||||||
}
|
}
|
||||||
testPlanReportDTO.setId(reportId);
|
testPlanReportDTO.setId(reportId);
|
||||||
testPlanReportDTO.setName(testPlanReport.getName());
|
testPlanReportDTO.setName(testPlanReport.getName());
|
||||||
|
|
|
@ -1381,9 +1381,11 @@ public class TestPlanService {
|
||||||
/**
|
/**
|
||||||
* @param testPlanReport 测试计划报告
|
* @param testPlanReport 测试计划报告
|
||||||
* @param testPlanReportContentWithBLOBs 测试计划报告内容
|
* @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;
|
TestPlanReportDataStruct testPlanReportStruct = null;
|
||||||
if (ObjectUtils.allNotNull(testPlanReport, testPlanReportContentWithBLOBs)) {
|
if (ObjectUtils.allNotNull(testPlanReport, testPlanReportContentWithBLOBs)) {
|
||||||
Map config = null;
|
Map config = null;
|
||||||
|
@ -1524,7 +1526,10 @@ public class TestPlanService {
|
||||||
report.setApiResult(apiResult);
|
report.setApiResult(apiResult);
|
||||||
report.setUiResult(uiResult);
|
report.setUiResult(uiResult);
|
||||||
report.setStartTime(testPlanReport.getCreateTime());
|
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());
|
report.setEndTime(testPlanReport.getEndTime());
|
||||||
}
|
}
|
||||||
|
@ -2108,11 +2113,15 @@ public class TestPlanService {
|
||||||
return projectIds.stream().distinct().collect(Collectors.toList());
|
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());
|
TestPlanWithBLOBs testPlanWithBLOBs = this.testPlanMapper.selectByPrimaryKey(testPlanReport.getTestPlanId());
|
||||||
TestPlanReportDataStruct testPlanReportDataStruct = new TestPlanReportDataStruct();
|
TestPlanReportDataStruct testPlanReportDataStruct = new TestPlanReportDataStruct();
|
||||||
try {
|
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) {
|
} catch (Exception e) {
|
||||||
LoggerUtil.error("统计测试计划数据出错!", e);
|
LoggerUtil.error("统计测试计划数据出错!", e);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue