feat(测试计划): 测试计划批量执行方法开发
This commit is contained in:
parent
f5ae0cd2a2
commit
791432f490
|
@ -27,17 +27,23 @@ public class TestPlanConfig implements Serializable {
|
|||
@NotNull(message = "{test_plan_config.repeat_case.not_blank}", groups = {Created.class})
|
||||
private Boolean repeatCase;
|
||||
|
||||
@Schema(description = "测试计划通过阈值; 0-100, 保留两位小数", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{test_plan_config.pass_threshold.not_blank}", groups = {Created.class})
|
||||
private Double passThreshold;
|
||||
|
||||
@Schema(description = "不同用例之间的执行方式(串行/并行)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{test_plan_config.case_run_mode.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{test_plan_config.case_run_mode.length_range}", groups = {Created.class, Updated.class})
|
||||
private String caseRunMode;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public enum Column {
|
||||
testPlanId("test_plan_id", "testPlanId", "VARCHAR", false),
|
||||
automaticStatusUpdate("automatic_status_update", "automaticStatusUpdate", "BIT", false),
|
||||
repeatCase("repeat_case", "repeatCase", "BIT", false),
|
||||
passThreshold("pass_threshold", "passThreshold", "DECIMAL", false);
|
||||
passThreshold("pass_threshold", "passThreshold", "DECIMAL", false),
|
||||
caseRunMode("case_run_mode", "caseRunMode", "VARCHAR", false);
|
||||
|
||||
private static final String BEGINNING_DELIMITER = "`";
|
||||
|
||||
|
|
|
@ -354,6 +354,76 @@ public class TestPlanConfigExample {
|
|||
addCriterion("pass_threshold not between", value1, value2, "passThreshold");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeIsNull() {
|
||||
addCriterion("case_run_mode is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeIsNotNull() {
|
||||
addCriterion("case_run_mode is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeEqualTo(String value) {
|
||||
addCriterion("case_run_mode =", value, "caseRunMode");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeNotEqualTo(String value) {
|
||||
addCriterion("case_run_mode <>", value, "caseRunMode");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeGreaterThan(String value) {
|
||||
addCriterion("case_run_mode >", value, "caseRunMode");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("case_run_mode >=", value, "caseRunMode");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeLessThan(String value) {
|
||||
addCriterion("case_run_mode <", value, "caseRunMode");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeLessThanOrEqualTo(String value) {
|
||||
addCriterion("case_run_mode <=", value, "caseRunMode");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeLike(String value) {
|
||||
addCriterion("case_run_mode like", value, "caseRunMode");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeNotLike(String value) {
|
||||
addCriterion("case_run_mode not like", value, "caseRunMode");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeIn(List<String> values) {
|
||||
addCriterion("case_run_mode in", values, "caseRunMode");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeNotIn(List<String> values) {
|
||||
addCriterion("case_run_mode not in", values, "caseRunMode");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeBetween(String value1, String value2) {
|
||||
addCriterion("case_run_mode between", value1, value2, "caseRunMode");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCaseRunModeNotBetween(String value1, String value2) {
|
||||
addCriterion("case_run_mode not between", value1, value2, "caseRunMode");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<result column="automatic_status_update" jdbcType="BIT" property="automaticStatusUpdate" />
|
||||
<result column="repeat_case" jdbcType="BIT" property="repeatCase" />
|
||||
<result column="pass_threshold" jdbcType="DECIMAL" property="passThreshold" />
|
||||
<result column="case_run_mode" jdbcType="VARCHAR" property="caseRunMode" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -66,7 +67,7 @@
|
|||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
test_plan_id, automatic_status_update, repeat_case, pass_threshold
|
||||
test_plan_id, automatic_status_update, repeat_case, pass_threshold, case_run_mode
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.plan.domain.TestPlanConfigExample" resultMap="BaseResultMap">
|
||||
select
|
||||
|
@ -100,9 +101,9 @@
|
|||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.plan.domain.TestPlanConfig">
|
||||
insert into test_plan_config (test_plan_id, automatic_status_update, repeat_case,
|
||||
pass_threshold)
|
||||
pass_threshold, case_run_mode)
|
||||
values (#{testPlanId,jdbcType=VARCHAR}, #{automaticStatusUpdate,jdbcType=BIT}, #{repeatCase,jdbcType=BIT},
|
||||
#{passThreshold,jdbcType=DECIMAL})
|
||||
#{passThreshold,jdbcType=DECIMAL}, #{caseRunMode,jdbcType=VARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.plan.domain.TestPlanConfig">
|
||||
insert into test_plan_config
|
||||
|
@ -119,6 +120,9 @@
|
|||
<if test="passThreshold != null">
|
||||
pass_threshold,
|
||||
</if>
|
||||
<if test="caseRunMode != null">
|
||||
case_run_mode,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="testPlanId != null">
|
||||
|
@ -133,6 +137,9 @@
|
|||
<if test="passThreshold != null">
|
||||
#{passThreshold,jdbcType=DECIMAL},
|
||||
</if>
|
||||
<if test="caseRunMode != null">
|
||||
#{caseRunMode,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.plan.domain.TestPlanConfigExample" resultType="java.lang.Long">
|
||||
|
@ -156,6 +163,9 @@
|
|||
<if test="record.passThreshold != null">
|
||||
pass_threshold = #{record.passThreshold,jdbcType=DECIMAL},
|
||||
</if>
|
||||
<if test="record.caseRunMode != null">
|
||||
case_run_mode = #{record.caseRunMode,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
|
@ -166,7 +176,8 @@
|
|||
set test_plan_id = #{record.testPlanId,jdbcType=VARCHAR},
|
||||
automatic_status_update = #{record.automaticStatusUpdate,jdbcType=BIT},
|
||||
repeat_case = #{record.repeatCase,jdbcType=BIT},
|
||||
pass_threshold = #{record.passThreshold,jdbcType=DECIMAL}
|
||||
pass_threshold = #{record.passThreshold,jdbcType=DECIMAL},
|
||||
case_run_mode = #{record.caseRunMode,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -183,6 +194,9 @@
|
|||
<if test="passThreshold != null">
|
||||
pass_threshold = #{passThreshold,jdbcType=DECIMAL},
|
||||
</if>
|
||||
<if test="caseRunMode != null">
|
||||
case_run_mode = #{caseRunMode,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where test_plan_id = #{testPlanId,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
@ -190,16 +204,19 @@
|
|||
update test_plan_config
|
||||
set automatic_status_update = #{automaticStatusUpdate,jdbcType=BIT},
|
||||
repeat_case = #{repeatCase,jdbcType=BIT},
|
||||
pass_threshold = #{passThreshold,jdbcType=DECIMAL}
|
||||
pass_threshold = #{passThreshold,jdbcType=DECIMAL},
|
||||
case_run_mode = #{caseRunMode,jdbcType=VARCHAR}
|
||||
where test_plan_id = #{testPlanId,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into test_plan_config
|
||||
(test_plan_id, automatic_status_update, repeat_case, pass_threshold)
|
||||
(test_plan_id, automatic_status_update, repeat_case, pass_threshold, case_run_mode
|
||||
)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.testPlanId,jdbcType=VARCHAR}, #{item.automaticStatusUpdate,jdbcType=BIT},
|
||||
#{item.repeatCase,jdbcType=BIT}, #{item.passThreshold,jdbcType=DECIMAL})
|
||||
#{item.repeatCase,jdbcType=BIT}, #{item.passThreshold,jdbcType=DECIMAL}, #{item.caseRunMode,jdbcType=VARCHAR}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
<insert id="batchInsertSelective" parameterType="map">
|
||||
|
@ -224,6 +241,9 @@
|
|||
<if test="'pass_threshold'.toString() == column.value">
|
||||
#{item.passThreshold,jdbcType=DECIMAL}
|
||||
</if>
|
||||
<if test="'case_run_mode'.toString() == column.value">
|
||||
#{item.caseRunMode,jdbcType=VARCHAR}
|
||||
</if>
|
||||
</foreach>
|
||||
)
|
||||
</foreach>
|
||||
|
|
|
@ -159,8 +159,12 @@ ALTER TABLE api_scenario_report DROP INDEX idx_test_plan_id;
|
|||
CREATE INDEX idx_test_plan_scenario_id ON api_scenario_report(test_plan_scenario_id);
|
||||
ALTER TABLE api_scenario_report ADD COLUMN `plan` BIT(1) NOT NULL DEFAULT 0 COMMENT '是否是测试计划整体执行';
|
||||
CREATE INDEX idx_plan ON api_scenario_report(`plan`);
|
||||
|
||||
-- 测试计划配置 增加运行模式
|
||||
ALTER table test_plan_config
|
||||
ADD COLUMN `case_run_mode` VARCHAR(50) NOT NULL DEFAULT 'PARALLEL' COMMENT '不同用例之间的执行方式(串行/并行)';
|
||||
|
||||
-- set innodb lock wait timeout to default
|
||||
SET SESSION innodb_lock_wait_timeout = DEFAULT;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -27,5 +27,5 @@ public enum ApiExecuteRunMode {
|
|||
/**
|
||||
* 定时任务
|
||||
*/
|
||||
SCENARIO
|
||||
SCHEDULE
|
||||
}
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
package io.metersphere.sdk.dto.queue;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class TestPlanExecutionQueue {
|
||||
private String queueId;
|
||||
private String parentQueueId;
|
||||
private String testPlanId;
|
||||
//顺序
|
||||
private long pos;
|
||||
//执行模式
|
||||
private String runMode;
|
||||
//执行来源
|
||||
private String executionSource;
|
||||
//预生成的报告ID (不一定会用到)
|
||||
private String prepareReportId;
|
||||
private String createUser;
|
||||
private long createTime;
|
||||
|
|
|
@ -101,6 +101,7 @@ log.test_plan.api_scenario=接口场景
|
|||
test_plan.type.not_blank=测试计划类型不能为空
|
||||
test_plan.group.not_plan=当前测试计划组没有可归档计划
|
||||
test_plan.group.error=不是合法的测试计划组
|
||||
test_plan.error=测试计划不合法
|
||||
test_plan_group.batch.log={0}测试计划组
|
||||
test_plan.batch.log={0}测试计划
|
||||
test_plan_report_not_exist=测试计划报告不存在
|
||||
|
|
|
@ -103,6 +103,7 @@ log.test_plan.api_scenario=Api scenario
|
|||
test_plan.type.not_blank=Test plan type cannot be empty
|
||||
test_plan.group.not_plan=There are no archived plans in the current testing plan group
|
||||
test_plan.group.error=Test plan group error
|
||||
test_plan.error=Test plan error
|
||||
test_plan_group.batch.log={0} test plan group
|
||||
test_plan.batch.log={0} plan
|
||||
test_plan_report_not_exist=The test plan report does not exist
|
||||
|
|
|
@ -103,6 +103,7 @@ log.test_plan.api_scenario=接口场景
|
|||
test_plan.type.not_blank=测试计划类型不能为空
|
||||
test_plan.group.not_plan=当前测试计划组没有可归档计划
|
||||
test_plan.group.error=不是合法的测试计划组
|
||||
test_plan.error=测试计划不合法
|
||||
test_plan_group.batch.log={0}测试计划组
|
||||
test_plan.batch.log={0}测试计划
|
||||
test_plan_report_not_exist=测试计划报告不存在
|
||||
|
|
|
@ -102,6 +102,7 @@ log.test_plan.api_scenario=接口場景
|
|||
test_plan.type.not_blank=測試計劃類型不能為空
|
||||
test_plan.group.not_plan=當前測試計劃組沒有可歸檔計劃
|
||||
test_plan.group.error=不是合法的測試計劃組
|
||||
test_plan.error=測試計劃不合法
|
||||
test_plan_group.batch.log={0}測試計劃組
|
||||
test_plan.batch.log={0}測試計劃
|
||||
test_plan_report_not_exist=測試計劃報告不存在
|
||||
|
|
|
@ -58,7 +58,7 @@ public class ApiScenarioScheduleJob extends BaseScheduleJob {
|
|||
|
||||
ApiResourceRunRequest runRequest = apiScenarioRunService.getApiResourceRunRequest(msScenario, tmpParam);
|
||||
|
||||
TaskRequestDTO taskRequest = apiScenarioRunService.getTaskRequest(IDGenerator.nextStr(), apiScenarioDetail.getId(), apiScenarioDetail.getProjectId(), ApiExecuteRunMode.SCENARIO.name());
|
||||
TaskRequestDTO taskRequest = apiScenarioRunService.getTaskRequest(IDGenerator.nextStr(), apiScenarioDetail.getId(), apiScenarioDetail.getProjectId(), ApiExecuteRunMode.SCHEDULE.name());
|
||||
TaskInfo taskInfo = taskRequest.getTaskInfo();
|
||||
TaskItem taskItem = taskRequest.getTaskItem();
|
||||
taskInfo.getRunModeConfig().setPoolId(apiRunModeConfigDTO.getPoolId());
|
||||
|
|
|
@ -835,7 +835,7 @@ public class ApiDefinitionModuleControllerTests extends BaseTest {
|
|||
planConfig.setRepeatCase(false);
|
||||
planConfig.setAutomaticStatusUpdate(false);
|
||||
request.setTestPlanId("wx_123");
|
||||
testPlanConfigMapper.insert(planConfig);
|
||||
testPlanConfigMapper.insertSelective(planConfig);
|
||||
this.requestPostWithOkAndReturn(URL_FILE_MODULE_COUNT, request);
|
||||
}
|
||||
|
||||
|
|
|
@ -520,7 +520,7 @@ public class FunctionalCaseControllerTests extends BaseTest {
|
|||
Assertions.assertTrue(moduleCount.containsKey("all"));
|
||||
|
||||
//不开启用例重复的测试计划入库,再次调用
|
||||
testPlanConfigMapper.insert(testPlanConfig);
|
||||
testPlanConfigMapper.insertSelective(testPlanConfig);
|
||||
|
||||
mvcResult = this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_MODULE_COUNT, request);
|
||||
returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
|
|
|
@ -113,14 +113,26 @@ public class ScheduleService {
|
|||
}
|
||||
}
|
||||
|
||||
public void closeIfExist(String resourceId, JobKey jobKey, TriggerKey triggerKey, Class clazz) {
|
||||
public void updateIfExist(String resourceId, boolean enable, JobKey jobKey, TriggerKey triggerKey, Class clazz, String operator) {
|
||||
ScheduleExample example = new ScheduleExample();
|
||||
example.createCriteria().andResourceIdEqualTo(resourceId).andJobEqualTo(clazz.getName());
|
||||
Schedule updateSchedule = new Schedule();
|
||||
updateSchedule.setEnable(false);
|
||||
scheduleMapper.updateByExampleSelective(updateSchedule, example);
|
||||
List<Schedule> scheduleList = scheduleMapper.selectByExample(example);
|
||||
if (CollectionUtils.isNotEmpty(scheduleList)) {
|
||||
Schedule schedule = scheduleList.getFirst();
|
||||
if (!schedule.getEnable().equals(enable)) {
|
||||
schedule.setEnable(enable);
|
||||
schedule.setUpdateTime(System.currentTimeMillis());
|
||||
scheduleMapper.updateByExampleSelective(schedule, example);
|
||||
apiScheduleNoticeService.sendScheduleNotice(schedule, operator);
|
||||
if (enable) {
|
||||
scheduleManager.addCronJob(jobKey, triggerKey, clazz, schedule.getValue(),
|
||||
scheduleManager.getDefaultJobDataMap(schedule, schedule.getValue(), schedule.getCreateUser()));
|
||||
} else {
|
||||
scheduleManager.removeJob(jobKey, triggerKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String scheduleConfig(ScheduleConfig scheduleConfig, JobKey jobKey, TriggerKey triggerKey, Class clazz, String operator) {
|
||||
Schedule schedule;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.metersphere.plan.controller;
|
||||
|
||||
import io.metersphere.plan.constants.TestPlanResourceConfig;
|
||||
import io.metersphere.plan.dto.request.TestPlanBatchExecuteRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanExecuteRequest;
|
||||
import io.metersphere.plan.service.TestPlanExecuteService;
|
||||
import io.metersphere.plan.service.TestPlanLogService;
|
||||
|
@ -33,13 +34,23 @@ public class TestPlanExecuteController {
|
|||
@Resource
|
||||
private TestPlanExecuteService testPlanExecuteService;
|
||||
|
||||
@PostMapping("/start")
|
||||
@Operation(summary = "测试计划-开始自行")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
@Log(type = OperationLogType.EXECUTE, expression = "#msClass.batchEditLog(#request)", msClass = TestPlanLogService.class)
|
||||
@PostMapping("/single")
|
||||
@Operation(summary = "测试计划单独执行")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE)
|
||||
@CheckOwner(resourceId = "#request.getExecuteId()", resourceType = "test_plan")
|
||||
@Log(type = OperationLogType.EXECUTE, expression = "#msClass.executeLog(#request)", msClass = TestPlanLogService.class)
|
||||
public void startExecute(@Validated @RequestBody TestPlanExecuteRequest request) {
|
||||
testPlanManagementService.checkModuleIsOpen(request.getExecuteId(), TestPlanResourceConfig.CONFIG_TEST_PLAN, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
|
||||
testPlanExecuteService.singleExecuteTestPlan(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping("/batch")
|
||||
@Operation(summary = "测试计划-开始自行")
|
||||
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
@Log(type = OperationLogType.EXECUTE, expression = "#msClass.batchExecuteLog(#request)", msClass = TestPlanLogService.class)
|
||||
public void startExecute(@Validated @RequestBody TestPlanBatchExecuteRequest request) {
|
||||
testPlanManagementService.checkModuleIsOpen(request.getProjectId(), TestPlanResourceConfig.CHECK_TYPE_PROJECT, Collections.singletonList(TestPlanResourceConfig.CONFIG_TEST_PLAN));
|
||||
testPlanExecuteService.execute(request, SessionUtils.getUserId());
|
||||
testPlanExecuteService.batchExecuteTestPlan(request, SessionUtils.getUserId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,4 +17,9 @@ public class TestPlanBatchEditRequest extends TestPlanBatchProcessRequest {
|
|||
@Schema(description = "标签")
|
||||
private List<String> tags;
|
||||
|
||||
@Schema(description = "定时任务是否开启")
|
||||
private boolean scheduleOpen;
|
||||
|
||||
@Schema(description = "本次编辑的字段", allowableValues = {"TAGS", "SCHEDULE"})
|
||||
private String editColumn;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package io.metersphere.plan.dto.request;
|
||||
|
||||
import io.metersphere.sdk.constants.ApiBatchRunMode;
|
||||
import io.metersphere.sdk.constants.ApiExecuteRunMode;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class TestPlanBatchExecuteRequest {
|
||||
|
||||
@Schema(description = "项目ID")
|
||||
@NotBlank(message = "project_is_not_exist")
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "执行ID")
|
||||
@NotEmpty(message = "test_plan.not.exist")
|
||||
private List<String> executeIds;
|
||||
|
||||
@Schema(description = "执行模式", allowableValues = {"SERIAL", "PARALLEL"}, requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String runMode = ApiBatchRunMode.SERIAL.name();
|
||||
|
||||
@Schema(description = "执行来源", allowableValues = {"JENKINS", "SCENARIO", "RUN"}, requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String executionSource = ApiExecuteRunMode.RUN.name();
|
||||
|
||||
}
|
|
@ -1,26 +1,22 @@
|
|||
package io.metersphere.plan.dto.request;
|
||||
|
||||
import io.metersphere.sdk.constants.ApiBatchRunMode;
|
||||
import io.metersphere.sdk.constants.ApiExecuteRunMode;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author wx
|
||||
*/
|
||||
@Data
|
||||
public class TestPlanExecuteRequest {
|
||||
|
||||
@Schema(description = "项目ID", required = true)
|
||||
@NotBlank(message = "{project.id.not_blank}")
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "执行ID")
|
||||
List<String> executeIds;
|
||||
@NotBlank(message = "test_plan.not.exist")
|
||||
private String executeId;
|
||||
|
||||
@Schema(description = "执行模式", allowableValues = {"SERIAL", "PARALLEL"}, requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String executeMode = ApiBatchRunMode.SERIAL.name();
|
||||
private String runMode = ApiBatchRunMode.SERIAL.name();
|
||||
|
||||
@Schema(description = "执行来源", allowableValues = {"JENKINS", "SCENARIO", "RUN"}, requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String executionSource = ApiExecuteRunMode.RUN.name();
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@ import java.util.List;
|
|||
|
||||
@Data
|
||||
public class TestPlanResponse extends TestPlanStatisticsResponse {
|
||||
@Schema(description = "父Id")
|
||||
private String parent;
|
||||
|
||||
@Schema(description = "项目ID")
|
||||
private String projectId;
|
||||
@Schema(description = "测试计划编号")
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package io.metersphere.plan.enums;
|
||||
|
||||
/**
|
||||
* 测试计划执行队列类型
|
||||
*/
|
||||
public enum TestPlanExecuteQueueType {
|
||||
TEST_PLAN, TEST_PLAN_GROUP, TEST_COLLECTION
|
||||
}
|
|
@ -3,6 +3,7 @@ package io.metersphere.plan.job;
|
|||
import io.metersphere.plan.dto.request.TestPlanExecuteRequest;
|
||||
import io.metersphere.plan.service.TestPlanExecuteService;
|
||||
import io.metersphere.sdk.constants.ApiBatchRunMode;
|
||||
import io.metersphere.sdk.constants.ApiExecuteRunMode;
|
||||
import io.metersphere.sdk.util.CommonBeanFactory;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.schedule.BaseScheduleJob;
|
||||
|
@ -10,7 +11,6 @@ import org.quartz.JobExecutionContext;
|
|||
import org.quartz.JobKey;
|
||||
import org.quartz.TriggerKey;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class TestPlanScheduleJob extends BaseScheduleJob {
|
||||
|
@ -21,9 +21,10 @@ public class TestPlanScheduleJob extends BaseScheduleJob {
|
|||
assert testPlanExecuteService != null;
|
||||
Map<String, String> runConfig = JSON.parseObject(context.getJobDetail().getJobDataMap().get("config").toString(), Map.class);
|
||||
String runMode = runConfig.containsKey("runMode") ? runConfig.get("runMode") : ApiBatchRunMode.SERIAL.name();
|
||||
testPlanExecuteService.execute(new TestPlanExecuteRequest() {{
|
||||
this.setExecuteIds(Collections.singletonList(resourceId));
|
||||
this.setExecuteMode(runMode);
|
||||
testPlanExecuteService.singleExecuteTestPlan(new TestPlanExecuteRequest() {{
|
||||
this.setExecuteId(resourceId);
|
||||
this.setRunMode(runMode);
|
||||
this.setExecutionSource(ApiExecuteRunMode.SCHEDULE.name());
|
||||
}}, userId);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ public interface ExtTestPlanApiScenarioMapper {
|
|||
|
||||
List<String> selectIdByTestPlanIdOrderByPos(String testPlanId);
|
||||
|
||||
Long getMaxPosByTestPlanId(String testPlanId);
|
||||
Long getMaxPosByRangeId(String testPlanId);
|
||||
|
||||
List<String> getIdByParam(ResourceSelectParam resourceSelectParam);
|
||||
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
WHERE test_plan_id = #{testPlanId}
|
||||
ORDER BY pos ASC
|
||||
</select>
|
||||
<select id="getMaxPosByTestPlanId" resultType="java.lang.Long">
|
||||
<select id="getMaxPosByRangeId" resultType="java.lang.Long">
|
||||
SELECT max(pos)
|
||||
FROM test_plan_api_scenario
|
||||
WHERE test_plan_id = #{0}
|
||||
WHERE test_plan_collection_Id = #{0}
|
||||
</select>
|
||||
<select id="getIdByParam"
|
||||
parameterType="io.metersphere.plan.dto.ResourceSelectParam"
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
t.type,
|
||||
t.description,
|
||||
t.pos,
|
||||
t.group_id AS parent,
|
||||
t.tags
|
||||
FROM test_plan t
|
||||
INNER JOIN user createUser ON t.create_user = createUser.id
|
||||
|
|
|
@ -12,29 +12,31 @@ import io.metersphere.functional.dto.FunctionalCaseModuleCountDTO;
|
|||
import io.metersphere.functional.dto.ProjectOptionDTO;
|
||||
import io.metersphere.plan.constants.AssociateCaseType;
|
||||
import io.metersphere.plan.constants.TreeTypeEnums;
|
||||
import io.metersphere.plan.domain.TestPlanApiCase;
|
||||
import io.metersphere.plan.domain.TestPlanApiCaseExample;
|
||||
import io.metersphere.plan.domain.TestPlanCollection;
|
||||
import io.metersphere.plan.domain.TestPlanCollectionExample;
|
||||
import io.metersphere.plan.domain.*;
|
||||
import io.metersphere.plan.dto.ApiCaseModuleDTO;
|
||||
import io.metersphere.plan.dto.ResourceLogInsertModule;
|
||||
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
||||
import io.metersphere.plan.dto.TestPlanCollectionDTO;
|
||||
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
|
||||
import io.metersphere.plan.dto.request.*;
|
||||
import io.metersphere.plan.dto.response.TestPlanApiCasePageResponse;
|
||||
import io.metersphere.plan.dto.response.TestPlanAssociationResponse;
|
||||
import io.metersphere.plan.dto.response.TestPlanOperationResponse;
|
||||
import io.metersphere.plan.mapper.ExtTestPlanApiCaseMapper;
|
||||
import io.metersphere.plan.mapper.TestPlanApiCaseMapper;
|
||||
import io.metersphere.plan.mapper.TestPlanCollectionMapper;
|
||||
import io.metersphere.plan.mapper.TestPlanMapper;
|
||||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.domain.ProjectExample;
|
||||
import io.metersphere.project.dto.ModuleCountDTO;
|
||||
import io.metersphere.project.dto.MoveNodeSortDTO;
|
||||
import io.metersphere.project.mapper.ProjectMapper;
|
||||
import io.metersphere.sdk.constants.CaseType;
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.constants.TestPlanResourceConstants;
|
||||
import io.metersphere.sdk.domain.Environment;
|
||||
import io.metersphere.sdk.domain.EnvironmentExample;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.mapper.EnvironmentMapper;
|
||||
import io.metersphere.sdk.util.BeanUtils;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
|
@ -63,6 +65,9 @@ import java.util.stream.Collectors;
|
|||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class TestPlanApiCaseService extends TestPlanResourceService {
|
||||
|
||||
@Resource
|
||||
private TestPlanMapper testPlanMapper;
|
||||
@Resource
|
||||
private TestPlanApiCaseMapper testPlanApiCaseMapper;
|
||||
@Resource
|
||||
|
@ -86,6 +91,8 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
|
|||
private TestPlanCollectionMapper testPlanCollectionMapper;
|
||||
@Resource
|
||||
private ApiTestCaseMapper apiTestCaseMapper;
|
||||
@Resource
|
||||
private TestPlanResourceLogService testPlanResourceLogService;
|
||||
|
||||
@Override
|
||||
public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
|
||||
|
@ -106,8 +113,7 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
|
|||
|
||||
@Override
|
||||
public void updatePos(String id, long pos) {
|
||||
// todo
|
||||
// extTestPlanApiCaseMapper.updatePos(id, pos);
|
||||
extTestPlanApiCaseMapper.updatePos(id, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -142,15 +148,14 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
|
|||
|
||||
@Override
|
||||
public void refreshPos(String testPlanId) {
|
||||
// todo
|
||||
// List<String> caseIdList = extTestPlanApiCaseMapper.selectIdByTestPlanIdOrderByPos(testPlanId);
|
||||
// SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
// ExtTestPlanApiCaseMapper batchUpdateMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class);
|
||||
// for (int i = 0; i < caseIdList.size(); i++) {
|
||||
// batchUpdateMapper.updatePos(caseIdList.get(i), i * DEFAULT_NODE_INTERVAL_POS);
|
||||
// }
|
||||
// sqlSession.flushStatements();
|
||||
// SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
List<String> caseIdList = extTestPlanApiCaseMapper.selectIdByTestPlanIdOrderByPos(testPlanId);
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
ExtTestPlanApiCaseMapper batchUpdateMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class);
|
||||
for (int i = 0; i < caseIdList.size(); i++) {
|
||||
batchUpdateMapper.updatePos(caseIdList.get(i), i * DEFAULT_NODE_INTERVAL_POS);
|
||||
}
|
||||
sqlSession.flushStatements();
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -541,4 +546,23 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
|
|||
apiCaseExample.createCriteria().andTestPlanIdEqualTo(planId);
|
||||
apiBatchMapper.updateByExampleSelective(record, apiCaseExample);
|
||||
}
|
||||
|
||||
public TestPlanOperationResponse sortNode(ResourceSortRequest request, LogInsertModule logInsertModule) {
|
||||
TestPlanApiCase dragNode = testPlanApiCaseMapper.selectByPrimaryKey(request.getMoveId());
|
||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestCollectionId());
|
||||
if (dragNode == null) {
|
||||
throw new MSException(Translator.get("test_plan.drag.node.error"));
|
||||
}
|
||||
TestPlanOperationResponse response = new TestPlanOperationResponse();
|
||||
MoveNodeSortDTO sortDTO = super.getNodeSortDTO(
|
||||
request.getTestCollectionId(),
|
||||
super.getNodeMoveRequest(request, true),
|
||||
extTestPlanApiCaseMapper::selectDragInfoById,
|
||||
extTestPlanApiCaseMapper::selectNodeByPosOperator
|
||||
);
|
||||
super.sort(sortDTO);
|
||||
response.setOperationCount(1);
|
||||
testPlanResourceLogService.saveSortLog(testPlan, request.getMoveId(), new ResourceLogInsertModule(TestPlanResourceConstants.RESOURCE_API_CASE, logInsertModule));
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,20 +3,26 @@ package io.metersphere.plan.service;
|
|||
import io.metersphere.api.dto.scenario.ApiScenarioDTO;
|
||||
import io.metersphere.api.service.scenario.ApiScenarioService;
|
||||
import io.metersphere.plan.constants.AssociateCaseType;
|
||||
import io.metersphere.plan.domain.TestPlan;
|
||||
import io.metersphere.plan.domain.TestPlanApiScenario;
|
||||
import io.metersphere.plan.domain.TestPlanApiScenarioExample;
|
||||
import io.metersphere.plan.dto.ResourceLogInsertModule;
|
||||
import io.metersphere.plan.dto.TestPlanCaseRunResultCount;
|
||||
import io.metersphere.plan.dto.TestPlanCollectionDTO;
|
||||
import io.metersphere.plan.dto.request.BaseCollectionAssociateRequest;
|
||||
import io.metersphere.plan.dto.request.ResourceSortRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanApiScenarioRequest;
|
||||
import io.metersphere.plan.mapper.ExtTestPlanApiScenarioMapper;
|
||||
import io.metersphere.plan.mapper.TestPlanApiScenarioMapper;
|
||||
import io.metersphere.plan.mapper.TestPlanCollectionMapper;
|
||||
import io.metersphere.plan.dto.response.TestPlanOperationResponse;
|
||||
import io.metersphere.plan.mapper.*;
|
||||
import io.metersphere.project.dto.MoveNodeSortDTO;
|
||||
import io.metersphere.sdk.constants.CaseType;
|
||||
import io.metersphere.sdk.constants.TestPlanResourceConstants;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.BeanUtils;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.dto.LogInsertModule;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
|
@ -43,6 +49,10 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
|
|||
private TestPlanCollectionMapper testPlanCollectionMapper;
|
||||
@Resource
|
||||
private ApiScenarioService apiScenarioService;
|
||||
@Resource
|
||||
private TestPlanMapper testPlanMapper;
|
||||
@Resource
|
||||
private TestPlanResourceLogService testPlanResourceLogService;
|
||||
|
||||
@Override
|
||||
public void deleteBatchByTestPlanId(List<String> testPlanIdList) {
|
||||
|
@ -52,14 +62,18 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public long getNextOrder(String projectId) {
|
||||
public long getNextOrder(String collectionId) {
|
||||
Long maxPos = extTestPlanApiScenarioMapper.getMaxPosByRangeId(collectionId);
|
||||
if (maxPos == null) {
|
||||
return 0;
|
||||
} else {
|
||||
return maxPos + DEFAULT_NODE_INTERVAL_POS;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePos(String id, long pos) {
|
||||
// todo
|
||||
// extTestPlanApiScenarioMapper.updatePos(id, pos);
|
||||
extTestPlanApiScenarioMapper.updatePos(id, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -94,19 +108,18 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
|
|||
|
||||
@Override
|
||||
public void refreshPos(String testPlanId) {
|
||||
// todo
|
||||
// List<String> caseIdList = extTestPlanApiScenarioMapper.selectIdByTestPlanIdOrderByPos(testPlanId);
|
||||
// SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
// ExtTestPlanApiCaseMapper batchUpdateMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class);
|
||||
// for (int i = 0; i < caseIdList.size(); i++) {
|
||||
// batchUpdateMapper.updatePos(caseIdList.get(i), i * DEFAULT_NODE_INTERVAL_POS);
|
||||
// }
|
||||
// sqlSession.flushStatements();
|
||||
// SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
List<String> caseIdList = extTestPlanApiScenarioMapper.selectIdByTestPlanIdOrderByPos(testPlanId);
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
ExtTestPlanApiCaseMapper batchUpdateMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class);
|
||||
for (int i = 0; i < caseIdList.size(); i++) {
|
||||
batchUpdateMapper.updatePos(caseIdList.get(i), i * DEFAULT_NODE_INTERVAL_POS);
|
||||
}
|
||||
sqlSession.flushStatements();
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void associateCollection(String planId, Map<String, List<BaseCollectionAssociateRequest>> collectionAssociates, String userId) {
|
||||
public void associateCollection(String planId, Map<String, List<BaseCollectionAssociateRequest>> collectionAssociates,String userId) {
|
||||
List<BaseCollectionAssociateRequest> apiScenarios = collectionAssociates.get(AssociateCaseType.API_SCENARIO);
|
||||
// TODO: 调用具体的关联场景用例入库方法 入参{计划ID, 测试集ID, 关联的用例ID集合}
|
||||
}
|
||||
|
@ -136,4 +149,22 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
|
|||
List<ApiScenarioDTO> scenarioPage = apiScenarioService.getScenarioPage(request, isRepeat, request.getTestPlanId());
|
||||
return scenarioPage;
|
||||
}
|
||||
public TestPlanOperationResponse sortNode(ResourceSortRequest request, LogInsertModule logInsertModule) {
|
||||
TestPlanApiScenario dragNode = testPlanApiScenarioMapper.selectByPrimaryKey(request.getMoveId());
|
||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getTestCollectionId());
|
||||
if (dragNode == null) {
|
||||
throw new MSException(Translator.get("test_plan.drag.node.error"));
|
||||
}
|
||||
TestPlanOperationResponse response = new TestPlanOperationResponse();
|
||||
MoveNodeSortDTO sortDTO = super.getNodeSortDTO(
|
||||
request.getTestCollectionId(),
|
||||
super.getNodeMoveRequest(request, true),
|
||||
extTestPlanApiScenarioMapper::selectDragInfoById,
|
||||
extTestPlanApiScenarioMapper::selectNodeByPosOperator
|
||||
);
|
||||
super.sort(sortDTO);
|
||||
response.setOperationCount(1);
|
||||
testPlanResourceLogService.saveSortLog(testPlan, request.getMoveId(), new ResourceLogInsertModule(TestPlanResourceConstants.RESOURCE_API_CASE, logInsertModule));
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ public class TestPlanBatchOperationService extends TestPlanBaseUtilsService {
|
|||
TestPlanConfig newTestPlanConfig = new TestPlanConfig();
|
||||
BeanUtils.copyBean(newTestPlanConfig, originalTestPlanConfig);
|
||||
newTestPlanConfig.setTestPlanId(testPlan.getId());
|
||||
testPlanConfigMapper.insert(newTestPlanConfig);
|
||||
testPlanConfigMapper.insertSelective(newTestPlanConfig);
|
||||
}
|
||||
|
||||
//todo 测试规划信息
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
package io.metersphere.plan.service;
|
||||
|
||||
import io.metersphere.plan.domain.TestPlan;
|
||||
import io.metersphere.plan.dto.request.TestPlanBatchExecuteRequest;
|
||||
import io.metersphere.plan.dto.request.TestPlanExecuteRequest;
|
||||
import io.metersphere.plan.enums.TestPlanExecuteQueueType;
|
||||
import io.metersphere.plan.mapper.TestPlanMapper;
|
||||
import io.metersphere.sdk.constants.ApiBatchRunMode;
|
||||
import io.metersphere.sdk.constants.TestPlanConstants;
|
||||
import io.metersphere.sdk.dto.queue.TestPlanExecutionQueue;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
|
@ -30,70 +34,137 @@ public class TestPlanExecuteService {
|
|||
@Resource
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
public static final String TEST_PLAN_QUEUE_PREFIX = "queue:test-plan:";
|
||||
public static final String QUEUE_PREFIX_TEST_PLAN = "test-plan-execute:";
|
||||
public static final String QUEUE_PREFIX_TEST_PLAN_GROUP = "test-plan-group-execute:";
|
||||
public static final String QUEUE_PREFIX_TEST_COLLECTION = "test-collection-execute:";
|
||||
|
||||
private TestPlanExecutionQueue genQueue(String testPlanId, String queueId, long pos, String userId, String executeMode) {
|
||||
TestPlanExecutionQueue testPlanExecutionQueue = new TestPlanExecutionQueue();
|
||||
testPlanExecutionQueue.setTestPlanId(testPlanId);
|
||||
testPlanExecutionQueue.setQueueId(queueId);
|
||||
testPlanExecutionQueue.setPos(pos);
|
||||
testPlanExecutionQueue.setPrepareReportId(IDGenerator.nextStr());
|
||||
testPlanExecutionQueue.setCreateUser(userId);
|
||||
testPlanExecutionQueue.setCreateTime(System.currentTimeMillis());
|
||||
testPlanExecutionQueue.setRunMode(executeMode);
|
||||
return testPlanExecutionQueue;
|
||||
}
|
||||
|
||||
public void execute(TestPlanExecuteRequest request, String userId) {
|
||||
|
||||
List<String> rightfulIds = testPlanService.selectRightfulIds(request.getExecuteIds());
|
||||
|
||||
if (CollectionUtils.isNotEmpty(rightfulIds)) {
|
||||
//遍历原始ID,只挑选符合条件的ID进行。防止顺序错乱。
|
||||
String executeMode = request.getExecuteMode();
|
||||
String queueId = IDGenerator.nextStr();
|
||||
long pos = 1;
|
||||
List<TestPlanExecutionQueue> testPlanExecutionQueues = new ArrayList<>();
|
||||
for (String testPlanId : request.getExecuteIds()) {
|
||||
List<TestPlan> childList = testPlanService.selectChildPlanByGroupId(testPlanId);
|
||||
if (CollectionUtils.isNotEmpty(childList)) {
|
||||
for (TestPlan child : childList) {
|
||||
testPlanExecutionQueues.add(genQueue(child.getId(), queueId, pos++, userId, executeMode));
|
||||
}
|
||||
} else {
|
||||
testPlanExecutionQueues.add(genQueue(testPlanId, queueId, pos++, userId, executeMode));
|
||||
}
|
||||
}
|
||||
if (StringUtils.equalsIgnoreCase(request.getExecuteMode(), ApiBatchRunMode.SERIAL.name())) {
|
||||
//串行
|
||||
testPlanExecutionQueues.forEach(testPlanExecutionQueue -> {
|
||||
redisTemplate.opsForList().rightPush(TEST_PLAN_QUEUE_PREFIX + queueId, JSON.toJSONString(testPlanExecutionQueue));
|
||||
});
|
||||
try {
|
||||
executeByExecutionQueue(getNextDetail(queueId));
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
} else {
|
||||
//并行
|
||||
testPlanExecutionQueues.forEach(testPlanExecutionQueue -> {
|
||||
executeByExecutionQueue(testPlanExecutionQueue);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void executeByExecutionQueue(TestPlanExecutionQueue queue) {
|
||||
Thread.startVirtualThread(() -> {
|
||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(queue.getTestPlanId());
|
||||
// todo 获取测试规划,通过测试规划执行方式确定用例的执行方式
|
||||
});
|
||||
public void executeTestPlan(TestPlan testPlan, String executionSource, String userId) {
|
||||
//todo 查询执行配置,配置下一步的队列
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个节点
|
||||
* 预执行执行测试计划
|
||||
*/
|
||||
public TestPlanExecutionQueue getNextDetail(String queueId) throws Exception {
|
||||
String queueKey = TEST_PLAN_QUEUE_PREFIX + queueId;
|
||||
private void prepareExecuteTestPlan(TestPlan testPlan, String parentQueueId, String runMode, String executionSource, String userId) {
|
||||
if (testPlan == null || StringUtils.equalsIgnoreCase(testPlan.getStatus(), TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED)) {
|
||||
throw new MSException("test_plan.error");
|
||||
}
|
||||
if (StringUtils.equalsIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
|
||||
List<TestPlan> children = testPlanService.selectNotArchivedChildren(testPlan.getId());
|
||||
|
||||
long pos = 0;
|
||||
List<TestPlanExecutionQueue> childrenQueue = new ArrayList<>();
|
||||
for (TestPlan child : children) {
|
||||
childrenQueue.add(
|
||||
new TestPlanExecutionQueue(child.getGroupId(), parentQueueId, child.getId(), pos++, runMode, executionSource, IDGenerator.nextStr(), userId, System.currentTimeMillis())
|
||||
);
|
||||
}
|
||||
|
||||
if (StringUtils.equalsIgnoreCase(runMode, ApiBatchRunMode.SERIAL.name())) {
|
||||
//串行
|
||||
childrenQueue.forEach(childQueue -> {
|
||||
redisTemplate.opsForList().rightPush(QUEUE_PREFIX_TEST_PLAN_GROUP + testPlan.getId(), JSON.toJSONString(childrenQueue));
|
||||
});
|
||||
executeNextTestPlanByGroupQueueId(testPlan.getId(), parentQueueId);
|
||||
} else {
|
||||
//并行
|
||||
childrenQueue.forEach(childQueue -> {
|
||||
executeTestPlan(testPlanMapper.selectByPrimaryKey(childQueue.getTestPlanId()), childQueue.getExecutionSource(), childQueue.getCreateUser());
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.executeTestPlan(testPlan, executionSource, userId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个执行测试计划
|
||||
*/
|
||||
public void singleExecuteTestPlan(TestPlanExecuteRequest request, String userId) {
|
||||
prepareExecuteTestPlan(testPlanMapper.selectByPrimaryKey(request.getExecuteId()), null, request.getRunMode(), request.getExecutionSource(), userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量执行测试计划
|
||||
*/
|
||||
public void batchExecuteTestPlan(TestPlanBatchExecuteRequest request, String userId) {
|
||||
List<String> rightfulIds = testPlanService.selectRightfulIds(request.getExecuteIds());
|
||||
if (CollectionUtils.isNotEmpty(rightfulIds)) {
|
||||
|
||||
String runMode = request.getRunMode();
|
||||
String queueId = IDGenerator.nextStr();
|
||||
long pos = 0;
|
||||
List<TestPlanExecutionQueue> testPlanExecutionQueues = new ArrayList<>();
|
||||
|
||||
//遍历原始ID,只挑选符合条件的ID进行。防止顺序错乱。
|
||||
for (String testPlanId : request.getExecuteIds()) {
|
||||
if (rightfulIds.contains(testPlanId)) {
|
||||
testPlanExecutionQueues.add(
|
||||
new TestPlanExecutionQueue(queueId, null, testPlanId, pos++, runMode, request.getExecutionSource(), IDGenerator.nextStr(), userId, System.currentTimeMillis())
|
||||
);
|
||||
}
|
||||
}
|
||||
if (StringUtils.equalsIgnoreCase(request.getRunMode(), ApiBatchRunMode.SERIAL.name())) {
|
||||
//串行
|
||||
testPlanExecutionQueues.forEach(testPlanExecutionQueue -> {
|
||||
redisTemplate.opsForList().rightPush(QUEUE_PREFIX_TEST_PLAN + queueId, JSON.toJSONString(testPlanExecutionQueue));
|
||||
});
|
||||
executeNextTestPlanByQueueId(queueId);
|
||||
} else {
|
||||
//并行
|
||||
testPlanExecutionQueues.forEach(testPlanExecutionQueue -> {
|
||||
prepareExecuteTestPlan(testPlanMapper.selectByPrimaryKey(testPlanExecutionQueue.getTestPlanId()),
|
||||
null,
|
||||
testPlanExecutionQueue.getRunMode(),
|
||||
testPlanExecutionQueue.getExecutionSource(),
|
||||
testPlanExecutionQueue.getCreateUser());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//执行下一个测试计划组节点的测试计划
|
||||
private void executeNextTestPlanByGroupQueueId(String groupQueueId, String parentQueueId) {
|
||||
TestPlanExecutionQueue nextQueue = getNextDetail(groupQueueId, QUEUE_PREFIX_TEST_PLAN_GROUP, TestPlanExecutionQueue.class);
|
||||
if (nextQueue != null) {
|
||||
try {
|
||||
executeTestPlan(testPlanMapper.selectByPrimaryKey(nextQueue.getTestPlanId()), nextQueue.getExecutionSource(), nextQueue.getCreateUser());
|
||||
} catch (Exception e) {
|
||||
this.executeNextTestPlanByQueueId(groupQueueId);
|
||||
}
|
||||
} else {
|
||||
// todo 测试计划组执行完成
|
||||
|
||||
if (StringUtils.isNotEmpty(parentQueueId)) {
|
||||
// 如果测试计划组是在批量执行时处理的,继续进行批量执行队列里的下个节点
|
||||
executeNextTestPlanByQueueId(parentQueueId);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//执行下一个批量执行节点的测试计划
|
||||
private void executeNextTestPlanByQueueId(String queueId) {
|
||||
TestPlanExecutionQueue nextQueue = getNextDetail(queueId, QUEUE_PREFIX_TEST_PLAN, TestPlanExecutionQueue.class);
|
||||
if (nextQueue != null) {
|
||||
try {
|
||||
prepareExecuteTestPlan(
|
||||
testPlanMapper.selectByPrimaryKey(nextQueue.getTestPlanId()),
|
||||
queueId,
|
||||
nextQueue.getRunMode(),
|
||||
nextQueue.getExecutionSource(),
|
||||
nextQueue.getCreateUser());
|
||||
} catch (Exception e) {
|
||||
this.executeNextTestPlanByQueueId(queueId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个队列节点
|
||||
*/
|
||||
private <T> T getNextDetail(String queueId, String queueType, Class<T> formatClass) {
|
||||
String queueKey = this.genQueueKey(queueId, queueType);
|
||||
ListOperations<String, String> listOps = redisTemplate.opsForList();
|
||||
String queueDetail = listOps.leftPop(queueKey);
|
||||
if (StringUtils.isBlank(queueDetail)) {
|
||||
|
@ -103,32 +174,46 @@ public class TestPlanExecuteService {
|
|||
if (StringUtils.isNotBlank(queueDetail)) {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(queueDetail)) {
|
||||
Long size = size(queueId);
|
||||
Long size = getQueueSize(queueId);
|
||||
if (size == null || size == 0) {
|
||||
// 最后一个节点清理队列
|
||||
deleteQueue(queueId);
|
||||
deleteQueue(queueKey);
|
||||
}
|
||||
return JSON.parseObject(queueDetail, TestPlanExecutionQueue.class);
|
||||
return JSON.parseObject(queueDetail, formatClass);
|
||||
}
|
||||
|
||||
// 整体获取完,清理队列
|
||||
deleteQueue(queueId);
|
||||
|
||||
deleteQueue(queueKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
public void deleteQueue(String queueId) {
|
||||
redisTemplate.delete(TEST_PLAN_QUEUE_PREFIX + queueId);
|
||||
private void deleteQueue(String queueKey) {
|
||||
redisTemplate.delete(queueKey);
|
||||
}
|
||||
|
||||
public Long size(String queueId) {
|
||||
private Long getQueueSize(String queueKey) {
|
||||
ListOperations<String, String> listOps = redisTemplate.opsForList();
|
||||
String queueKey = TEST_PLAN_QUEUE_PREFIX + queueId;
|
||||
return listOps.size(queueKey);
|
||||
}
|
||||
|
||||
//生成队列key
|
||||
private String genQueueKey(String queueId, String queueType) {
|
||||
String key = "";
|
||||
if (StringUtils.equalsIgnoreCase(queueType, TestPlanExecuteQueueType.TEST_PLAN.name())) {
|
||||
key = QUEUE_PREFIX_TEST_PLAN;
|
||||
} else if (StringUtils.equalsIgnoreCase(queueType, TestPlanExecuteQueueType.TEST_PLAN_GROUP.name())) {
|
||||
key = QUEUE_PREFIX_TEST_PLAN_GROUP;
|
||||
} else if (StringUtils.equalsIgnoreCase(queueType, TestPlanExecuteQueueType.TEST_COLLECTION.name())) {
|
||||
key = QUEUE_PREFIX_TEST_COLLECTION;
|
||||
}
|
||||
return key + queueId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
handleAssociateCase(createOrCopyRequest.getBaseAssociateCaseRequest(), operator, createTestPlan);
|
||||
|
||||
testPlanMapper.insert(createTestPlan);
|
||||
testPlanConfigMapper.insert(testPlanConfig);
|
||||
testPlanConfigMapper.insertSelective(testPlanConfig);
|
||||
return createTestPlan;
|
||||
}
|
||||
|
||||
|
@ -307,10 +307,8 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
|
||||
//删除测试计划报告 todo: 正式版增加接口用例报告、接口场景报告的清理
|
||||
testPlanReportService.deleteByTestPlanIds(testPlanIds);
|
||||
/*
|
||||
todo
|
||||
删除计划定时任务
|
||||
*/
|
||||
//删除定时任务
|
||||
scheduleService.deleteByResourceIds(testPlanIds, TestPlanScheduleJob.class.getName());
|
||||
}
|
||||
|
||||
|
||||
|
@ -622,14 +620,27 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
* @param userId
|
||||
*/
|
||||
public void batchEdit(TestPlanBatchEditRequest request, String userId) {
|
||||
|
||||
// 目前计划的批量操作不支持全选所有页
|
||||
List<String> ids = request.getSelectIds();
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
if (StringUtils.equalsIgnoreCase(request.getEditColumn(), "SCHEDULE")) {
|
||||
TestPlanExample example = new TestPlanExample();
|
||||
example.createCriteria().andIdIn(ids).andStatusNotEqualTo(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED);
|
||||
List<TestPlan> testPlanList = testPlanMapper.selectByExample(example);
|
||||
//批量编辑定时任务
|
||||
for (TestPlan testPlan : testPlanList) {
|
||||
scheduleService.updateIfExist(testPlan.getId(), request.isScheduleOpen(), TestPlanScheduleJob.getJobKey(testPlan.getId()),
|
||||
TestPlanScheduleJob.getTriggerKey(testPlan.getId()), TestPlanScheduleJob.class, userId);
|
||||
}
|
||||
} else {
|
||||
//默认编辑tags
|
||||
User user = userMapper.selectByPrimaryKey(userId);
|
||||
handleTags(request, userId, ids);
|
||||
testPlanSendNoticeService.batchSendNotice(request.getProjectId(), ids, user, NoticeConstants.Event.UPDATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理标签
|
||||
|
@ -750,7 +761,7 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
testPlan.setStatus(testPlanFinalStatus);
|
||||
testPlanMapper.updateByPrimaryKeySelective(testPlan);
|
||||
|
||||
List<TestPlan> childPlan = this.selectChildPlanByGroupId(testPlanId);
|
||||
List<TestPlan> childPlan = this.selectNotArchivedChildren(testPlanId);
|
||||
if (CollectionUtils.isNotEmpty(childPlan)) {
|
||||
TestPlan updateGroupPlan = new TestPlan();
|
||||
updateGroupPlan.setId(testPlanId);
|
||||
|
@ -787,11 +798,11 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
|
||||
if (request.isEnable() && StringUtils.equalsIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
|
||||
//配置开启的测试计划组定时任务,要将组下的所有测试计划定时任务都关闭掉
|
||||
List<TestPlan> children = this.selectChildPlanByGroupId(testPlan.getId());
|
||||
List<TestPlan> children = this.selectNotArchivedChildren(testPlan.getId());
|
||||
for (TestPlan child : children) {
|
||||
scheduleService.closeIfExist(child.getId(), TestPlanScheduleJob.getJobKey(testPlan.getId()),
|
||||
scheduleService.updateIfExist(child.getId(), false, TestPlanScheduleJob.getJobKey(testPlan.getId()),
|
||||
TestPlanScheduleJob.getTriggerKey(testPlan.getId()),
|
||||
TestPlanScheduleJob.class);
|
||||
TestPlanScheduleJob.class, operator);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -811,7 +822,7 @@ public class TestPlanService extends TestPlanBaseUtilsService {
|
|||
return extTestPlanMapper.selectNotArchivedIds(executeIds);
|
||||
}
|
||||
|
||||
public List<TestPlan> selectChildPlanByGroupId(String testPlanGroupId) {
|
||||
public List<TestPlan> selectNotArchivedChildren(String testPlanGroupId) {
|
||||
TestPlanExample example = new TestPlanExample();
|
||||
example.createCriteria().andGroupIdEqualTo(testPlanGroupId).andStatusNotEqualTo(TestPlanConstants.TEST_PLAN_STATUS_ARCHIVED);
|
||||
example.setOrderByClause("pos asc");
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
<!-- typeHandler="io.metersphere.handler.ListTypeHandler"/>-->
|
||||
<!-- </table>-->
|
||||
|
||||
<!-- <table tableName="test_plan_functional_case"/>-->
|
||||
<table tableName="test_plan_config"/>
|
||||
<!-- <table tableName="test_plan_api_case"/>-->
|
||||
<!-- <table tableName="test_plan_api_scenario"/>-->
|
||||
<!-- <table tableName="test_plan_report"/>-->
|
||||
|
|
|
@ -119,7 +119,8 @@ public class TestPlanTests extends BaseTest {
|
|||
private static final String URL_POST_TEST_PLAN_BATCH_DELETE = "/test-plan/batch-delete";
|
||||
private static final String URL_POST_TEST_PLAN_SCHEDULE = "/test-plan/schedule-config";
|
||||
private static final String URL_POST_TEST_PLAN_SCHEDULE_DELETE = "/test-plan/schedule-config-delete/%s";
|
||||
private static final String URL_POST_TEST_PLAN_EXECUTE = "/test-plan-execute/start";
|
||||
private static final String URL_POST_TEST_PLAN_SINGLE_EXECUTE = "/test-plan-execute/single";
|
||||
private static final String URL_POST_TEST_PLAN_BATCH_EXECUTE = "/test-plan-execute/batch";
|
||||
|
||||
//测试计划资源-功能用例
|
||||
private static final String URL_POST_RESOURCE_CASE_ASSOCIATION = "/test-plan/association";
|
||||
|
@ -1492,13 +1493,21 @@ public class TestPlanTests extends BaseTest {
|
|||
@Order(71)
|
||||
public void executeTest() throws Exception {
|
||||
TestPlanExecuteRequest executeRequest = new TestPlanExecuteRequest();
|
||||
executeRequest.setExecuteIds(Collections.singletonList(groupTestPlanId7));
|
||||
executeRequest.setProjectId(project.getId());
|
||||
executeRequest.setExecuteId(groupTestPlanId7);
|
||||
//串行
|
||||
this.requestPostWithOk(URL_POST_TEST_PLAN_EXECUTE, executeRequest);
|
||||
this.requestPostWithOk(URL_POST_TEST_PLAN_SINGLE_EXECUTE, executeRequest);
|
||||
//并行
|
||||
executeRequest.setExecuteMode(ApiBatchRunMode.PARALLEL.name());
|
||||
this.requestPostWithOk(URL_POST_TEST_PLAN_EXECUTE, executeRequest);
|
||||
executeRequest.setRunMode(ApiBatchRunMode.PARALLEL.name());
|
||||
this.requestPostWithOk(URL_POST_TEST_PLAN_SINGLE_EXECUTE, executeRequest);
|
||||
|
||||
TestPlanBatchExecuteRequest batchExecuteRequest = new TestPlanBatchExecuteRequest();
|
||||
batchExecuteRequest.setExecuteIds(Collections.singletonList(groupTestPlanId7));
|
||||
batchExecuteRequest.setProjectId(project.getId());
|
||||
//串行
|
||||
this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_EXECUTE, batchExecuteRequest);
|
||||
//并行
|
||||
batchExecuteRequest.setRunMode(ApiBatchRunMode.PARALLEL.name());
|
||||
this.requestPostWithOk(URL_POST_TEST_PLAN_BATCH_EXECUTE, batchExecuteRequest);
|
||||
}
|
||||
@Test
|
||||
@Order(81)
|
||||
|
|
|
@ -4,10 +4,10 @@ VALUES
|
|||
('wxxx_2', 10000, 'wxx_1234', 'NONE', '1', 'eeew', 'PREPARED', 'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11');
|
||||
|
||||
|
||||
INSERT INTO `test_plan_config`(`test_plan_id`, `automatic_status_update`, `repeat_case`, `pass_threshold`)
|
||||
VALUES
|
||||
('wxxx_1', b'0', b'0', 100),
|
||||
('wxxx_2', b'0', b'0', 100);
|
||||
INSERT INTO `test_plan_config`(`test_plan_id`, `automatic_status_update`, `repeat_case`, `pass_threshold`,
|
||||
`case_run_mode`)
|
||||
VALUES ('wxxx_1', b'0', b'0', 100, 'PARALLEL'),
|
||||
('wxxx_2', b'0', b'0', 100, 'PARALLEL');
|
||||
|
||||
|
||||
INSERT INTO `api_definition`(`id`, `name`, `protocol`, `method`, `path`, `status`, `num`, `tags`, `pos`, `project_id`, `module_id`, `latest`, `version_id`, `ref_id`, `description`, `create_time`, `create_user`, `update_time`, `update_user`, `delete_user`, `delete_time`, `deleted`)
|
||||
|
|
|
@ -4,10 +4,10 @@ VALUES
|
|||
('wxx_2', 10000, 'wx_1234', 'NONE', '1', 'eeew', 'PREPARED', 'TEST_PLAN', NULL, 1714980158000, 'WX', 1714980158000, 'WX', 1714980158000, 1714980158000, 1714980158000, 1714980158000, '11');
|
||||
|
||||
|
||||
INSERT INTO `test_plan_config`(`test_plan_id`, `automatic_status_update`, `repeat_case`, `pass_threshold`)
|
||||
VALUES
|
||||
('wxx_1', b'0', b'0', 100),
|
||||
('wxx_2', b'0', b'0', 100);
|
||||
INSERT INTO `test_plan_config`(`test_plan_id`, `automatic_status_update`, `repeat_case`, `pass_threshold`,
|
||||
'case_run_mode')
|
||||
VALUES ('wxx_1', b'0', b'0', 100, 'PARALLEL'),
|
||||
('wxx_2', b'0', b'0', 100, 'PARALLEL');
|
||||
|
||||
INSERT INTO `test_plan_functional_case`(`id`, `test_plan_id`, `functional_case_id`, `create_time`, `create_user`, `execute_user`, `last_exec_time`, `last_exec_result`, `pos`, `test_plan_collection_id`)
|
||||
VALUES ('wxx_tpfc_1', 'wxx_1', 'wxx_test_1', 1714980158000, 'admin', NULL, NULL, NULL, 1, '123');
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
INSERT INTO `test_plan`(`id`, `num`, `project_id`, `group_id`, `module_id`, `name`, `status`, `type`, `tags`, `create_time`, `create_user`, `update_time`, `update_user`, `planned_start_time`, `planned_end_time`, `actual_start_time`, `actual_end_time`, `description`) VALUES
|
||||
('plan_id_for_gen_report', 100001, '100001100001', 'NONE', '1', 'gen-report-plan', 'PREPARED', 'TEST_PLAN', NULL, CURRENT_TIMESTAMP, 'admin', CURRENT_TIMESTAMP, 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, '11'),
|
||||
('plan_id_for_gen_report_1', 100001, '100001100001', 'NONE', '1', 'gen-report-plan-1', 'PREPARED', 'TEST_PLAN', NULL, CURRENT_TIMESTAMP, 'admin', CURRENT_TIMESTAMP, 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, '11');
|
||||
INSERT INTO `test_plan_config`(`test_plan_id`, `automatic_status_update`, `repeat_case`, `pass_threshold`) VALUES
|
||||
('plan_id_for_gen_report', b'0', b'0', 100.00),
|
||||
('plan_id_for_gen_report_1', b'0', b'0', 0.00);
|
||||
INSERT INTO `test_plan_config`(`test_plan_id`, `automatic_status_update`, `repeat_case`, `pass_threshold`,
|
||||
'case_run_mode')
|
||||
VALUES ('plan_id_for_gen_report', b'0', b'0', 100.00, 'PARALLEL'),
|
||||
('plan_id_for_gen_report_1', b'0', b'0', 0.00, 'PARALLEL');
|
||||
|
||||
-- 计划关联用例执行的测试数据
|
||||
INSERT INTO `test_plan_functional_case` (`id`, `test_plan_id`, `functional_case_id`, `create_time`, `create_user`, `execute_user`, `last_exec_time`, `last_exec_result`, `pos`, `test_plan_collection_id`) VALUES
|
||||
|
|
|
@ -43,11 +43,11 @@ INSERT INTO `test_plan_module`(`id`, `project_id`, `name`, `parent_id`, `pos`, `
|
|||
VALUES ('1', 'songtianyang-fix-wx', 'wx_测试模块名称', 'ROOT', 1, 1714980158000, 1714980158000, 'admin', 'admin');
|
||||
|
||||
|
||||
INSERT INTO `test_plan_config`(`test_plan_id`, `automatic_status_update`, `repeat_case`, `pass_threshold`)
|
||||
VALUES
|
||||
('wx_test_plan_id_1', b'0', b'0', 100),
|
||||
('wx_test_plan_id_4', b'0', b'0', 100),
|
||||
('wx_test_plan_id_7', b'0', b'0', 100);
|
||||
INSERT INTO `test_plan_config`(`test_plan_id`, `automatic_status_update`, `repeat_case`, `pass_threshold`,
|
||||
'case_run_mode')
|
||||
VALUES ('wx_test_plan_id_1', b'0', b'0', 100, 'PARALLEL'),
|
||||
('wx_test_plan_id_4', b'0', b'0', 100, 'PARALLEL'),
|
||||
('wx_test_plan_id_7', b'0', b'0', 100, 'PARALLEL');
|
||||
|
||||
|
||||
INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time)
|
||||
|
|
Loading…
Reference in New Issue