feat: 执行测试计划接口用例后更新关联的功能用例状态

This commit is contained in:
chenjianxing 2021-06-16 15:25:22 +08:00 committed by jianxing
parent 5fa131b13c
commit 0ed0330dfb
12 changed files with 364 additions and 103 deletions

View File

@ -15,8 +15,10 @@ import io.metersphere.i18n.Translator;
import io.metersphere.notice.sender.NoticeModel; import io.metersphere.notice.sender.NoticeModel;
import io.metersphere.notice.service.NoticeSendService; import io.metersphere.notice.service.NoticeSendService;
import io.metersphere.service.SystemParameterService; import io.metersphere.service.SystemParameterService;
import io.metersphere.track.request.testcase.TrackCount;
import io.metersphere.track.service.TestPlanApiCaseService; import io.metersphere.track.service.TestPlanApiCaseService;
import io.metersphere.track.service.TestPlanReportService; import io.metersphere.track.service.TestPlanReportService;
import io.metersphere.track.service.TestPlanScenarioCaseService;
import io.metersphere.track.service.TestPlanTestCaseService; import io.metersphere.track.service.TestPlanTestCaseService;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -208,6 +210,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
ApiTestReport report = null; ApiTestReport report = null;
ApiTestReportVariable reportTask = null; ApiTestReportVariable reportTask = null;
String reportUrl = null; String reportUrl = null;
String planScenarioId = null;
// 这部分后续优化只留 DEFINITION SCENARIO 两部分 // 这部分后续优化只留 DEFINITION SCENARIO 两部分
if (StringUtils.equals(this.runMode, ApiRunMode.DEBUG.name())) { if (StringUtils.equals(this.runMode, ApiRunMode.DEBUG.name())) {
report = apiReportService.get(debugReportId); report = apiReportService.get(debugReportId);
@ -335,6 +338,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo(); BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
reportUrl = baseSystemConfigDTO.getUrl() + "/#/api/automation/report"; reportUrl = baseSystemConfigDTO.getUrl() + "/#/api/automation/report";
testResult.setTestId(scenarioReport.getScenarioId()); testResult.setTestId(scenarioReport.getScenarioId());
planScenarioId = scenarioReport.getTestPlanScenarioId();
} else { } else {
apiTestService.changeStatus(testId, APITestStatus.Completed); apiTestService.changeStatus(testId, APITestStatus.Completed);
report = apiReportService.getRunningReport(testResult.getTestId()); report = apiReportService.getRunningReport(testResult.getTestId());
@ -343,6 +347,8 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
queue.clear(); queue.clear();
super.teardownTest(context); super.teardownTest(context);
updateTestCaseStates(testResult, planScenarioId);
List<String> ids = testPlanTestCaseService.getTestPlanTestCaseIds(testResult.getTestId()); List<String> ids = testPlanTestCaseService.getTestPlanTestCaseIds(testResult.getTestId());
if (ids.size() > 0) { if (ids.size() > 0) {
try { try {
@ -363,6 +369,37 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
} }
/**
* 更新测试计划关联接口测试的功能用例的状态
* @param testResult
*/
private void updateTestCaseStates(TestResult testResult, String testPlanScenarioId) {
try {
if (StringUtils.equalsAny(this.runMode, ApiRunMode.API_PLAN.name(), ApiRunMode.SCHEDULE_API_PLAN.name(),
ApiRunMode.JENKINS_API_PLAN.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name())) {
testResult.getScenarios().forEach(scenarioResult -> {
if (scenarioResult != null && CollectionUtils.isNotEmpty(scenarioResult.getRequestResults())) {
scenarioResult.getRequestResults().forEach(item -> {
if (StringUtils.equalsAny(this.runMode, ApiRunMode.API_PLAN.name(), ApiRunMode.SCHEDULE_API_PLAN.name(),
ApiRunMode.JENKINS_API_PLAN.name())) {
TestPlanApiCase testPlanApiCase = testPlanApiCaseService.getById(item.getName());
ApiTestCaseWithBLOBs apiTestCase = apiTestCaseService.get(testPlanApiCase.getApiCaseId());
testPlanTestCaseService.updateTestCaseStates(apiTestCase.getId(), apiTestCase.getName(), testPlanApiCase.getTestPlanId(), TrackCount.TESTCASE);
} else {
TestPlanScenarioCaseService testPlanScenarioCaseService = CommonBeanFactory.getBean(TestPlanScenarioCaseService.class);
TestPlanApiScenario testPlanApiScenario = testPlanScenarioCaseService.get(testPlanScenarioId);
ApiScenarioWithBLOBs apiScenario = apiAutomationService.getApiScenario(testPlanApiScenario.getApiScenarioId());
testPlanTestCaseService.updateTestCaseStates(apiScenario.getId(), apiScenario.getName(), testPlanApiScenario.getTestPlanId(), TrackCount.AUTOMATION);
}
});
}
});
}
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
}
}
private static void sendTask(ApiTestReportVariable report, String reportUrl, TestResult testResult) { private static void sendTask(ApiTestReportVariable report, String reportUrl, TestResult testResult) {
if (report == null) { if (report == null) {
return; return;

View File

@ -233,6 +233,7 @@ public class ApiScenarioReportService {
testPlanApiScenario.setPassRate(passRate); testPlanApiScenario.setPassRate(passRate);
testPlanApiScenario.setReportId(report.getId()); testPlanApiScenario.setReportId(report.getId());
testPlanApiScenario.setUpdateTime(report.getCreateTime()); testPlanApiScenario.setUpdateTime(report.getCreateTime());
report.setTestPlanScenarioId(testPlanApiScenario.getId());
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario); testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
} }
returnReport = report; returnReport = report;
@ -280,6 +281,7 @@ public class ApiScenarioReportService {
} }
TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(planScenarioId); TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(planScenarioId);
report.setScenarioId(testPlanApiScenario.getApiScenarioId()); report.setScenarioId(testPlanApiScenario.getApiScenarioId());
report.setTestPlanScenarioId(planScenarioId);
apiScenarioReportMapper.updateByPrimaryKeySelective(report); apiScenarioReportMapper.updateByPrimaryKeySelective(report);
if (scenarioResult.getError() > 0) { if (scenarioResult.getError() > 0) {
testPlanApiScenario.setLastResult(ScenarioStatus.Fail.name()); testPlanApiScenario.setLastResult(ScenarioStatus.Fail.name());

View File

@ -31,5 +31,7 @@ public class ApiScenarioReport implements Serializable {
private String description; private String description;
private String testPlanScenarioId;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@ -1,8 +1,7 @@
package io.metersphere.base.domain; package io.metersphere.base.domain;
import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import lombok.Data;
@Data @Data
public class TestPlan implements Serializable { public class TestPlan implements Serializable {
@ -30,20 +29,22 @@ public class TestPlan implements Serializable {
private Long updateTime; private Long updateTime;
private Long actualEndTime;
private Long plannedStartTime; private Long plannedStartTime;
private Long plannedEndTime; private Long plannedEndTime;
private Long actualStartTime; private Long actualStartTime;
private Long actualEndTime;
private String creator; private String creator;
private String projectId; private String projectId;
private Integer executionTimes; private Integer executionTimes;
private Boolean automaticStatusUpdate;
private String tags; private String tags;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -924,66 +924,6 @@ public class TestPlanExample {
return (Criteria) this; return (Criteria) this;
} }
public Criteria andActualEndTimeIsNull() {
addCriterion("actual_end_time is null");
return (Criteria) this;
}
public Criteria andActualEndTimeIsNotNull() {
addCriterion("actual_end_time is not null");
return (Criteria) this;
}
public Criteria andActualEndTimeEqualTo(Long value) {
addCriterion("actual_end_time =", value, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeNotEqualTo(Long value) {
addCriterion("actual_end_time <>", value, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeGreaterThan(Long value) {
addCriterion("actual_end_time >", value, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeGreaterThanOrEqualTo(Long value) {
addCriterion("actual_end_time >=", value, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeLessThan(Long value) {
addCriterion("actual_end_time <", value, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeLessThanOrEqualTo(Long value) {
addCriterion("actual_end_time <=", value, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeIn(List<Long> values) {
addCriterion("actual_end_time in", values, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeNotIn(List<Long> values) {
addCriterion("actual_end_time not in", values, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeBetween(Long value1, Long value2) {
addCriterion("actual_end_time between", value1, value2, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeNotBetween(Long value1, Long value2) {
addCriterion("actual_end_time not between", value1, value2, "actualEndTime");
return (Criteria) this;
}
public Criteria andPlannedStartTimeIsNull() { public Criteria andPlannedStartTimeIsNull() {
addCriterion("planned_start_time is null"); addCriterion("planned_start_time is null");
return (Criteria) this; return (Criteria) this;
@ -1164,6 +1104,66 @@ public class TestPlanExample {
return (Criteria) this; return (Criteria) this;
} }
public Criteria andActualEndTimeIsNull() {
addCriterion("actual_end_time is null");
return (Criteria) this;
}
public Criteria andActualEndTimeIsNotNull() {
addCriterion("actual_end_time is not null");
return (Criteria) this;
}
public Criteria andActualEndTimeEqualTo(Long value) {
addCriterion("actual_end_time =", value, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeNotEqualTo(Long value) {
addCriterion("actual_end_time <>", value, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeGreaterThan(Long value) {
addCriterion("actual_end_time >", value, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeGreaterThanOrEqualTo(Long value) {
addCriterion("actual_end_time >=", value, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeLessThan(Long value) {
addCriterion("actual_end_time <", value, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeLessThanOrEqualTo(Long value) {
addCriterion("actual_end_time <=", value, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeIn(List<Long> values) {
addCriterion("actual_end_time in", values, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeNotIn(List<Long> values) {
addCriterion("actual_end_time not in", values, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeBetween(Long value1, Long value2) {
addCriterion("actual_end_time between", value1, value2, "actualEndTime");
return (Criteria) this;
}
public Criteria andActualEndTimeNotBetween(Long value1, Long value2) {
addCriterion("actual_end_time not between", value1, value2, "actualEndTime");
return (Criteria) this;
}
public Criteria andCreatorIsNull() { public Criteria andCreatorIsNull() {
addCriterion("creator is null"); addCriterion("creator is null");
return (Criteria) this; return (Criteria) this;
@ -1363,6 +1363,66 @@ public class TestPlanExample {
addCriterion("execution_times not between", value1, value2, "executionTimes"); addCriterion("execution_times not between", value1, value2, "executionTimes");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andAutomaticStatusUpdateIsNull() {
addCriterion("automatic_status_update is null");
return (Criteria) this;
}
public Criteria andAutomaticStatusUpdateIsNotNull() {
addCriterion("automatic_status_update is not null");
return (Criteria) this;
}
public Criteria andAutomaticStatusUpdateEqualTo(Boolean value) {
addCriterion("automatic_status_update =", value, "automaticStatusUpdate");
return (Criteria) this;
}
public Criteria andAutomaticStatusUpdateNotEqualTo(Boolean value) {
addCriterion("automatic_status_update <>", value, "automaticStatusUpdate");
return (Criteria) this;
}
public Criteria andAutomaticStatusUpdateGreaterThan(Boolean value) {
addCriterion("automatic_status_update >", value, "automaticStatusUpdate");
return (Criteria) this;
}
public Criteria andAutomaticStatusUpdateGreaterThanOrEqualTo(Boolean value) {
addCriterion("automatic_status_update >=", value, "automaticStatusUpdate");
return (Criteria) this;
}
public Criteria andAutomaticStatusUpdateLessThan(Boolean value) {
addCriterion("automatic_status_update <", value, "automaticStatusUpdate");
return (Criteria) this;
}
public Criteria andAutomaticStatusUpdateLessThanOrEqualTo(Boolean value) {
addCriterion("automatic_status_update <=", value, "automaticStatusUpdate");
return (Criteria) this;
}
public Criteria andAutomaticStatusUpdateIn(List<Boolean> values) {
addCriterion("automatic_status_update in", values, "automaticStatusUpdate");
return (Criteria) this;
}
public Criteria andAutomaticStatusUpdateNotIn(List<Boolean> values) {
addCriterion("automatic_status_update not in", values, "automaticStatusUpdate");
return (Criteria) this;
}
public Criteria andAutomaticStatusUpdateBetween(Boolean value1, Boolean value2) {
addCriterion("automatic_status_update between", value1, value2, "automaticStatusUpdate");
return (Criteria) this;
}
public Criteria andAutomaticStatusUpdateNotBetween(Boolean value1, Boolean value2) {
addCriterion("automatic_status_update not between", value1, value2, "automaticStatusUpdate");
return (Criteria) this;
}
} }
public static class Criteria extends GeneratedCriteria { public static class Criteria extends GeneratedCriteria {

View File

@ -14,13 +14,14 @@
<result column="executor_match_rule" jdbcType="VARCHAR" property="executorMatchRule" /> <result column="executor_match_rule" jdbcType="VARCHAR" property="executorMatchRule" />
<result column="create_time" jdbcType="BIGINT" property="createTime" /> <result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" /> <result column="update_time" jdbcType="BIGINT" property="updateTime" />
<result column="actual_end_time" jdbcType="BIGINT" property="actualEndTime" />
<result column="planned_start_time" jdbcType="BIGINT" property="plannedStartTime" /> <result column="planned_start_time" jdbcType="BIGINT" property="plannedStartTime" />
<result column="planned_end_time" jdbcType="BIGINT" property="plannedEndTime" /> <result column="planned_end_time" jdbcType="BIGINT" property="plannedEndTime" />
<result column="actual_start_time" jdbcType="BIGINT" property="actualStartTime" /> <result column="actual_start_time" jdbcType="BIGINT" property="actualStartTime" />
<result column="actual_end_time" jdbcType="BIGINT" property="actualEndTime" />
<result column="creator" jdbcType="VARCHAR" property="creator" /> <result column="creator" jdbcType="VARCHAR" property="creator" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" /> <result column="project_id" jdbcType="VARCHAR" property="projectId" />
<result column="execution_times" jdbcType="INTEGER" property="executionTimes" /> <result column="execution_times" jdbcType="INTEGER" property="executionTimes" />
<result column="automatic_status_update" jdbcType="BIT" property="automaticStatusUpdate" />
</resultMap> </resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestPlan"> <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestPlan">
<result column="tags" jdbcType="LONGVARCHAR" property="tags" /> <result column="tags" jdbcType="LONGVARCHAR" property="tags" />
@ -85,8 +86,8 @@
</sql> </sql>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id, workspace_id, report_id, `name`, description, `status`, stage, principal, test_case_match_rule, id, workspace_id, report_id, `name`, description, `status`, stage, principal, test_case_match_rule,
executor_match_rule, create_time, update_time, actual_end_time, planned_start_time, executor_match_rule, create_time, update_time, planned_start_time, planned_end_time,
planned_end_time, actual_start_time, creator, project_id, execution_times actual_start_time, actual_end_time, creator, project_id, execution_times, automatic_status_update
</sql> </sql>
<sql id="Blob_Column_List"> <sql id="Blob_Column_List">
tags tags
@ -144,16 +145,18 @@
`name`, description, `status`, `name`, description, `status`,
stage, principal, test_case_match_rule, stage, principal, test_case_match_rule,
executor_match_rule, create_time, update_time, executor_match_rule, create_time, update_time,
actual_end_time, planned_start_time, planned_end_time, planned_start_time, planned_end_time, actual_start_time,
actual_start_time, creator, project_id, actual_end_time, creator, project_id,
execution_times, tags) execution_times, automatic_status_update, tags
)
values (#{id,jdbcType=VARCHAR}, #{workspaceId,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR}, values (#{id,jdbcType=VARCHAR}, #{workspaceId,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR},
#{name,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
#{stage,jdbcType=VARCHAR}, #{principal,jdbcType=VARCHAR}, #{testCaseMatchRule,jdbcType=VARCHAR}, #{stage,jdbcType=VARCHAR}, #{principal,jdbcType=VARCHAR}, #{testCaseMatchRule,jdbcType=VARCHAR},
#{executorMatchRule,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{executorMatchRule,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
#{actualEndTime,jdbcType=BIGINT}, #{plannedStartTime,jdbcType=BIGINT}, #{plannedEndTime,jdbcType=BIGINT}, #{plannedStartTime,jdbcType=BIGINT}, #{plannedEndTime,jdbcType=BIGINT}, #{actualStartTime,jdbcType=BIGINT},
#{actualStartTime,jdbcType=BIGINT}, #{creator,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{actualEndTime,jdbcType=BIGINT}, #{creator,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR},
#{executionTimes,jdbcType=INTEGER}, #{tags,jdbcType=LONGVARCHAR}) #{executionTimes,jdbcType=INTEGER}, #{automaticStatusUpdate,jdbcType=BIT}, #{tags,jdbcType=LONGVARCHAR}
)
</insert> </insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlan"> <insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlan">
insert into test_plan insert into test_plan
@ -194,9 +197,6 @@
<if test="updateTime != null"> <if test="updateTime != null">
update_time, update_time,
</if> </if>
<if test="actualEndTime != null">
actual_end_time,
</if>
<if test="plannedStartTime != null"> <if test="plannedStartTime != null">
planned_start_time, planned_start_time,
</if> </if>
@ -206,6 +206,9 @@
<if test="actualStartTime != null"> <if test="actualStartTime != null">
actual_start_time, actual_start_time,
</if> </if>
<if test="actualEndTime != null">
actual_end_time,
</if>
<if test="creator != null"> <if test="creator != null">
creator, creator,
</if> </if>
@ -215,6 +218,9 @@
<if test="executionTimes != null"> <if test="executionTimes != null">
execution_times, execution_times,
</if> </if>
<if test="automaticStatusUpdate != null">
automatic_status_update,
</if>
<if test="tags != null"> <if test="tags != null">
tags, tags,
</if> </if>
@ -256,9 +262,6 @@
<if test="updateTime != null"> <if test="updateTime != null">
#{updateTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
</if> </if>
<if test="actualEndTime != null">
#{actualEndTime,jdbcType=BIGINT},
</if>
<if test="plannedStartTime != null"> <if test="plannedStartTime != null">
#{plannedStartTime,jdbcType=BIGINT}, #{plannedStartTime,jdbcType=BIGINT},
</if> </if>
@ -268,6 +271,9 @@
<if test="actualStartTime != null"> <if test="actualStartTime != null">
#{actualStartTime,jdbcType=BIGINT}, #{actualStartTime,jdbcType=BIGINT},
</if> </if>
<if test="actualEndTime != null">
#{actualEndTime,jdbcType=BIGINT},
</if>
<if test="creator != null"> <if test="creator != null">
#{creator,jdbcType=VARCHAR}, #{creator,jdbcType=VARCHAR},
</if> </if>
@ -277,6 +283,9 @@
<if test="executionTimes != null"> <if test="executionTimes != null">
#{executionTimes,jdbcType=INTEGER}, #{executionTimes,jdbcType=INTEGER},
</if> </if>
<if test="automaticStatusUpdate != null">
#{automaticStatusUpdate,jdbcType=BIT},
</if>
<if test="tags != null"> <if test="tags != null">
#{tags,jdbcType=LONGVARCHAR}, #{tags,jdbcType=LONGVARCHAR},
</if> </if>
@ -327,9 +336,6 @@
<if test="record.updateTime != null"> <if test="record.updateTime != null">
update_time = #{record.updateTime,jdbcType=BIGINT}, update_time = #{record.updateTime,jdbcType=BIGINT},
</if> </if>
<if test="record.actualEndTime != null">
actual_end_time = #{record.actualEndTime,jdbcType=BIGINT},
</if>
<if test="record.plannedStartTime != null"> <if test="record.plannedStartTime != null">
planned_start_time = #{record.plannedStartTime,jdbcType=BIGINT}, planned_start_time = #{record.plannedStartTime,jdbcType=BIGINT},
</if> </if>
@ -339,6 +345,9 @@
<if test="record.actualStartTime != null"> <if test="record.actualStartTime != null">
actual_start_time = #{record.actualStartTime,jdbcType=BIGINT}, actual_start_time = #{record.actualStartTime,jdbcType=BIGINT},
</if> </if>
<if test="record.actualEndTime != null">
actual_end_time = #{record.actualEndTime,jdbcType=BIGINT},
</if>
<if test="record.creator != null"> <if test="record.creator != null">
creator = #{record.creator,jdbcType=VARCHAR}, creator = #{record.creator,jdbcType=VARCHAR},
</if> </if>
@ -348,6 +357,9 @@
<if test="record.executionTimes != null"> <if test="record.executionTimes != null">
execution_times = #{record.executionTimes,jdbcType=INTEGER}, execution_times = #{record.executionTimes,jdbcType=INTEGER},
</if> </if>
<if test="record.automaticStatusUpdate != null">
automatic_status_update = #{record.automaticStatusUpdate,jdbcType=BIT},
</if>
<if test="record.tags != null"> <if test="record.tags != null">
tags = #{record.tags,jdbcType=LONGVARCHAR}, tags = #{record.tags,jdbcType=LONGVARCHAR},
</if> </if>
@ -370,13 +382,14 @@
executor_match_rule = #{record.executorMatchRule,jdbcType=VARCHAR}, executor_match_rule = #{record.executorMatchRule,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT}, create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT}, update_time = #{record.updateTime,jdbcType=BIGINT},
actual_end_time = #{record.actualEndTime,jdbcType=BIGINT},
planned_start_time = #{record.plannedStartTime,jdbcType=BIGINT}, planned_start_time = #{record.plannedStartTime,jdbcType=BIGINT},
planned_end_time = #{record.plannedEndTime,jdbcType=BIGINT}, planned_end_time = #{record.plannedEndTime,jdbcType=BIGINT},
actual_start_time = #{record.actualStartTime,jdbcType=BIGINT}, actual_start_time = #{record.actualStartTime,jdbcType=BIGINT},
actual_end_time = #{record.actualEndTime,jdbcType=BIGINT},
creator = #{record.creator,jdbcType=VARCHAR}, creator = #{record.creator,jdbcType=VARCHAR},
project_id = #{record.projectId,jdbcType=VARCHAR}, project_id = #{record.projectId,jdbcType=VARCHAR},
execution_times = #{record.executionTimes,jdbcType=INTEGER}, execution_times = #{record.executionTimes,jdbcType=INTEGER},
automatic_status_update = #{record.automaticStatusUpdate,jdbcType=BIT},
tags = #{record.tags,jdbcType=LONGVARCHAR} tags = #{record.tags,jdbcType=LONGVARCHAR}
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" /> <include refid="Update_By_Example_Where_Clause" />
@ -396,13 +409,14 @@
executor_match_rule = #{record.executorMatchRule,jdbcType=VARCHAR}, executor_match_rule = #{record.executorMatchRule,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT}, create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT}, update_time = #{record.updateTime,jdbcType=BIGINT},
actual_end_time = #{record.actualEndTime,jdbcType=BIGINT},
planned_start_time = #{record.plannedStartTime,jdbcType=BIGINT}, planned_start_time = #{record.plannedStartTime,jdbcType=BIGINT},
planned_end_time = #{record.plannedEndTime,jdbcType=BIGINT}, planned_end_time = #{record.plannedEndTime,jdbcType=BIGINT},
actual_start_time = #{record.actualStartTime,jdbcType=BIGINT}, actual_start_time = #{record.actualStartTime,jdbcType=BIGINT},
actual_end_time = #{record.actualEndTime,jdbcType=BIGINT},
creator = #{record.creator,jdbcType=VARCHAR}, creator = #{record.creator,jdbcType=VARCHAR},
project_id = #{record.projectId,jdbcType=VARCHAR}, project_id = #{record.projectId,jdbcType=VARCHAR},
execution_times = #{record.executionTimes,jdbcType=INTEGER} execution_times = #{record.executionTimes,jdbcType=INTEGER},
automatic_status_update = #{record.automaticStatusUpdate,jdbcType=BIT}
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" /> <include refid="Update_By_Example_Where_Clause" />
</if> </if>
@ -443,9 +457,6 @@
<if test="updateTime != null"> <if test="updateTime != null">
update_time = #{updateTime,jdbcType=BIGINT}, update_time = #{updateTime,jdbcType=BIGINT},
</if> </if>
<if test="actualEndTime != null">
actual_end_time = #{actualEndTime,jdbcType=BIGINT},
</if>
<if test="plannedStartTime != null"> <if test="plannedStartTime != null">
planned_start_time = #{plannedStartTime,jdbcType=BIGINT}, planned_start_time = #{plannedStartTime,jdbcType=BIGINT},
</if> </if>
@ -455,6 +466,9 @@
<if test="actualStartTime != null"> <if test="actualStartTime != null">
actual_start_time = #{actualStartTime,jdbcType=BIGINT}, actual_start_time = #{actualStartTime,jdbcType=BIGINT},
</if> </if>
<if test="actualEndTime != null">
actual_end_time = #{actualEndTime,jdbcType=BIGINT},
</if>
<if test="creator != null"> <if test="creator != null">
creator = #{creator,jdbcType=VARCHAR}, creator = #{creator,jdbcType=VARCHAR},
</if> </if>
@ -464,6 +478,9 @@
<if test="executionTimes != null"> <if test="executionTimes != null">
execution_times = #{executionTimes,jdbcType=INTEGER}, execution_times = #{executionTimes,jdbcType=INTEGER},
</if> </if>
<if test="automaticStatusUpdate != null">
automatic_status_update = #{automaticStatusUpdate,jdbcType=BIT},
</if>
<if test="tags != null"> <if test="tags != null">
tags = #{tags,jdbcType=LONGVARCHAR}, tags = #{tags,jdbcType=LONGVARCHAR},
</if> </if>
@ -483,13 +500,14 @@
executor_match_rule = #{executorMatchRule,jdbcType=VARCHAR}, executor_match_rule = #{executorMatchRule,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT}, create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT}, update_time = #{updateTime,jdbcType=BIGINT},
actual_end_time = #{actualEndTime,jdbcType=BIGINT},
planned_start_time = #{plannedStartTime,jdbcType=BIGINT}, planned_start_time = #{plannedStartTime,jdbcType=BIGINT},
planned_end_time = #{plannedEndTime,jdbcType=BIGINT}, planned_end_time = #{plannedEndTime,jdbcType=BIGINT},
actual_start_time = #{actualStartTime,jdbcType=BIGINT}, actual_start_time = #{actualStartTime,jdbcType=BIGINT},
actual_end_time = #{actualEndTime,jdbcType=BIGINT},
creator = #{creator,jdbcType=VARCHAR}, creator = #{creator,jdbcType=VARCHAR},
project_id = #{projectId,jdbcType=VARCHAR}, project_id = #{projectId,jdbcType=VARCHAR},
execution_times = #{executionTimes,jdbcType=INTEGER}, execution_times = #{executionTimes,jdbcType=INTEGER},
automatic_status_update = #{automaticStatusUpdate,jdbcType=BIT},
tags = #{tags,jdbcType=LONGVARCHAR} tags = #{tags,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</update> </update>
@ -506,13 +524,14 @@
executor_match_rule = #{executorMatchRule,jdbcType=VARCHAR}, executor_match_rule = #{executorMatchRule,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT}, create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT}, update_time = #{updateTime,jdbcType=BIGINT},
actual_end_time = #{actualEndTime,jdbcType=BIGINT},
planned_start_time = #{plannedStartTime,jdbcType=BIGINT}, planned_start_time = #{plannedStartTime,jdbcType=BIGINT},
planned_end_time = #{plannedEndTime,jdbcType=BIGINT}, planned_end_time = #{plannedEndTime,jdbcType=BIGINT},
actual_start_time = #{actualStartTime,jdbcType=BIGINT}, actual_start_time = #{actualStartTime,jdbcType=BIGINT},
actual_end_time = #{actualEndTime,jdbcType=BIGINT},
creator = #{creator,jdbcType=VARCHAR}, creator = #{creator,jdbcType=VARCHAR},
project_id = #{projectId,jdbcType=VARCHAR}, project_id = #{projectId,jdbcType=VARCHAR},
execution_times = #{executionTimes,jdbcType=INTEGER} execution_times = #{executionTimes,jdbcType=INTEGER},
automatic_status_update = #{automaticStatusUpdate,jdbcType=BIT}
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</update> </update>
</mapper> </mapper>

View File

@ -219,4 +219,16 @@ public class TestPlanApiCaseService {
} }
return null; return null;
} }
public Boolean hasFailCase(String planId, List<String> apiCaseIds) {
if (CollectionUtils.isEmpty(apiCaseIds)) {
return false;
}
TestPlanApiCaseExample example = new TestPlanApiCaseExample();
example.createCriteria()
.andTestPlanIdEqualTo(planId)
.andApiCaseIdIn(apiCaseIds)
.andStatusEqualTo("error");
return testPlanApiCaseMapper.countByExample(example) > 0 ? true : false;
}
} }

View File

@ -326,4 +326,16 @@ public class TestPlanLoadCaseService {
} }
return null; return null;
} }
public Boolean hasFailCase(String planId, List<String> performanceIds) {
if (CollectionUtils.isEmpty(performanceIds)) {
return false;
}
TestPlanLoadCaseExample example = new TestPlanLoadCaseExample();
example.createCriteria()
.andTestPlanIdEqualTo(planId)
.andLoadCaseIdIn(performanceIds)
.andStatusEqualTo("error");
return testPlanLoadCaseMapper.countByExample(example) > 0 ? true : false;
}
} }

View File

@ -236,4 +236,20 @@ public class TestPlanScenarioCaseService {
} }
return null; return null;
} }
public TestPlanApiScenario get(String id) {
return testPlanApiScenarioMapper.selectByPrimaryKey(id);
}
public Boolean hasFailCase(String planId, List<String> automationIds) {
if (CollectionUtils.isEmpty(automationIds)) {
return false;
}
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
example.createCriteria()
.andTestPlanIdEqualTo(planId)
.andApiScenarioIdIn(automationIds)
.andLastResultEqualTo("Fail");
return testPlanApiScenarioMapper.countByExample(example) > 0 ? true : false;
}
} }

View File

@ -8,6 +8,7 @@ import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
import io.metersphere.commons.constants.TestPlanTestCaseStatus; import io.metersphere.commons.constants.TestPlanTestCaseStatus;
import io.metersphere.commons.user.SessionUser; import io.metersphere.commons.user.SessionUser;
import io.metersphere.commons.utils.BeanUtils; import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.ServiceUtils; import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils; import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.controller.request.member.QueryMemberRequest; import io.metersphere.controller.request.member.QueryMemberRequest;
@ -17,19 +18,19 @@ import io.metersphere.service.UserService;
import io.metersphere.track.dto.TestCaseTestDTO; import io.metersphere.track.dto.TestCaseTestDTO;
import io.metersphere.track.dto.TestPlanCaseDTO; import io.metersphere.track.dto.TestPlanCaseDTO;
import io.metersphere.track.request.testcase.TestPlanCaseBatchRequest; import io.metersphere.track.request.testcase.TestPlanCaseBatchRequest;
import io.metersphere.track.request.testcase.TrackCount;
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest; import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
import io.metersphere.track.request.testplancase.TestPlanFuncCaseBatchRequest; import io.metersphere.track.request.testplancase.TestPlanFuncCaseBatchRequest;
import io.metersphere.track.request.testplancase.TestPlanFuncCaseConditions; import io.metersphere.track.request.testplancase.TestPlanFuncCaseConditions;
import io.metersphere.track.request.testreview.SaveCommentRequest;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList; import java.util.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@ -38,13 +39,16 @@ public class TestPlanTestCaseService {
@Resource @Resource
TestPlanTestCaseMapper testPlanTestCaseMapper; TestPlanTestCaseMapper testPlanTestCaseMapper;
@Resource @Resource
UserService userService; UserService userService;
@Resource @Resource
TestPlanService testPlanService; TestPlanService testPlanService;
@Resource
TestPlanApiCaseService testPlanApiCaseService;
@Resource
TestPlanLoadCaseService testPlanLoadCaseService;
@Resource
TestPlanScenarioCaseService testPlanScenarioCaseService;
@Resource @Resource
ExtTestPlanTestCaseMapper extTestPlanTestCaseMapper; ExtTestPlanTestCaseMapper extTestPlanTestCaseMapper;
@Resource @Resource
@ -57,6 +61,10 @@ public class TestPlanTestCaseService {
private TestCaseMapper testCaseMapper; private TestCaseMapper testCaseMapper;
@Resource @Resource
private TestPlanMapper testPlanMapper; private TestPlanMapper testPlanMapper;
@Resource
private TestCaseTestMapper testCaseTestMapper;
@Resource
private TestCaseCommentService testCaseCommentService;
public List<TestPlanCaseDTO> list(QueryTestPlanCaseRequest request) { public List<TestPlanCaseDTO> list(QueryTestPlanCaseRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders())); request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
@ -206,6 +214,81 @@ public class TestPlanTestCaseService {
return extTestPlanTestCaseMapper.updateTestCaseStates(ids, reportStatus); return extTestPlanTestCaseMapper.updateTestCaseStates(ids, reportStatus);
} }
/**
* 更新测试计划关联接口测试的功能用例的状态
* @param testId 接口测试id
*/
public void updateTestCaseStates(String testId, String testName, String planId, String testType) {
TestPlan testPlan = testPlanService.getTestPlan(planId);
if (BooleanUtils.isNotTrue(testPlan.getAutomaticStatusUpdate())) {
return;
}
TestCaseTestExample example = new TestCaseTestExample();
example.createCriteria().andTestIdEqualTo(testId);
// 获取跟改接口测试有关联是功能用例id
List<TestCaseTest> testCaseTests = testCaseTestMapper.selectByExample(example);
testCaseTests.forEach(testCaseTest -> {
TestPlanTestCaseExample testPlanTestCaseExample = new TestPlanTestCaseExample();
testPlanTestCaseExample.createCriteria()
.andCaseIdEqualTo(testCaseTest.getTestCaseId())
.andPlanIdEqualTo(planId);
// 获取该功能用例与测试计划关联的用例
List<TestPlanTestCase> testPlanTestCases = testPlanTestCaseMapper.selectByExample(testPlanTestCaseExample);
try {
testPlanTestCases.forEach(testPlanTestCase -> {
// 获取跟该功能用例关联的所有自动化用例
List<TestCaseTestDTO> relateTests = extTestPlanTestCaseMapper.listTestCaseTest(testPlanTestCase.getCaseId());
List<String> apiCaseIds = new ArrayList<>();
List<String> performanceIds = new ArrayList<>();
List<String> automationIds = new ArrayList<>();
relateTests.forEach(item -> {
String type = item.getTestType();
String id = item.getTestId();
if (StringUtils.equals(TrackCount.TESTCASE, type)) {
apiCaseIds.add(id);
} else if (StringUtils.equals(TrackCount.AUTOMATION, type)) {
automationIds.add(id);
} else if (StringUtils.equals(TrackCount.PERFORMANCE, type)) {
performanceIds.add(id);
}
});
Boolean hasApiFailCase = testPlanApiCaseService.hasFailCase(testPlanTestCase.getPlanId(), apiCaseIds);
Boolean hasScenarioFailCase = testPlanScenarioCaseService.hasFailCase(testPlanTestCase.getPlanId(), automationIds);
Boolean hasLoadFailCase = testPlanLoadCaseService.hasFailCase(testPlanTestCase.getPlanId(), performanceIds);
String status = TestPlanTestCaseStatus.Pass.name();
if (hasApiFailCase || hasScenarioFailCase || hasLoadFailCase) {
status = TestPlanTestCaseStatus.Failure.name();
}
String tip = "执行成功";
if (StringUtils.equals(TrackCount.TESTCASE, testType) && hasApiFailCase) {
tip = "执行失败";
} else if (StringUtils.equals(TrackCount.AUTOMATION, testType) && hasScenarioFailCase) {
tip = "执行失败";
} else if (StringUtils.equals(TrackCount.PERFORMANCE, testType) && hasLoadFailCase) {
tip = "执行失败";
}
TestPlanTestCaseWithBLOBs item = new TestPlanTestCaseWithBLOBs();
item.setId(testPlanTestCase.getId());
item.setStatus(status);
testPlanTestCaseMapper.updateByPrimaryKeySelective(item);
SaveCommentRequest saveCommentRequest = new SaveCommentRequest();
saveCommentRequest.setCaseId(testPlanTestCase.getCaseId());
saveCommentRequest.setId(UUID.randomUUID().toString());
saveCommentRequest.setDescription("关联的测试:[" + testName + "]" + tip);
testCaseCommentService.saveComment(saveCommentRequest);
});
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
}
});
}
public List<TestPlanCaseDTO> listForMinder(QueryTestPlanCaseRequest request) { public List<TestPlanCaseDTO> listForMinder(QueryTestPlanCaseRequest request) {
return extTestPlanTestCaseMapper.listForMinder(request); return extTestPlanTestCaseMapper.listForMinder(request);
} }

View File

@ -0,0 +1,2 @@
-- 是否自定更新功能用例状态
ALTER TABLE test_plan ADD automatic_status_update TINYINT(1) DEFAULT 0 NULL COMMENT '是否自定更新功能用例状态';

View File

@ -75,6 +75,18 @@
</el-row> </el-row>
<!--end:xuxm增加自定义计划开始计划结束时间字段--> <!--end:xuxm增加自定义计划开始计划结束时间字段-->
<el-row>
<el-col :span="8" :offset="1">
<el-form-item
:label="$t('自动更新状态')"
:label-width="formLabelWidth"
prop="automaticStatusUpdate">
<el-switch v-model="form.automaticStatusUpdate"/>
<ms-instructions-icon :content="'当功能用例关联的接口或性能用例在测试计划执行后,自动更新功能用例的状态'"/>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" justify="left" style="margin-top: 10px;"> <el-row type="flex" justify="left" style="margin-top: 10px;">
<el-col :span="23" :offset="1"> <el-col :span="23" :offset="1">
<el-form-item :label="$t('commons.description')" :label-width="formLabelWidth" prop="description"> <el-form-item :label="$t('commons.description')" :label-width="formLabelWidth" prop="description">
@ -123,14 +135,14 @@
<script> <script>
import {WORKSPACE_ID} from '@/common/js/constants';
import TestPlanStatusButton from "../common/TestPlanStatusButton"; import TestPlanStatusButton from "../common/TestPlanStatusButton";
import {getCurrentProjectID, getCurrentWorkspaceId, listenGoBack, removeGoBackListener} from "@/common/js/utils"; import {getCurrentProjectID, getCurrentWorkspaceId, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag"; import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag";
import MsInstructionsIcon from "@/business/components/common/components/MsInstructionsIcon";
export default { export default {
name: "TestPlanEdit", name: "TestPlanEdit",
components: {TestPlanStatusButton, MsInputTag}, components: {MsInstructionsIcon, TestPlanStatusButton, MsInputTag},
data() { data() {
return { return {
isStepTableAlive: true, isStepTableAlive: true,
@ -142,7 +154,8 @@ export default {
stage: '', stage: '',
description: '', description: '',
plannedStartTime: '', plannedStartTime: '',
plannedEndTime: '' plannedEndTime: '',
automaticStatusUpdate: false
}, },
rules: { rules: {
name: [ name: [
@ -283,5 +296,7 @@ export default {
</script> </script>
<style scoped> <style scoped>
.instructions-icon {
margin-left: 10px;
}
</style> </style>