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.service.NoticeSendService;
import io.metersphere.service.SystemParameterService;
import io.metersphere.track.request.testcase.TrackCount;
import io.metersphere.track.service.TestPlanApiCaseService;
import io.metersphere.track.service.TestPlanReportService;
import io.metersphere.track.service.TestPlanScenarioCaseService;
import io.metersphere.track.service.TestPlanTestCaseService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@ -208,6 +210,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
ApiTestReport report = null;
ApiTestReportVariable reportTask = null;
String reportUrl = null;
String planScenarioId = null;
// 这部分后续优化只留 DEFINITION SCENARIO 两部分
if (StringUtils.equals(this.runMode, ApiRunMode.DEBUG.name())) {
report = apiReportService.get(debugReportId);
@ -335,6 +338,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
reportUrl = baseSystemConfigDTO.getUrl() + "/#/api/automation/report";
testResult.setTestId(scenarioReport.getScenarioId());
planScenarioId = scenarioReport.getTestPlanScenarioId();
} else {
apiTestService.changeStatus(testId, APITestStatus.Completed);
report = apiReportService.getRunningReport(testResult.getTestId());
@ -343,6 +347,8 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
queue.clear();
super.teardownTest(context);
updateTestCaseStates(testResult, planScenarioId);
List<String> ids = testPlanTestCaseService.getTestPlanTestCaseIds(testResult.getTestId());
if (ids.size() > 0) {
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) {
if (report == null) {
return;

View File

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

View File

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

View File

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

View File

@ -924,66 +924,6 @@ public class TestPlanExample {
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() {
addCriterion("planned_start_time is null");
return (Criteria) this;
@ -1164,6 +1104,66 @@ public class TestPlanExample {
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() {
addCriterion("creator is null");
return (Criteria) this;
@ -1363,6 +1363,66 @@ public class TestPlanExample {
addCriterion("execution_times not between", value1, value2, "executionTimes");
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 {

View File

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

View File

@ -219,4 +219,16 @@ public class TestPlanApiCaseService {
}
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;
}
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;
}
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.user.SessionUser;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils;
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.TestPlanCaseDTO;
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.TestPlanFuncCaseBatchRequest;
import io.metersphere.track.request.testplancase.TestPlanFuncCaseConditions;
import io.metersphere.track.request.testreview.SaveCommentRequest;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
@Service
@ -38,13 +39,16 @@ public class TestPlanTestCaseService {
@Resource
TestPlanTestCaseMapper testPlanTestCaseMapper;
@Resource
UserService userService;
@Resource
TestPlanService testPlanService;
@Resource
TestPlanApiCaseService testPlanApiCaseService;
@Resource
TestPlanLoadCaseService testPlanLoadCaseService;
@Resource
TestPlanScenarioCaseService testPlanScenarioCaseService;
@Resource
ExtTestPlanTestCaseMapper extTestPlanTestCaseMapper;
@Resource
@ -57,6 +61,10 @@ public class TestPlanTestCaseService {
private TestCaseMapper testCaseMapper;
@Resource
private TestPlanMapper testPlanMapper;
@Resource
private TestCaseTestMapper testCaseTestMapper;
@Resource
private TestCaseCommentService testCaseCommentService;
public List<TestPlanCaseDTO> list(QueryTestPlanCaseRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
@ -206,6 +214,81 @@ public class TestPlanTestCaseService {
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) {
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>
<!--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-col :span="23" :offset="1">
<el-form-item :label="$t('commons.description')" :label-width="formLabelWidth" prop="description">
@ -123,14 +135,14 @@
<script>
import {WORKSPACE_ID} from '@/common/js/constants';
import TestPlanStatusButton from "../common/TestPlanStatusButton";
import {getCurrentProjectID, getCurrentWorkspaceId, listenGoBack, removeGoBackListener} from "@/common/js/utils";
import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag";
import MsInstructionsIcon from "@/business/components/common/components/MsInstructionsIcon";
export default {
name: "TestPlanEdit",
components: {TestPlanStatusButton, MsInputTag},
components: {MsInstructionsIcon, TestPlanStatusButton, MsInputTag},
data() {
return {
isStepTableAlive: true,
@ -142,7 +154,8 @@ export default {
stage: '',
description: '',
plannedStartTime: '',
plannedEndTime: ''
plannedEndTime: '',
automaticStatusUpdate: false
},
rules: {
name: [
@ -283,5 +296,7 @@ export default {
</script>
<style scoped>
.instructions-icon {
margin-left: 10px;
}
</style>