feat(测试跟踪): 新增批量执行测试计划功能

--user=郭雨琦
This commit is contained in:
guoyuqi 2022-04-07 16:32:43 +08:00 committed by xiaomeinvG
parent 909a8d6678
commit 429ac0ff41
8 changed files with 76 additions and 55 deletions

View File

@ -12,10 +12,7 @@ import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ext.ExtApiExecutionQueueMapper;
import io.metersphere.base.mapper.ext.ExtApiScenarioReportMapper;
import io.metersphere.commons.constants.APITestStatus;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.ExecuteResult;
import io.metersphere.commons.constants.TestPlanReportStatus;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.constants.RunModeConstants;
@ -58,6 +55,10 @@ public class ApiExecutionQueueService {
private ExtApiExecutionQueueMapper extApiExecutionQueueMapper;
@Resource
private ApiScenarioReportResultMapper apiScenarioReportResultMapper;
@Resource
private TestPlanExecutionQueueMapper testPlanExecutionQueueMapper;
@Resource
private TestPlanReportMapper testPlanReportMapper;
@Transactional(propagation = Propagation.REQUIRES_NEW)
@ -394,6 +395,24 @@ public class ApiExecutionQueueService {
}
// 清除异常队列/一般是服务突然停止产生
extApiExecutionQueueMapper.delete();
//清除未及时清理的批量执行测试计划的队列
deleteBatchPlanQueue(timeout);
}
private void deleteBatchPlanQueue(long timeout) {
TestPlanReportExample testPlanReportExample = new TestPlanReportExample();
testPlanReportExample.createCriteria().andTriggerModeEqualTo(TriggerMode.BATCH.name());
testPlanReportExample.createCriteria().andCreateTimeLessThan(timeout);
List<String>status = new ArrayList<>();
status.add("COMPLETED");
status.add("Completed");
testPlanReportExample.createCriteria().andStatusIn(status);
List<TestPlanReport> testPlanReports1 = testPlanReportMapper.selectByExample(testPlanReportExample);
List<String> finishedReportIds = testPlanReports1.stream().map(TestPlanReport::getId).collect(Collectors.toList());
TestPlanExecutionQueueExample testPlanExecutionQueueExample = new TestPlanExecutionQueueExample();
testPlanExecutionQueueExample.createCriteria().andCreateTimeLessThan(timeout);
testPlanExecutionQueueExample.createCriteria().andReportIdIn(finishedReportIds);
testPlanExecutionQueueMapper.deleteByExample(testPlanExecutionQueueExample);
}
public void stop(String reportId) {

View File

@ -15,7 +15,7 @@ public class TestPlanWithBLOBs extends TestPlan implements Serializable {
private String reportConfig;
private String request;
private String runModeConfig;
private static final long serialVersionUID = 1L;
}

View File

@ -27,7 +27,7 @@
<result column="tags" jdbcType="LONGVARCHAR" property="tags" />
<result column="report_summary" jdbcType="LONGVARCHAR" property="reportSummary" />
<result column="report_config" jdbcType="LONGVARCHAR" property="reportConfig" />
<result column="request" jdbcType="LONGVARCHAR" property="request" />
<result column="run_mode_config" jdbcType="LONGVARCHAR" property="runModeConfig" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
@ -94,7 +94,7 @@
repeat_case
</sql>
<sql id="Blob_Column_List">
tags, report_summary, report_config, request
tags, report_summary, report_config, run_mode_config
</sql>
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.base.domain.TestPlanExample" resultMap="ResultMapWithBLOBs">
select
@ -152,7 +152,7 @@
planned_end_time, actual_start_time, actual_end_time,
creator, project_id, execution_times,
automatic_status_update, repeat_case, tags,
report_summary, report_config, request
report_summary, report_config, run_mode_config
)
values (#{id,jdbcType=VARCHAR}, #{workspaceId,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR},
#{name,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
@ -161,7 +161,7 @@
#{plannedEndTime,jdbcType=BIGINT}, #{actualStartTime,jdbcType=BIGINT}, #{actualEndTime,jdbcType=BIGINT},
#{creator,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{executionTimes,jdbcType=INTEGER},
#{automaticStatusUpdate,jdbcType=BIT}, #{repeatCase,jdbcType=BIT}, #{tags,jdbcType=LONGVARCHAR},
#{reportSummary,jdbcType=LONGVARCHAR}, #{reportConfig,jdbcType=LONGVARCHAR}, #{request,jdbcType=LONGVARCHAR}
#{reportSummary,jdbcType=LONGVARCHAR}, #{reportConfig,jdbcType=LONGVARCHAR}, #{runModeConfig,jdbcType=LONGVARCHAR}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlanWithBLOBs">
@ -236,8 +236,8 @@
<if test="reportConfig != null">
report_config,
</if>
<if test="request != null">
request,
<if test="runModeConfig != null">
run_mode_config,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
@ -310,8 +310,8 @@
<if test="reportConfig != null">
#{reportConfig,jdbcType=LONGVARCHAR},
</if>
<if test="request != null">
#{request,jdbcType=LONGVARCHAR},
<if test="runModeConfig != null">
#{runModeConfig,jdbcType=LONGVARCHAR},
</if>
</trim>
</insert>
@ -393,8 +393,8 @@
<if test="record.reportConfig != null">
report_config = #{record.reportConfig,jdbcType=LONGVARCHAR},
</if>
<if test="record.request != null">
request = #{record.request,jdbcType=LONGVARCHAR},
<if test="record.runModeConfig != null">
run_mode_config = #{record.runModeConfig,jdbcType=LONGVARCHAR},
</if>
</set>
<if test="_parameter != null">
@ -426,7 +426,7 @@
tags = #{record.tags,jdbcType=LONGVARCHAR},
report_summary = #{record.reportSummary,jdbcType=LONGVARCHAR},
report_config = #{record.reportConfig,jdbcType=LONGVARCHAR},
request = #{record.request,jdbcType=LONGVARCHAR}
run_mode_config = #{record.runModeConfig,jdbcType=LONGVARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -526,8 +526,8 @@
<if test="reportConfig != null">
report_config = #{reportConfig,jdbcType=LONGVARCHAR},
</if>
<if test="request != null">
request = #{request,jdbcType=LONGVARCHAR},
<if test="runModeConfig != null">
run_mode_config = #{runModeConfig,jdbcType=LONGVARCHAR},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
@ -556,7 +556,7 @@
tags = #{tags,jdbcType=LONGVARCHAR},
report_summary = #{reportSummary,jdbcType=LONGVARCHAR},
report_config = #{reportConfig,jdbcType=LONGVARCHAR},
request = #{request,jdbcType=LONGVARCHAR}
run_mode_config = #{runModeConfig,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.TestPlan">

View File

@ -2,6 +2,7 @@ package io.metersphere.track.request.testplan;
import io.metersphere.track.dto.TestPlanScheduleReportInfoDTO;
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import lombok.Getter;
import lombok.Setter;
@ -26,5 +27,6 @@ public class TestplanRunRequest {
private List<String> testPlanIds;
private Boolean isAll;
private TestPlanScheduleReportInfoDTO planScheduleReportInfoDTO;
private QueryTestPlanRequest queryTestPlanRequest;
}

View File

@ -219,7 +219,7 @@ public class TestPlanReportService {
}
}
public TestPlanScheduleReportInfoDTO genTestPlanReportBySchedule(String projectID, String planReportId, String planId, String userId, String triggerMode) {
public TestPlanScheduleReportInfoDTO genTestPlanReportBySchedule(String planReportId, String planId, String userId, String triggerMode) {
Map<String, String> planScenarioIdMap = new LinkedHashMap<>();
Map<String, String> planTestCaseIdMap = new LinkedHashMap<>();
Map<String, String> performanceIdMap = new LinkedHashMap<>();
@ -252,19 +252,22 @@ public class TestPlanReportService {
performanceInfoMap.put(id, TestPlanApiExecuteStatus.PREPARE.name());
}
TestPlanScheduleReportInfoDTO returnDTO = new TestPlanScheduleReportInfoDTO();
TestPlanReport testPlanReport;
if(StringUtils.isBlank(planReportId)){
planReportId = UUID.randomUUID().toString();
testPlanReport = null;
}else{
testPlanReport= this.getTestPlanReport(planReportId);
returnDTO.setTestPlanReport(testPlanReport);
}
TestPlanReportSaveRequest saveRequest = new TestPlanReportSaveRequest(planReportId, planId, userId, triggerMode,
planTestCaseIdMap.size() > 0, planScenarioIdMap.size() > 0, performanceIdMap.size() > 0,
apiCaseInfoMap, scenarioInfoMap, performanceInfoMap);
TestPlanScheduleReportInfoDTO returnDTO = new TestPlanScheduleReportInfoDTO();
TestPlanReport testPlanReport = this.getTestPlanReport(planReportId);
if(testPlanReport==null){
returnDTO = this.genTestPlanReport(saveRequest);
}else{
returnDTO.setTestPlanReport(testPlanReport);
}
returnDTO.setPlanScenarioIdMap(planScenarioIdMap);
returnDTO.setApiTestCaseDataMap(planTestCaseIdMap);
@ -550,11 +553,14 @@ public class TestPlanReportService {
TestPlanExecutionQueueExample queueExample = new TestPlanExecutionQueueExample();
queueExample.createCriteria().andReportIdIsNotNull();
List<TestPlanExecutionQueue> planExecutionQueueList = testPlanExecutionQueueMapper.selectByExample(testPlanExecutionQueueExample);
if(planExecutionQueueList==null||planExecutionQueueList.size()==0){
return testPlanReport;
}
TestPlanExecutionQueue testPlanExecutionQueue = planExecutionQueueList.get(0);
TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(testPlanExecutionQueue.getTestPlanId());
JSONObject jsonObject = JSONObject.parseObject(testPlan.getRequest());
JSONObject jsonObject = JSONObject.parseObject(testPlan.getRunModeConfig());
TestplanRunRequest runRequest = JSON.toJavaObject(jsonObject,TestplanRunRequest.class);
TestPlanScheduleReportInfoDTO testPlanScheduleReportInfoDTO = this.genTestPlanReportBySchedule(null, testPlanExecutionQueue.getReportId(), testPlanExecutionQueue.getTestPlanId(), runRequest.getUserId(), runRequest.getTriggerMode());
TestPlanScheduleReportInfoDTO testPlanScheduleReportInfoDTO = this.genTestPlanReportBySchedule( testPlanExecutionQueue.getReportId(), testPlanExecutionQueue.getTestPlanId(), runRequest.getUserId(), runRequest.getTriggerMode());
runRequest.setPlanScheduleReportInfoDTO(testPlanScheduleReportInfoDTO);
testPlanService.runPlan(runRequest);
}

View File

@ -1010,7 +1010,7 @@ public class TestPlanService {
@Transactional(propagation = Propagation.NOT_SUPPORTED)
TestPlanScheduleReportInfoDTO genTestPlanReport(String projectID, String planId, String userId, String triggerMode) {
TestPlanScheduleReportInfoDTO reportInfoDTO = testPlanReportService.genTestPlanReportBySchedule(projectID,null, planId, userId, triggerMode);
TestPlanScheduleReportInfoDTO reportInfoDTO = testPlanReportService.genTestPlanReportBySchedule(null, planId, userId, triggerMode);
return reportInfoDTO;
}
@ -1935,15 +1935,12 @@ public class TestPlanService {
String apiRunConfig = JSONObject.toJSONString(runModeConfig);
String request = JSON.toJSONString(testplanRunRequest);
TestPlanWithBLOBs testPlanWithBLOBs = testPlanMapper.selectByPrimaryKey(testPlanId);
testPlanWithBLOBs.setRequest(request);
if(testPlanWithBLOBs.getRunModeConfig()==null||!(StringUtils.equals(request,testPlanWithBLOBs.getRunModeConfig()))){
testPlanWithBLOBs.setRunModeConfig(request);
testPlanMapper.updateByPrimaryKeyWithBLOBs(testPlanWithBLOBs);
if(testplanRunRequest.getPlanScheduleReportInfoDTO()!=null){
return this.run(testPlanId, testplanRunRequest.getProjectId(),
testplanRunRequest.getUserId(), testplanRunRequest.getTriggerMode(),testplanRunRequest.getPlanScheduleReportInfoDTO(), apiRunConfig);
}else{
return this.run(testPlanId, testplanRunRequest.getProjectId(),
testplanRunRequest.getUserId(), testplanRunRequest.getTriggerMode(),null, apiRunConfig);
}
return this.run(testPlanId, testplanRunRequest.getProjectId(),
testplanRunRequest.getUserId(), testplanRunRequest.getTriggerMode(),testplanRunRequest.getPlanScheduleReportInfoDTO() != null ? testplanRunRequest.getPlanScheduleReportInfoDTO() : null, apiRunConfig);
}
@ -2118,15 +2115,24 @@ public class TestPlanService {
if (CollectionUtils.isEmpty(ids)&&!request.getIsAll()) {
return new LinkedList<>();
}
LoggerUtil.debug("开始查询测试计划");
List<TestPlanWithBLOBs> planList = getTestPlanWithBLOBs(request, ids);
LoggerUtil.info("开始查询测试计划");
List<TestPlanWithBLOBs> planList = new ArrayList<>();
if(request.getIsAll()!=null&&request.getIsAll()){
List<TestPlanDTOWithMetric> testPlanDTOWithMetrics = this.listTestPlan(request.getQueryTestPlanRequest());
planList.addAll(testPlanDTOWithMetrics);
}else{
TestPlanExample example = new TestPlanExample();
example.createCriteria().andIdIn(ids);
example.createCriteria().andProjectIdEqualTo(request.getProjectId());
planList = testPlanMapper.selectByExampleWithBLOBs(example);
}
Map<String, TestPlanWithBLOBs> testPlanMap = planList.stream().collect(Collectors.toMap(TestPlan::getId, a -> a,(k1,k2)->k1));
Map<String, TestPlanReport> executeQueue = new LinkedHashMap<>();
List<MsExecResponseDTO> responseDTOS = new LinkedList<>();
Map<String, TestPlanScheduleReportInfoDTO> planScheduleReportInfoDTOMap = new LinkedHashMap<>();
for (TestPlanWithBLOBs testPlan : planList) {
if(StringUtils.isBlank(testPlan.getRequest())){
if(StringUtils.isBlank(testPlan.getRunModeConfig())){
MSException.throwException("请保存["+testPlan.getName()+"]的运行配置");
}
//创建测试报告然后返回的ID重新赋值为resourceID作为后续的参数
@ -2135,15 +2141,12 @@ public class TestPlanService {
//测试计划准备执行取消测试计划的实际结束时间
extTestPlanMapper.updateActualEndTimeIsNullById(testPlan.getId());
String planReportId = reportInfoDTO.getTestPlanReport().getId();
testPlanLog.info("ReportId[" + planReportId + "] created. TestPlanID:[" + testPlan.getId() + "] ");
executeQueue.put(testPlan.getId(), reportInfoDTO.getTestPlanReport());
responseDTOS.add(new MsExecResponseDTO(testPlan.getId(), reportInfoDTO.getTestPlanReport().getId(), request.getTriggerMode()));
planScheduleReportInfoDTOMap.put(testPlan.getId(),reportInfoDTO);
}
LoggerUtil.debug("开始生成测试计划队列");
LoggerUtil.info("开始生成测试计划队列");
List<TestPlanExecutionQueue> planExecutionQueues = getTestPlanExecutionQueues(request, executeQueue);
@ -2179,14 +2182,14 @@ public class TestPlanService {
if(StringUtils.equalsIgnoreCase(request.getMode(),"serial")){
TestPlanExecutionQueue planExecutionQueue = planExecutionQueues.get(0);
TestPlanWithBLOBs testPlan = testPlanMap.get(planExecutionQueue.getTestPlanId());
JSONObject jsonObject = JSONObject.parseObject(testPlan.getRequest());
JSONObject jsonObject = JSONObject.parseObject(testPlan.getRunModeConfig());
TestplanRunRequest runRequest = JSON.toJavaObject(jsonObject,TestplanRunRequest.class);
runRequest.setPlanScheduleReportInfoDTO(planScheduleReportInfoDTOMap.get(planExecutionQueue.getTestPlanId()));
runPlan(runRequest);
}else {
for (TestPlanExecutionQueue planExecutionQueue : planExecutionQueues) {
TestPlanWithBLOBs testPlan = testPlanMap.get(planExecutionQueue.getTestPlanId());
JSONObject jsonObject = JSONObject.parseObject(testPlan.getRequest());
JSONObject jsonObject = JSONObject.parseObject(testPlan.getRunModeConfig());
TestplanRunRequest runRequest = JSON.toJavaObject(jsonObject,TestplanRunRequest.class);
runRequest.setPlanScheduleReportInfoDTO(planScheduleReportInfoDTOMap.get(planExecutionQueue.getTestPlanId()));
runPlan(runRequest);
@ -2198,14 +2201,4 @@ public class TestPlanService {
}
}
private List<TestPlanWithBLOBs> getTestPlanWithBLOBs(TestplanRunRequest request, List<String> ids) {
TestPlanExample example = new TestPlanExample();
if(CollectionUtils.isNotEmpty(ids)){
example.createCriteria().andIdIn(ids);
}
example.createCriteria().andProjectIdEqualTo(request.getProjectId());
List<TestPlanWithBLOBs> planList = testPlanMapper.selectByExampleWithBLOBs(example);
return planList;
}
}

View File

@ -123,7 +123,7 @@ END//
DELIMITER ;
CALL schema_change();
ALTER TABLE `test_plan` ADD COLUMN `request` LONGTEXT COMMENT 'request (JSON format)';
ALTER TABLE `test_plan` ADD COLUMN `run_mode_config` LONGTEXT COMMENT 'request (JSON format)';
--
INSERT INTO user_group_permission (id, group_id, permission_id, module_id)

View File

@ -627,6 +627,7 @@ export default {
const ids = [];
if (this.condition.selectAll) {
param.isAll = true;
param.queryTestPlanRequest = this.condition
}
else {
this.$refs.testPlanLitTable.selectRows.forEach((item) => {