fix(测试跟踪): 数据太多时,测试计划报告列表内存溢出
--bug=1020253 --user=陈建星 【测试跟踪】访问报告页面,服务会挂 https://www.tapd.cn/55049933/s/1305503
This commit is contained in:
parent
f4ccfa60d4
commit
c5f3767fc9
|
@ -0,0 +1,11 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
import io.metersphere.base.domain.TestPlanReportContentWithBLOBs;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
public interface ExtTestPlanReportContentMapper {
|
||||
|
||||
boolean isDynamicallyGenerateReport(@Param("reportId") String reportId);
|
||||
|
||||
TestPlanReportContentWithBLOBs selectForPassRate(@Param("reportId") String reportId);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
<mapper namespace="io.metersphere.base.mapper.ext.ExtTestPlanReportContentMapper">
|
||||
|
||||
<select id="isDynamicallyGenerateReport" resultType="java.lang.Boolean">
|
||||
select count(*) > 0
|
||||
from test_plan_report_content
|
||||
where test_plan_report_id = #{reportId}
|
||||
and (
|
||||
plan_api_case_report_struct is not null or plan_api_case_report_struct != ''
|
||||
or plan_scenario_report_struct is not null or plan_scenario_report_struct != ''
|
||||
or plan_ui_scenario_report_struct is not null or plan_ui_scenario_report_struct != ''
|
||||
or plan_load_case_report_struct is not null or plan_load_case_report_struct != ''
|
||||
)
|
||||
</select>
|
||||
<select id="selectForPassRate" resultType="io.metersphere.base.domain.TestPlanReportContentWithBLOBs">
|
||||
select id,
|
||||
test_plan_report_id,
|
||||
plan_scenario_report_struct,
|
||||
plan_api_case_report_struct,
|
||||
plan_load_case_report_struct,
|
||||
plan_ui_scenario_report_struct
|
||||
from test_plan_report_content
|
||||
where test_plan_report_id = #{reportId}
|
||||
</select>
|
||||
</mapper>
|
|
@ -4,6 +4,7 @@ package io.metersphere.plan.service;
|
|||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtTestPlanReportContentMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtTestPlanReportMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
|
||||
import io.metersphere.commons.constants.*;
|
||||
|
@ -73,6 +74,8 @@ public class TestPlanReportService {
|
|||
@Resource
|
||||
TestPlanReportContentMapper testPlanReportContentMapper;
|
||||
@Resource
|
||||
ExtTestPlanReportContentMapper extTestPlanReportContentMapper;
|
||||
@Resource
|
||||
private TestPlanPrincipalMapper testPlanPrincipalMapper;
|
||||
@Resource
|
||||
ExtTestPlanTestCaseMapper extTestPlanTestCaseMapper;
|
||||
|
@ -136,92 +139,84 @@ public class TestPlanReportService {
|
|||
for (TestPlanReportDTO testPlanReportDTO : list) {
|
||||
// 如果数据库查询成功率字段为空或 0 则重新计算一次
|
||||
if (testPlanReportDTO.getPassRate() == null || testPlanReportDTO.getPassRate() == 0) {
|
||||
TestPlanReportContentExample example = new TestPlanReportContentExample();
|
||||
example.createCriteria().andTestPlanReportIdEqualTo(testPlanReportDTO.getId());
|
||||
List<TestPlanReportContentWithBLOBs> testPlanReportContents = testPlanReportContentMapper.selectByExampleWithBLOBs(example);
|
||||
if (this.isDynamicallyGenerateReports(testPlanReportDTO.getId())) {
|
||||
TestPlanReportContentWithBLOBs testPlanReportContent = extTestPlanReportContentMapper.selectForPassRate(testPlanReportDTO.getId());
|
||||
String planId = testPlanReportDTO.getTestPlanId();
|
||||
TestPlanSimpleReportDTO report = new TestPlanSimpleReportDTO();
|
||||
Map<String, TestCaseReportStatusResultDTO> statusResultMap = new HashMap<>();
|
||||
|
||||
if (CollectionUtils.isNotEmpty(testPlanReportContents)) {
|
||||
TestPlanReportContentWithBLOBs testPlanReportContent = testPlanReportContents.get(0);
|
||||
if (testPlanReportContent != null) {
|
||||
if (this.isDynamicallyGenerateReports(testPlanReportContent)) {
|
||||
String planId = testPlanReportDTO.getTestPlanId();
|
||||
TestPlanSimpleReportDTO report = new TestPlanSimpleReportDTO();
|
||||
Map<String, TestCaseReportStatusResultDTO> statusResultMap = new HashMap<>();
|
||||
TestPlanExecuteReportDTO testPlanExecuteReportDTO = genTestPlanExecuteReportDTOByTestPlanReportContent(testPlanReportContent);
|
||||
// 功能用例
|
||||
TestPlanStatusCalculator.buildStatusResultMap(extTestPlanTestCaseMapper.selectForPlanReport(planId), statusResultMap, report, TestPlanTestCaseStatus.Pass.name());
|
||||
|
||||
TestPlanExecuteReportDTO testPlanExecuteReportDTO = genTestPlanExecuteReportDTOByTestPlanReportContent(testPlanReportContent);
|
||||
// 功能用例
|
||||
TestPlanStatusCalculator.buildStatusResultMap(extTestPlanTestCaseMapper.selectForPlanReport(planId), statusResultMap, report, TestPlanTestCaseStatus.Pass.name());
|
||||
// 测试计划报告各用例集合
|
||||
List<PlanReportCaseDTO> planReportCaseDTOS;
|
||||
|
||||
// 测试计划报告各用例集合
|
||||
List<PlanReportCaseDTO> planReportCaseDTOS;
|
||||
Set<String> serviceIdSet = DiscoveryUtil.getServiceIdSet();
|
||||
|
||||
Set<String> serviceIdSet = DiscoveryUtil.getServiceIdSet();
|
||||
if (testPlanExecuteReportDTO == null) {
|
||||
|
||||
if (testPlanExecuteReportDTO == null) {
|
||||
|
||||
if (serviceIdSet.contains(MicroServiceName.API_TEST)) {
|
||||
// 接口用例
|
||||
planReportCaseDTOS = planTestPlanApiCaseService.selectStatusForPlanReport(planId);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
// 场景用例
|
||||
planReportCaseDTOS = planTestPlanScenarioCaseService.selectStatusForPlanReport(planId);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
|
||||
|
||||
if (serviceIdSet.contains(MicroServiceName.PERFORMANCE_TEST)) {
|
||||
// 性能用例
|
||||
planReportCaseDTOS = planTestPlanLoadCaseService.selectStatusForPlanReport(planId);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
} else {
|
||||
// 报告 ID 集合
|
||||
List<String> reportIds = null;
|
||||
// 接口用例
|
||||
if (serviceIdSet.contains(MicroServiceName.API_TEST)) {
|
||||
if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap())) {
|
||||
reportIds = new ArrayList<>(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap().values());
|
||||
planReportCaseDTOS = planApiDefinitionExecResultService.selectForPlanReport(reportIds);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanScenarioIdAndReportIdMap())) {
|
||||
// 场景用例
|
||||
reportIds = new ArrayList<>(testPlanExecuteReportDTO.getTestPlanScenarioIdAndReportIdMap().values());
|
||||
planReportCaseDTOS = planApiScenarioReportService.selectForPlanReport(reportIds);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceIdSet.contains(MicroServiceName.UI_TEST)) {
|
||||
if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanUiScenarioIdAndReportIdMap())) {
|
||||
// 场景用例
|
||||
reportIds = new ArrayList<>(testPlanExecuteReportDTO.getTestPlanUiScenarioIdAndReportIdMap().values());
|
||||
planReportCaseDTOS = planApiScenarioReportService.selectForPlanReport(reportIds);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceIdSet.contains(MicroServiceName.PERFORMANCE_TEST)) {
|
||||
if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanLoadCaseIdAndReportIdMap())) {
|
||||
// 性能用例
|
||||
reportIds = new ArrayList<>(testPlanExecuteReportDTO.getTestPlanLoadCaseIdAndReportIdMap().values());
|
||||
planReportCaseDTOS = planLoadTestReportService.getPlanReportCaseDTO(reportIds);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
report.setExecuteRate(0.0);
|
||||
report.setPassRate(0.0);
|
||||
|
||||
// 设置成功率
|
||||
if (report.getCaseCount() != null && report.getCaseCount() != 0) {
|
||||
report.setExecuteRate(report.getExecuteCount() * 1.0 / report.getCaseCount());
|
||||
report.setPassRate(report.getPassCount() * 1.0 / report.getCaseCount());
|
||||
}
|
||||
testPlanReportDTO.setPassRate(report.getPassRate());
|
||||
if (serviceIdSet.contains(MicroServiceName.API_TEST)) {
|
||||
// 接口用例
|
||||
planReportCaseDTOS = planTestPlanApiCaseService.selectStatusForPlanReport(planId);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
// 场景用例
|
||||
planReportCaseDTOS = planTestPlanScenarioCaseService.selectStatusForPlanReport(planId);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
|
||||
|
||||
if (serviceIdSet.contains(MicroServiceName.PERFORMANCE_TEST)) {
|
||||
// 性能用例
|
||||
planReportCaseDTOS = planTestPlanLoadCaseService.selectStatusForPlanReport(planId);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
} else {
|
||||
// 报告 ID 集合
|
||||
List<String> reportIds = null;
|
||||
// 接口用例
|
||||
if (serviceIdSet.contains(MicroServiceName.API_TEST)) {
|
||||
if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap())) {
|
||||
reportIds = new ArrayList<>(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap().values());
|
||||
planReportCaseDTOS = planApiDefinitionExecResultService.selectForPlanReport(reportIds);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanScenarioIdAndReportIdMap())) {
|
||||
// 场景用例
|
||||
reportIds = new ArrayList<>(testPlanExecuteReportDTO.getTestPlanScenarioIdAndReportIdMap().values());
|
||||
planReportCaseDTOS = planApiScenarioReportService.selectForPlanReport(reportIds);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceIdSet.contains(MicroServiceName.UI_TEST)) {
|
||||
if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanUiScenarioIdAndReportIdMap())) {
|
||||
// 场景用例
|
||||
reportIds = new ArrayList<>(testPlanExecuteReportDTO.getTestPlanUiScenarioIdAndReportIdMap().values());
|
||||
planReportCaseDTOS = planApiScenarioReportService.selectForPlanReport(reportIds);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceIdSet.contains(MicroServiceName.PERFORMANCE_TEST)) {
|
||||
if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanLoadCaseIdAndReportIdMap())) {
|
||||
// 性能用例
|
||||
reportIds = new ArrayList<>(testPlanExecuteReportDTO.getTestPlanLoadCaseIdAndReportIdMap().values());
|
||||
planReportCaseDTOS = planLoadTestReportService.getPlanReportCaseDTO(reportIds);
|
||||
TestPlanStatusCalculator.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
report.setExecuteRate(0.0);
|
||||
report.setPassRate(0.0);
|
||||
|
||||
// 设置成功率
|
||||
if (report.getCaseCount() != null && report.getCaseCount() != 0) {
|
||||
report.setExecuteRate(report.getExecuteCount() * 1.0 / report.getCaseCount());
|
||||
report.setPassRate(report.getPassCount() * 1.0 / report.getCaseCount());
|
||||
}
|
||||
testPlanReportDTO.setPassRate(report.getPassRate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -475,7 +470,8 @@ public class TestPlanReportService {
|
|||
|
||||
private void updatePassRateAndApiBaseInfoFromReportContent(String status, TestPlanSimpleReportDTO reportDTO, TestPlanReportContentWithBLOBs reportContent, boolean apiBaseInfoChanged) {
|
||||
// 如果报告已结束,则更新测试计划报告通过率字段 passRate
|
||||
if (!StringUtils.equalsIgnoreCase(status, "running") && (Double.compare(reportContent.getPassRate(), reportDTO.getPassRate()) != 0 || apiBaseInfoChanged)) {
|
||||
if (!StringUtils.equalsIgnoreCase(status, APITestStatus.Running.name())
|
||||
&& (Double.compare(reportContent.getPassRate(), reportDTO.getPassRate()) != 0 || apiBaseInfoChanged)) {
|
||||
TestPlanReportContentExample contentExample = new TestPlanReportContentExample();
|
||||
contentExample.createCriteria().andTestPlanReportIdEqualTo(reportContent.getTestPlanReportId());
|
||||
TestPlanReportContentWithBLOBs content = new TestPlanReportContentWithBLOBs();
|
||||
|
@ -1084,6 +1080,10 @@ public class TestPlanReportService {
|
|||
(StringUtils.isNotEmpty(testPlanReportContent.getPlanApiCaseReportStruct()) || StringUtils.isNotEmpty(testPlanReportContent.getPlanScenarioReportStruct()) || StringUtils.isNotEmpty(testPlanReportContent.getPlanLoadCaseReportStruct()) || StringUtils.isNotEmpty(testPlanReportContent.getPlanUiScenarioReportStruct()));
|
||||
}
|
||||
|
||||
private boolean isDynamicallyGenerateReports(String reportId) {
|
||||
return extTestPlanReportContentMapper.isDynamicallyGenerateReport(reportId);
|
||||
}
|
||||
|
||||
private TestPlanReportContentWithBLOBs dynamicallyGenerateReports(TestPlanReportContentWithBLOBs testPlanReportContent) {
|
||||
TestPlanReport report = testPlanReportMapper.selectByPrimaryKey(testPlanReportContent.getTestPlanReportId());
|
||||
testPlanReportContent = this.updateReport(report, testPlanReportContent);
|
||||
|
|
|
@ -12,30 +12,10 @@
|
|||
import TestPlanReportList from './components/TestPlanReportList';
|
||||
import MsContainer from "metersphere-frontend/src/components/MsContainer";
|
||||
import MsMainContainer from "metersphere-frontend/src/components/MsMainContainer";
|
||||
import {TEST_PLAN_REPORT_CONFIGS} from "metersphere-frontend/src/components/search/search-components";
|
||||
|
||||
export default {
|
||||
name: "TestPlanReport",
|
||||
components: {MsMainContainer, MsContainer, TestPlanReportList},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
activated() {
|
||||
this.refreshTestPlanList();
|
||||
},
|
||||
mounted() {
|
||||
this.refreshTestPlanList();
|
||||
},
|
||||
watch: {
|
||||
'$route'(to, from) {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
refreshTestPlanList() {
|
||||
this.$refs.testPlanReportList.condition = {components: TEST_PLAN_REPORT_CONFIGS};
|
||||
this.$refs.testPlanReportList.initTableData();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -234,28 +234,28 @@ export default {
|
|||
}
|
||||
},
|
||||
activated() {
|
||||
|
||||
},
|
||||
created() {
|
||||
this.projectId = this.$route.params.projectId;
|
||||
this.batchButtons = this.publicButtons;
|
||||
this.operators = this.simpleOperators;
|
||||
if (!this.projectId) {
|
||||
this.projectId = getCurrentProjectID();
|
||||
}
|
||||
this.isTestManagerOrTestUser = true;
|
||||
|
||||
this.initTableData();
|
||||
|
||||
// 通知过来的数据跳转到报告
|
||||
if (this.$route.query.resourceId) {
|
||||
testPlanReportGetDb(this.$route.query.resourceId)
|
||||
.then(response => {
|
||||
this.$refs.dbReport.open(response.data);
|
||||
});
|
||||
}
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.projectId = this.$route.params.projectId;
|
||||
this.batchButtons = this.publicButtons;
|
||||
this.operators = this.simpleOperators;
|
||||
if (!this.projectId) {
|
||||
this.projectId = getCurrentProjectID();
|
||||
}
|
||||
this.isTestManagerOrTestUser = true;
|
||||
|
||||
this.initTableData();
|
||||
|
||||
// 通知过来的数据跳转到报告
|
||||
if (this.$route.query.resourceId) {
|
||||
testPlanReportGetDb(this.$route.query.resourceId)
|
||||
.then(response => {
|
||||
this.$refs.dbReport.open(response.data);
|
||||
});
|
||||
}
|
||||
},
|
||||
initTableData() {
|
||||
initCondition(this.condition, this.condition.selectAll);
|
||||
this.condition.orders = getLastTableSortField(this.tableHeaderKey);
|
||||
|
|
Loading…
Reference in New Issue