Merge pull request #7423 from metersphere/pr@v1.14@feat_测试计划支持允许重复关联用例

feat: 测试计划支持允许重复关联用例
This commit is contained in:
jianxing 2021-11-02 16:10:59 +08:00 committed by GitHub
commit f8078a4a06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 435 additions and 183 deletions

View File

@ -70,8 +70,7 @@ public class ApiDefinitionController {
@PostMapping("/list/relevance/{goPage}/{pageSize}") @PostMapping("/list/relevance/{goPage}/{pageSize}")
public Pager<List<ApiDefinitionResult>> listRelevance(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiDefinitionRequest request) { public Pager<List<ApiDefinitionResult>> listRelevance(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiDefinitionRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true); return apiDefinitionService.listRelevance(request, goPage, pageSize);
return PageUtils.setPageInfo(page, apiDefinitionService.listRelevance(request));
} }
@PostMapping("/list/relevance/review/{goPage}/{pageSize}") @PostMapping("/list/relevance/review/{goPage}/{pageSize}")

View File

@ -21,4 +21,7 @@ public class ApiDefinitionRequest extends BaseQueryRequest {
private String status; private String status;
private String apiCaseCoverage; private String apiCaseCoverage;
private String reviewId; private String reviewId;
// 测试计划是否允许重复
private boolean repeatCase;
} }

View File

@ -52,12 +52,14 @@ import io.metersphere.service.ScheduleService;
import io.metersphere.service.SystemParameterService; import io.metersphere.service.SystemParameterService;
import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest; import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.service.TestPlanService;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.HashTree;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@ -125,6 +127,9 @@ public class ApiDefinitionService {
private RelationshipEdgeService relationshipEdgeService; private RelationshipEdgeService relationshipEdgeService;
@Resource @Resource
private ApiDefinitionFollowMapper apiDefinitionFollowMapper; private ApiDefinitionFollowMapper apiDefinitionFollowMapper;
@Resource
@Lazy
private TestPlanService testPlanService;
private static Cache cache = Cache.newHardMemoryCache(0, 3600); private static Cache cache = Cache.newHardMemoryCache(0, 3600);
@ -1247,13 +1252,18 @@ public class ApiDefinitionService {
// extApiDefinitionMapper.removeToGcByExample(example); // extApiDefinitionMapper.removeToGcByExample(example);
} }
public List<ApiDefinitionResult> listRelevance(ApiDefinitionRequest request) { public Pager<List<ApiDefinitionResult>> listRelevance(ApiDefinitionRequest request, int goPage, int pageSize) {
request.setOrders(ServiceUtils.getDefaultSortOrder(request.getOrders())); request.setOrders(ServiceUtils.getDefaultSortOrder(request.getOrders()));
if (testPlanService.isAllowedRepeatCase(request.getPlanId())) {
request.setRepeatCase(true);
}
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
List<ApiDefinitionResult> resList = extApiDefinitionMapper.listRelevance(request); List<ApiDefinitionResult> resList = extApiDefinitionMapper.listRelevance(request);
calculateResult(resList, request.getProjectId()); calculateResult(resList, request.getProjectId());
return resList; return PageUtils.setPageInfo(page, resList);
} }
public List<ApiDefinitionResult> listRelevanceReview(ApiDefinitionRequest request) { public List<ApiDefinitionResult> listRelevanceReview(ApiDefinitionRequest request) {
request.setOrders(ServiceUtils.getDefaultSortOrder(request.getOrders())); request.setOrders(ServiceUtils.getDefaultSortOrder(request.getOrders()));
List<ApiDefinitionResult> resList = extApiDefinitionMapper.listRelevanceReview(request); List<ApiDefinitionResult> resList = extApiDefinitionMapper.listRelevanceReview(request);

View File

@ -37,6 +37,7 @@ import io.metersphere.service.FileService;
import io.metersphere.service.QuotaService; import io.metersphere.service.QuotaService;
import io.metersphere.service.UserService; import io.metersphere.service.UserService;
import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
import io.metersphere.track.service.TestPlanService;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
@ -96,6 +97,9 @@ public class ApiTestCaseService {
@Lazy @Lazy
private APITestService apiTestService; private APITestService apiTestService;
@Resource @Resource
@Lazy
private TestPlanService testPlanService;
@Resource
private ExtTestPlanApiCaseMapper extTestPlanApiCaseMapper; private ExtTestPlanApiCaseMapper extTestPlanApiCaseMapper;
@Resource @Resource
private ApiTestEnvironmentMapper apiTestEnvironmentMapper; private ApiTestEnvironmentMapper apiTestEnvironmentMapper;
@ -544,6 +548,7 @@ public class ApiTestCaseService {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ExtTestPlanApiCaseMapper batchMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class); ExtTestPlanApiCaseMapper batchMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class);
TestPlanApiCaseMapper batchBaseMapper = sqlSession.getMapper(TestPlanApiCaseMapper.class);
Long nextOrder = ServiceUtils.getNextOrder(request.getPlanId(), extTestPlanApiCaseMapper::getLastOrder); Long nextOrder = ServiceUtils.getNextOrder(request.getPlanId(), extTestPlanApiCaseMapper::getLastOrder);
for (ApiTestCase apiTestCase : apiTestCases) { for (ApiTestCase apiTestCase : apiTestCases) {
@ -557,8 +562,12 @@ public class ApiTestCaseService {
testPlanApiCase.setUpdateTime(System.currentTimeMillis()); testPlanApiCase.setUpdateTime(System.currentTimeMillis());
testPlanApiCase.setOrder(nextOrder); testPlanApiCase.setOrder(nextOrder);
nextOrder += 5000; nextOrder += 5000;
if (testPlanService.isAllowedRepeatCase(request.getPlanId())) {
batchBaseMapper.insert(testPlanApiCase);
} else {
batchMapper.insertIfNotExists(testPlanApiCase); batchMapper.insertIfNotExists(testPlanApiCase);
} }
}
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getPlanId()); TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getPlanId());
if (StringUtils.equals(testPlan.getStatus(), TestPlanStatus.Prepare.name()) if (StringUtils.equals(testPlan.getStatus(), TestPlanStatus.Prepare.name())

View File

@ -27,14 +27,14 @@ 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;
@ -43,5 +43,9 @@ public class TestPlan implements Serializable {
private Boolean automaticStatusUpdate; private Boolean automaticStatusUpdate;
private String followPeople;
private Boolean repeatCase;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@ -854,66 +854,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;
@ -1094,6 +1034,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;
@ -1353,6 +1353,136 @@ public class TestPlanExample {
addCriterion("automatic_status_update not between", value1, value2, "automaticStatusUpdate"); addCriterion("automatic_status_update not between", value1, value2, "automaticStatusUpdate");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andFollowPeopleIsNull() {
addCriterion("follow_people is null");
return (Criteria) this;
}
public Criteria andFollowPeopleIsNotNull() {
addCriterion("follow_people is not null");
return (Criteria) this;
}
public Criteria andFollowPeopleEqualTo(String value) {
addCriterion("follow_people =", value, "followPeople");
return (Criteria) this;
}
public Criteria andFollowPeopleNotEqualTo(String value) {
addCriterion("follow_people <>", value, "followPeople");
return (Criteria) this;
}
public Criteria andFollowPeopleGreaterThan(String value) {
addCriterion("follow_people >", value, "followPeople");
return (Criteria) this;
}
public Criteria andFollowPeopleGreaterThanOrEqualTo(String value) {
addCriterion("follow_people >=", value, "followPeople");
return (Criteria) this;
}
public Criteria andFollowPeopleLessThan(String value) {
addCriterion("follow_people <", value, "followPeople");
return (Criteria) this;
}
public Criteria andFollowPeopleLessThanOrEqualTo(String value) {
addCriterion("follow_people <=", value, "followPeople");
return (Criteria) this;
}
public Criteria andFollowPeopleLike(String value) {
addCriterion("follow_people like", value, "followPeople");
return (Criteria) this;
}
public Criteria andFollowPeopleNotLike(String value) {
addCriterion("follow_people not like", value, "followPeople");
return (Criteria) this;
}
public Criteria andFollowPeopleIn(List<String> values) {
addCriterion("follow_people in", values, "followPeople");
return (Criteria) this;
}
public Criteria andFollowPeopleNotIn(List<String> values) {
addCriterion("follow_people not in", values, "followPeople");
return (Criteria) this;
}
public Criteria andFollowPeopleBetween(String value1, String value2) {
addCriterion("follow_people between", value1, value2, "followPeople");
return (Criteria) this;
}
public Criteria andFollowPeopleNotBetween(String value1, String value2) {
addCriterion("follow_people not between", value1, value2, "followPeople");
return (Criteria) this;
}
public Criteria andRepeatCaseIsNull() {
addCriterion("repeat_case is null");
return (Criteria) this;
}
public Criteria andRepeatCaseIsNotNull() {
addCriterion("repeat_case is not null");
return (Criteria) this;
}
public Criteria andRepeatCaseEqualTo(Boolean value) {
addCriterion("repeat_case =", value, "repeatCase");
return (Criteria) this;
}
public Criteria andRepeatCaseNotEqualTo(Boolean value) {
addCriterion("repeat_case <>", value, "repeatCase");
return (Criteria) this;
}
public Criteria andRepeatCaseGreaterThan(Boolean value) {
addCriterion("repeat_case >", value, "repeatCase");
return (Criteria) this;
}
public Criteria andRepeatCaseGreaterThanOrEqualTo(Boolean value) {
addCriterion("repeat_case >=", value, "repeatCase");
return (Criteria) this;
}
public Criteria andRepeatCaseLessThan(Boolean value) {
addCriterion("repeat_case <", value, "repeatCase");
return (Criteria) this;
}
public Criteria andRepeatCaseLessThanOrEqualTo(Boolean value) {
addCriterion("repeat_case <=", value, "repeatCase");
return (Criteria) this;
}
public Criteria andRepeatCaseIn(List<Boolean> values) {
addCriterion("repeat_case in", values, "repeatCase");
return (Criteria) this;
}
public Criteria andRepeatCaseNotIn(List<Boolean> values) {
addCriterion("repeat_case not in", values, "repeatCase");
return (Criteria) this;
}
public Criteria andRepeatCaseBetween(Boolean value1, Boolean value2) {
addCriterion("repeat_case between", value1, value2, "repeatCase");
return (Criteria) this;
}
public Criteria andRepeatCaseNotBetween(Boolean value1, Boolean value2) {
addCriterion("repeat_case not between", value1, value2, "repeatCase");
return (Criteria) this;
}
} }
public static class Criteria extends GeneratedCriteria { public static class Criteria extends GeneratedCriteria {

View File

@ -13,14 +13,16 @@
<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" /> <result column="automatic_status_update" jdbcType="BIT" property="automaticStatusUpdate" />
<result column="follow_people" jdbcType="VARCHAR" property="followPeople" />
<result column="repeat_case" jdbcType="BIT" property="repeatCase" />
</resultMap> </resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestPlanWithBLOBs"> <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestPlanWithBLOBs">
<result column="tags" jdbcType="LONGVARCHAR" property="tags" /> <result column="tags" jdbcType="LONGVARCHAR" property="tags" />
@ -86,10 +88,10 @@
</where> </where>
</sql> </sql>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id id, workspace_id, report_id, `name`, description, `status`, stage, test_case_match_rule,
, workspace_id, report_id, `name`, description, `status`, stage, test_case_match_rule, executor_match_rule, create_time, update_time, planned_start_time, planned_end_time,
executor_match_rule, create_time, update_time, actual_end_time, planned_start_time, actual_start_time, actual_end_time, creator, project_id, execution_times, automatic_status_update,
planned_end_time, actual_start_time, creator, project_id, execution_times, automatic_status_update follow_people, repeat_case
</sql> </sql>
<sql id="Blob_Column_List"> <sql id="Blob_Column_List">
tags, report_summary, report_config tags, report_summary, report_config
@ -146,19 +148,21 @@
insert into test_plan (id, workspace_id, report_id, insert into test_plan (id, workspace_id, report_id,
`name`, description, `status`, `name`, description, `status`,
stage, test_case_match_rule, executor_match_rule, stage, test_case_match_rule, executor_match_rule,
create_time, update_time, actual_end_time, create_time, update_time, planned_start_time,
planned_start_time, planned_end_time, actual_start_time, planned_end_time, actual_start_time, actual_end_time,
creator, project_id, execution_times, creator, project_id, execution_times,
automatic_status_update, tags, report_summary, automatic_status_update, follow_people, repeat_case,
report_config) tags, report_summary, report_config
)
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}, #{testCaseMatchRule,jdbcType=VARCHAR}, #{executorMatchRule,jdbcType=VARCHAR}, #{stage,jdbcType=VARCHAR}, #{testCaseMatchRule,jdbcType=VARCHAR}, #{executorMatchRule,jdbcType=VARCHAR},
#{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{actualEndTime,jdbcType=BIGINT}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{plannedStartTime,jdbcType=BIGINT},
#{plannedStartTime,jdbcType=BIGINT}, #{plannedEndTime,jdbcType=BIGINT}, #{actualStartTime,jdbcType=BIGINT}, #{plannedEndTime,jdbcType=BIGINT}, #{actualStartTime,jdbcType=BIGINT}, #{actualEndTime,jdbcType=BIGINT},
#{creator,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{executionTimes,jdbcType=INTEGER}, #{creator,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{executionTimes,jdbcType=INTEGER},
#{automaticStatusUpdate,jdbcType=BIT}, #{tags,jdbcType=LONGVARCHAR}, #{reportSummary,jdbcType=LONGVARCHAR}, #{automaticStatusUpdate,jdbcType=BIT}, #{followPeople,jdbcType=VARCHAR}, #{repeatCase,jdbcType=BIT},
#{reportConfig,jdbcType=LONGVARCHAR}) #{tags,jdbcType=LONGVARCHAR}, #{reportSummary,jdbcType=LONGVARCHAR}, #{reportConfig,jdbcType=LONGVARCHAR}
)
</insert> </insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlanWithBLOBs"> <insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlanWithBLOBs">
insert into test_plan insert into test_plan
@ -196,9 +200,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>
@ -208,6 +209,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>
@ -220,6 +224,12 @@
<if test="automaticStatusUpdate != null"> <if test="automaticStatusUpdate != null">
automatic_status_update, automatic_status_update,
</if> </if>
<if test="followPeople != null">
follow_people,
</if>
<if test="repeatCase != null">
repeat_case,
</if>
<if test="tags != null"> <if test="tags != null">
tags, tags,
</if> </if>
@ -264,9 +274,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>
@ -276,6 +283,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>
@ -288,6 +298,12 @@
<if test="automaticStatusUpdate != null"> <if test="automaticStatusUpdate != null">
#{automaticStatusUpdate,jdbcType=BIT}, #{automaticStatusUpdate,jdbcType=BIT},
</if> </if>
<if test="followPeople != null">
#{followPeople,jdbcType=VARCHAR},
</if>
<if test="repeatCase != null">
#{repeatCase,jdbcType=BIT},
</if>
<if test="tags != null"> <if test="tags != null">
#{tags,jdbcType=LONGVARCHAR}, #{tags,jdbcType=LONGVARCHAR},
</if> </if>
@ -341,9 +357,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>
@ -353,6 +366,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>
@ -365,6 +381,12 @@
<if test="record.automaticStatusUpdate != null"> <if test="record.automaticStatusUpdate != null">
automatic_status_update = #{record.automaticStatusUpdate,jdbcType=BIT}, automatic_status_update = #{record.automaticStatusUpdate,jdbcType=BIT},
</if> </if>
<if test="record.followPeople != null">
follow_people = #{record.followPeople,jdbcType=VARCHAR},
</if>
<if test="record.repeatCase != null">
repeat_case = #{record.repeatCase,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>
@ -392,14 +414,16 @@
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}, automatic_status_update = #{record.automaticStatusUpdate,jdbcType=BIT},
follow_people = #{record.followPeople,jdbcType=VARCHAR},
repeat_case = #{record.repeatCase,jdbcType=BIT},
tags = #{record.tags,jdbcType=LONGVARCHAR}, tags = #{record.tags,jdbcType=LONGVARCHAR},
report_summary = #{record.reportSummary,jdbcType=LONGVARCHAR}, report_summary = #{record.reportSummary,jdbcType=LONGVARCHAR},
report_config = #{record.reportConfig,jdbcType=LONGVARCHAR} report_config = #{record.reportConfig,jdbcType=LONGVARCHAR}
@ -420,14 +444,16 @@
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} automatic_status_update = #{record.automaticStatusUpdate,jdbcType=BIT},
follow_people = #{record.followPeople,jdbcType=VARCHAR},
repeat_case = #{record.repeatCase,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>
@ -465,9 +491,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>
@ -477,6 +500,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>
@ -489,6 +515,12 @@
<if test="automaticStatusUpdate != null"> <if test="automaticStatusUpdate != null">
automatic_status_update = #{automaticStatusUpdate,jdbcType=BIT}, automatic_status_update = #{automaticStatusUpdate,jdbcType=BIT},
</if> </if>
<if test="followPeople != null">
follow_people = #{followPeople,jdbcType=VARCHAR},
</if>
<if test="repeatCase != null">
repeat_case = #{repeatCase,jdbcType=BIT},
</if>
<if test="tags != null"> <if test="tags != null">
tags = #{tags,jdbcType=LONGVARCHAR}, tags = #{tags,jdbcType=LONGVARCHAR},
</if> </if>
@ -513,14 +545,16 @@
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}, automatic_status_update = #{automaticStatusUpdate,jdbcType=BIT},
follow_people = #{followPeople,jdbcType=VARCHAR},
repeat_case = #{repeatCase,jdbcType=BIT},
tags = #{tags,jdbcType=LONGVARCHAR}, tags = #{tags,jdbcType=LONGVARCHAR},
report_summary = #{reportSummary,jdbcType=LONGVARCHAR}, report_summary = #{reportSummary,jdbcType=LONGVARCHAR},
report_config = #{reportConfig,jdbcType=LONGVARCHAR} report_config = #{reportConfig,jdbcType=LONGVARCHAR}
@ -538,14 +572,16 @@
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} automatic_status_update = #{automaticStatusUpdate,jdbcType=BIT},
follow_people = #{followPeople,jdbcType=VARCHAR},
repeat_case = #{repeatCase,jdbcType=BIT}
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</update> </update>
</mapper> </mapper>

View File

@ -427,6 +427,7 @@
</if> </if>
</foreach> </foreach>
</if> </if>
<if test="!request.repeatCase">
and exists ( and exists (
select id select id
from api_test_case c from api_test_case c
@ -438,6 +439,7 @@
and t.test_plan_id = #{request.planId} and t.test_plan_id = #{request.planId}
) )
) )
</if>
</where> </where>
<if test="request.orders != null and request.orders.size() > 0"> <if test="request.orders != null and request.orders.size() > 0">
order by order by

View File

@ -296,7 +296,7 @@
<if test="request.executeStatus == 'executePass'"> <if test="request.executeStatus == 'executePass'">
and api_scenario.last_result = 'Success' and api_scenario.last_result = 'Success'
</if> </if>
<if test="request.notInTestPlan == true "> <if test="request.notInTestPlan">
and api_scenario.id not in ( and api_scenario.id not in (
select pc.api_scenario_id select pc.api_scenario_id
from test_plan_api_scenario pc from test_plan_api_scenario pc

View File

@ -127,9 +127,13 @@
select test_case.id, test_case.name, test_case.priority, test_case.type, test_case.review_status, select test_case.id, test_case.name, test_case.priority, test_case.type, test_case.review_status,
test_case.num, test_case.custom_num, test_case.priority, test_case.tags, test_case.create_time, test_case.update_time test_case.num, test_case.custom_num, test_case.priority, test_case.tags, test_case.create_time, test_case.update_time
from test_case as test_case from test_case as test_case
<if test="!request.repeatCase">
left join test_plan_test_case as T2 on test_case.id=T2.case_id and T2.plan_id =#{request.planId} left join test_plan_test_case as T2 on test_case.id=T2.case_id and T2.plan_id =#{request.planId}
<include refid="notInQueryWhereCondition"></include> </if>
<include refid="notInQueryWhereCondition"/>
<if test="!request.repeatCase">
and T2.case_id is null and T2.case_id is null
</if>
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/> <include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
</select> </select>

View File

@ -17,9 +17,11 @@
select load_test.id select load_test.id
from load_test from load_test
where load_test.project_id = #{request.projectId} where load_test.project_id = #{request.projectId}
<if test="!request.repeatCase">
and load_test.id not in ( and load_test.id not in (
select tplc.load_case_id from test_plan_load_case tplc where tplc.test_plan_id = #{request.testPlanId} select tplc.load_case_id from test_plan_load_case tplc where tplc.test_plan_id = #{request.testPlanId}
) )
</if>
<if test="request.name != null and request.name != ''"> <if test="request.name != null and request.name != ''">
and load_test.name like CONCAT('%', #{request.name},'%') and load_test.name like CONCAT('%', #{request.name},'%')
</if> </if>

View File

@ -121,8 +121,8 @@ public class TestCaseController {
@PostMapping("/relate/{goPage}/{pageSize}") @PostMapping("/relate/{goPage}/{pageSize}")
public Pager<List<TestCase>> getTestCaseRelateList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestCaseRequest request) { public Pager<List<TestCase>> getTestCaseRelateList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestCaseRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true); // Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, testCaseService.getTestCaseRelateList(request)); return testCaseService.getTestCaseRelateList(request, goPage, pageSize);
} }
@PostMapping("/relationship/relate/{goPage}/{pageSize}") @PostMapping("/relationship/relate/{goPage}/{pageSize}")

View File

@ -31,8 +31,7 @@ public class TestPlanLoadCaseController {
@PostMapping("/relevance/list/{goPage}/{pageSize}") @PostMapping("/relevance/list/{goPage}/{pageSize}")
public Pager<List<LoadTest>> relevanceList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody LoadCaseRequest request) { public Pager<List<LoadTest>> relevanceList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody LoadCaseRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true); return testPlanLoadCaseService.relevanceList(request, goPage, pageSize);
return PageUtils.setPageInfo(page, testPlanLoadCaseService.relevanceList(request));
} }
@PostMapping("/relevance") @PostMapping("/relevance")

View File

@ -49,8 +49,7 @@ public class TestPlanScenarioCaseController {
@PostMapping("/relevance/list/{goPage}/{pageSize}") @PostMapping("/relevance/list/{goPage}/{pageSize}")
public Pager<List<ApiScenarioDTO>> relevanceList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiScenarioRequest request) { public Pager<List<ApiScenarioDTO>> relevanceList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody ApiScenarioRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true); return testPlanScenarioCaseService.relevanceList(request, goPage, pageSize);
return PageUtils.setPageInfo(page, testPlanScenarioCaseService.relevanceList(request));
} }
@GetMapping("/delete/{id}") @GetMapping("/delete/{id}")

View File

@ -18,6 +18,9 @@ public class QueryTestCaseRequest extends BaseQueryRequest {
private List<String> testCaseIds; private List<String> testCaseIds;
// 测试计划是否允许重复
private boolean repeatCase;
private String planId; private String planId;
private String issuesId; private String issuesId;

View File

@ -19,4 +19,7 @@ public class LoadCaseRequest extends TestPlanLoadCase {
private Map<String, List<String>> filters; private Map<String, List<String>> filters;
private List<OrderRequest> orders; private List<OrderRequest> orders;
private Map<String, Object> combine; private Map<String, Object> combine;
// 测试计划是否允许重复
private boolean repeatCase;
} }

View File

@ -142,6 +142,9 @@ public class TestCaseService {
private PerformanceTestService performanceTestService; private PerformanceTestService performanceTestService;
@Resource @Resource
private TestCaseFollowMapper testCaseFollowMapper; private TestCaseFollowMapper testCaseFollowMapper;
@Resource
@Lazy
private TestPlanService testPlanService;
private void setNode(TestCaseWithBLOBs testCase) { private void setNode(TestCaseWithBLOBs testCase) {
if (StringUtils.isEmpty(testCase.getNodeId()) || "default-module".equals(testCase.getNodeId())) { if (StringUtils.isEmpty(testCase.getNodeId()) || "default-module".equals(testCase.getNodeId())) {
@ -452,12 +455,16 @@ public class TestCaseService {
* @param request * @param request
* @return * @return
*/ */
public List<TestCase> getTestCaseRelateList(QueryTestCaseRequest request) { public Pager<List<TestCase>> getTestCaseRelateList(QueryTestCaseRequest request, int goPage, int pageSize) {
setDefaultOrder(request); setDefaultOrder(request);
request.getOrders().forEach(order -> { request.getOrders().forEach(order -> {
order.setPrefix("test_case"); order.setPrefix("test_case");
}); });
return getTestCaseByNotInPlan(request); if (testPlanService.isAllowedRepeatCase(request.getPlanId())) {
request.setRepeatCase(true);
}
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, getTestCaseByNotInPlan(request));
} }
public List<TestCase> getTestCaseByNotInPlan(QueryTestCaseRequest request) { public List<TestCase> getTestCaseByNotInPlan(QueryTestCaseRequest request) {

View File

@ -90,7 +90,8 @@ public class TestPlanApiCaseService {
@Resource @Resource
private ResourcePoolCalculation resourcePoolCalculation; private ResourcePoolCalculation resourcePoolCalculation;
@Resource @Resource
private NodeKafkaService nodeKafkaService; @Lazy
private TestPlanService testPlanService;
@Resource @Resource
private TestResourcePoolMapper testResourcePoolMapper; private TestResourcePoolMapper testResourcePoolMapper;
@ -138,12 +139,14 @@ public class TestPlanApiCaseService {
} }
public Pager<List<ApiTestCaseDTO>> relevanceList(int goPage, int pageSize, ApiTestCaseRequest request) { public Pager<List<ApiTestCaseDTO>> relevanceList(int goPage, int pageSize, ApiTestCaseRequest request) {
if (!testPlanService.isAllowedRepeatCase(request.getPlanId())) { // 不允许重复关联
List<String> ids = apiTestCaseService.selectIdsNotExistsInPlan(request.getProjectId(), request.getPlanId()); List<String> ids = apiTestCaseService.selectIdsNotExistsInPlan(request.getProjectId(), request.getPlanId());
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
if (CollectionUtils.isEmpty(ids)) { if (CollectionUtils.isEmpty(ids)) {
return PageUtils.setPageInfo(page, new ArrayList<>()); return PageUtils.setPageInfo(PageHelper.startPage(goPage, pageSize, true), new ArrayList<>());
} }
request.setIds(ids); request.setIds(ids);
}
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId()); request.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
return PageUtils.setPageInfo(page, apiTestCaseService.listSimple(request)); return PageUtils.setPageInfo(page, apiTestCaseService.listSimple(request));
} }

View File

@ -1,6 +1,8 @@
package io.metersphere.track.service; package io.metersphere.track.service;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.LoadTestMapper; import io.metersphere.base.mapper.LoadTestMapper;
import io.metersphere.base.mapper.LoadTestReportMapper; import io.metersphere.base.mapper.LoadTestReportMapper;
@ -10,9 +12,7 @@ import io.metersphere.base.mapper.ext.ExtTestPlanLoadCaseMapper;
import io.metersphere.commons.constants.RunModeConstants; import io.metersphere.commons.constants.RunModeConstants;
import io.metersphere.commons.constants.TestPlanStatus; import io.metersphere.commons.constants.TestPlanStatus;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.ServiceUtils; import io.metersphere.commons.utils.*;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.commons.utils.TestPlanUtils;
import io.metersphere.controller.request.OrderRequest; import io.metersphere.controller.request.OrderRequest;
import io.metersphere.controller.request.ResetOrderRequest; import io.metersphere.controller.request.ResetOrderRequest;
import io.metersphere.log.vo.OperatingLogDetails; import io.metersphere.log.vo.OperatingLogDetails;
@ -30,6 +30,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -57,16 +58,23 @@ public class TestPlanLoadCaseService {
private LoadTestReportMapper loadTestReportMapper; private LoadTestReportMapper loadTestReportMapper;
@Resource @Resource
private LoadTestMapper loadTestMapper; private LoadTestMapper loadTestMapper;
@Resource
@Lazy
private TestPlanService testPlanService;
public List<LoadTest> relevanceList(LoadCaseRequest request) { public Pager<List<LoadTest>> relevanceList(LoadCaseRequest request, int goPage, int pageSize) {
List<OrderRequest> orders = ServiceUtils.getDefaultSortOrder(request.getOrders()); List<OrderRequest> orders = ServiceUtils.getDefaultSortOrder(request.getOrders());
orders.forEach(i -> i.setPrefix("load_test")); orders.forEach(i -> i.setPrefix("load_test"));
request.setOrders(orders); request.setOrders(orders);
if (testPlanService.isAllowedRepeatCase(request.getTestPlanId())) {
request.setRepeatCase(true);
}
List<String> ids = extTestPlanLoadCaseMapper.selectIdsNotInPlan(request); List<String> ids = extTestPlanLoadCaseMapper.selectIdsNotInPlan(request);
if (CollectionUtils.isEmpty(ids)) { if (CollectionUtils.isEmpty(ids)) {
return new ArrayList<>(); return PageUtils.setPageInfo(PageHelper.startPage(goPage, pageSize, true), new ArrayList<>());
} }
return performanceTestService.getLoadTestListByIds(ids); Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, performanceTestService.getLoadTestListByIds(ids));
} }
public List<TestPlanLoadCaseDTO> list(LoadCaseRequest request) { public List<TestPlanLoadCaseDTO> list(LoadCaseRequest request) {

View File

@ -2,6 +2,8 @@ package io.metersphere.track.service;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.api.dto.automation.*; import io.metersphere.api.dto.automation.*;
import io.metersphere.api.service.ApiAutomationService; import io.metersphere.api.service.ApiAutomationService;
import io.metersphere.api.service.ApiScenarioReportService; import io.metersphere.api.service.ApiScenarioReportService;
@ -14,6 +16,8 @@ import io.metersphere.base.mapper.ext.ExtTestPlanScenarioCaseMapper;
import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.constants.TestPlanTestCaseStatus; import io.metersphere.commons.constants.TestPlanTestCaseStatus;
import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager;
import io.metersphere.commons.utils.ServiceUtils; import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.TestPlanUtils; import io.metersphere.commons.utils.TestPlanUtils;
import io.metersphere.controller.request.ResetOrderRequest; import io.metersphere.controller.request.ResetOrderRequest;
@ -26,6 +30,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -55,6 +60,9 @@ public class TestPlanScenarioCaseService {
private ApiTestEnvironmentMapper apiTestEnvironmentMapper; private ApiTestEnvironmentMapper apiTestEnvironmentMapper;
@Resource @Resource
private SqlSessionFactory sqlSessionFactory; private SqlSessionFactory sqlSessionFactory;
@Resource
@Lazy
private TestPlanService testPlanService;
public List<ApiScenarioDTO> list(TestPlanScenarioRequest request) { public List<ApiScenarioDTO> list(TestPlanScenarioRequest request) {
request.setProjectId(null); request.setProjectId(null);
@ -107,10 +115,13 @@ public class TestPlanScenarioCaseService {
return idList; return idList;
} }
public List<ApiScenarioDTO> relevanceList(ApiScenarioRequest request) { public Pager<List<ApiScenarioDTO>> relevanceList(ApiScenarioRequest request, int goPage, int pageSize) {
request.setNotInTestPlan(true); request.setNotInTestPlan(true);
List<ApiScenarioDTO> list = apiAutomationService.list(request); if (testPlanService.isAllowedRepeatCase(request.getPlanId())) {
return list; request.setNotInTestPlan(false);
}
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, apiAutomationService.list(request));
} }
public int delete(String id) { public int delete(String id) {

View File

@ -26,7 +26,6 @@ import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.*; import io.metersphere.base.mapper.ext.*;
import io.metersphere.commons.constants.*; import io.metersphere.commons.constants.*;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.user.SessionUser;
import io.metersphere.commons.utils.*; import io.metersphere.commons.utils.*;
import io.metersphere.dto.BaseSystemConfigDTO; import io.metersphere.dto.BaseSystemConfigDTO;
import io.metersphere.dto.IssueTemplateDao; import io.metersphere.dto.IssueTemplateDao;
@ -36,7 +35,6 @@ import io.metersphere.log.utils.ReflexObjectUtil;
import io.metersphere.log.vo.DetailColumn; import io.metersphere.log.vo.DetailColumn;
import io.metersphere.log.vo.OperatingLogDetails; import io.metersphere.log.vo.OperatingLogDetails;
import io.metersphere.log.vo.track.TestPlanReference; import io.metersphere.log.vo.track.TestPlanReference;
import io.metersphere.notice.sender.NoticeModel;
import io.metersphere.notice.service.NoticeSendService; import io.metersphere.notice.service.NoticeSendService;
import io.metersphere.performance.base.*; import io.metersphere.performance.base.*;
import io.metersphere.performance.dto.LoadTestExportJmx; import io.metersphere.performance.dto.LoadTestExportJmx;
@ -2072,4 +2070,8 @@ public class TestPlanService {
userExample.createCriteria().andIdIn(userIds); userExample.createCriteria().andIdIn(userIds);
return userMapper.selectByExample(userExample); return userMapper.selectByExample(userExample);
} }
public boolean isAllowedRepeatCase(String planId) {
return testPlanMapper.selectByPrimaryKey(planId).getRepeatCase();
}
} }

View File

@ -356,7 +356,7 @@ public class TestReviewTestCaseService {
} }
public void initOrderField() { public void initOrderField() {
ServiceUtils.initOrderField(TestCaseReviewTestCase.class, TestCaseReviewMapper.class, ServiceUtils.initOrderField(TestCaseReviewTestCase.class, TestCaseReviewTestCaseMapper.class,
extTestReviewCaseMapper::selectReviewIds, extTestReviewCaseMapper::selectReviewIds,
extTestReviewCaseMapper::getIdsOrderByUpdateTime); extTestReviewCaseMapper::getIdsOrderByUpdateTime);
} }

View File

@ -1,5 +1,10 @@
ALTER TABLE mock_expect_config ADD COLUMN expect_num varchar(50); ALTER TABLE mock_expect_config ADD COLUMN expect_num varchar(50);
ALTER TABLE test_plan ADD COLUMN repeat_case TINYINT(1) DEFAULT 0 COMMENT '是否允许重复添加用例';
ALTER TABLE test_plan_api_case DROP KEY plan_id_case_id;
ALTER TABLE test_plan_load_case DROP KEY plan_load_case_id;
ALTER TABLE test_plan_api_scenario DROP KEY plan_id_scenario_id;
insert into user_group_permission (id, group_id, permission_id, module_id) insert into user_group_permission (id, group_id, permission_id, module_id)
values (UUID(), 'ws_admin', 'WORKSPACE_PROJECT_MANAGER:READ+UPLOAD_JAR', 'WORKSPACE_PROJECT_MANAGER'); values (UUID(), 'ws_admin', 'WORKSPACE_PROJECT_MANAGER:READ+UPLOAD_JAR', 'WORKSPACE_PROJECT_MANAGER');
insert into user_group_permission (id, group_id, permission_id, module_id) insert into user_group_permission (id, group_id, permission_id, module_id)

View File

@ -88,6 +88,18 @@
<ms-instructions-icon :content="'当功能用例关联的接口或性能用例在测试计划执行后,自动更新功能用例的状态'"/> <ms-instructions-icon :content="'当功能用例关联的接口或性能用例在测试计划执行后,自动更新功能用例的状态'"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12">
<el-form-item
:label="$t('允许关联重复用例')"
label-width="140px"
prop="automaticStatusUpdate">
<el-switch v-model="form.repeatCase"/>
<ms-instructions-icon :content="'是否允许同一个测试计划中多次关联相同用例'"/>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" justify="left" :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="$t('test_track.plan.follow_people')" :label-width="formLabelWidth" <el-form-item :label="$t('test_track.plan.follow_people')" :label-width="formLabelWidth"
prop="follows"> prop="follows">
@ -175,6 +187,7 @@ export default {
plannedStartTime: '', plannedStartTime: '',
plannedEndTime: '', plannedEndTime: '',
automaticStatusUpdate: false, automaticStatusUpdate: false,
repeatCase: false,
follows: [] follows: []
}, },
rules: { rules: {