feat(测试计划): 批量复制

This commit is contained in:
WangXu10 2024-05-09 11:42:26 +08:00 committed by 刘瑞斌
parent a50c2ecbdb
commit 283086b461
11 changed files with 966 additions and 36 deletions

View File

@ -0,0 +1,103 @@
package io.metersphere.plan.domain;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import lombok.Data;
@Data
public class TestPlanAllocation implements Serializable {
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{test_plan_allocation.id.not_blank}", groups = {Updated.class})
@Size(min = 1, max = 50, message = "{test_plan_allocation.id.length_range}", groups = {Created.class, Updated.class})
private String id;
@Schema(description = "测试计划ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{test_plan_allocation.test_plan_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{test_plan_allocation.test_plan_id.length_range}", groups = {Created.class, Updated.class})
private String testPlanId;
@Schema(description = "运行配置", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{test_plan_allocation.run_mode_config.not_blank}", groups = {Created.class})
private byte[] runModeConfig;
private static final long serialVersionUID = 1L;
public enum Column {
id("id", "id", "VARCHAR", false),
testPlanId("test_plan_id", "testPlanId", "VARCHAR", false),
runModeConfig("run_mode_config", "runModeConfig", "LONGVARBINARY", false);
private static final String BEGINNING_DELIMITER = "`";
private static final String ENDING_DELIMITER = "`";
private final String column;
private final boolean isColumnNameDelimited;
private final String javaProperty;
private final String jdbcType;
public String value() {
return this.column;
}
public String getValue() {
return this.column;
}
public String getJavaProperty() {
return this.javaProperty;
}
public String getJdbcType() {
return this.jdbcType;
}
Column(String column, String javaProperty, String jdbcType, boolean isColumnNameDelimited) {
this.column = column;
this.javaProperty = javaProperty;
this.jdbcType = jdbcType;
this.isColumnNameDelimited = isColumnNameDelimited;
}
public String desc() {
return this.getEscapedColumnName() + " DESC";
}
public String asc() {
return this.getEscapedColumnName() + " ASC";
}
public static Column[] excludes(Column ... excludes) {
ArrayList<Column> columns = new ArrayList<>(Arrays.asList(Column.values()));
if (excludes != null && excludes.length > 0) {
columns.removeAll(new ArrayList<>(Arrays.asList(excludes)));
}
return columns.toArray(new Column[]{});
}
public static Column[] all() {
return Column.values();
}
public String getEscapedColumnName() {
if (this.isColumnNameDelimited) {
return new StringBuilder().append(BEGINNING_DELIMITER).append(this.column).append(ENDING_DELIMITER).toString();
} else {
return this.column;
}
}
public String getAliasedEscapedColumnName() {
return this.getEscapedColumnName();
}
}
}

View File

@ -0,0 +1,340 @@
package io.metersphere.plan.domain;
import java.util.ArrayList;
import java.util.List;
public class TestPlanAllocationExample {
protected String orderByClause;
protected boolean distinct;
protected List<Criteria> oredCriteria;
public TestPlanAllocationExample() {
oredCriteria = new ArrayList<Criteria>();
}
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
public String getOrderByClause() {
return orderByClause;
}
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
public boolean isDistinct() {
return distinct;
}
public List<Criteria> getOredCriteria() {
return oredCriteria;
}
public void or(Criteria criteria) {
oredCriteria.add(criteria);
}
public Criteria or() {
Criteria criteria = createCriteriaInternal();
oredCriteria.add(criteria);
return criteria;
}
public Criteria createCriteria() {
Criteria criteria = createCriteriaInternal();
if (oredCriteria.size() == 0) {
oredCriteria.add(criteria);
}
return criteria;
}
protected Criteria createCriteriaInternal() {
Criteria criteria = new Criteria();
return criteria;
}
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
}
protected abstract static class GeneratedCriteria {
protected List<Criterion> criteria;
protected GeneratedCriteria() {
super();
criteria = new ArrayList<Criterion>();
}
public boolean isValid() {
return criteria.size() > 0;
}
public List<Criterion> getAllCriteria() {
return criteria;
}
public List<Criterion> getCriteria() {
return criteria;
}
protected void addCriterion(String condition) {
if (condition == null) {
throw new RuntimeException("Value for condition cannot be null");
}
criteria.add(new Criterion(condition));
}
protected void addCriterion(String condition, Object value, String property) {
if (value == null) {
throw new RuntimeException("Value for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value));
}
protected void addCriterion(String condition, Object value1, Object value2, String property) {
if (value1 == null || value2 == null) {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(String value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(String value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(String value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(String value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(String value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(String value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdLike(String value) {
addCriterion("id like", value, "id");
return (Criteria) this;
}
public Criteria andIdNotLike(String value) {
addCriterion("id not like", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List<String> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List<String> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(String value1, String value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(String value1, String value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andTestPlanIdIsNull() {
addCriterion("test_plan_id is null");
return (Criteria) this;
}
public Criteria andTestPlanIdIsNotNull() {
addCriterion("test_plan_id is not null");
return (Criteria) this;
}
public Criteria andTestPlanIdEqualTo(String value) {
addCriterion("test_plan_id =", value, "testPlanId");
return (Criteria) this;
}
public Criteria andTestPlanIdNotEqualTo(String value) {
addCriterion("test_plan_id <>", value, "testPlanId");
return (Criteria) this;
}
public Criteria andTestPlanIdGreaterThan(String value) {
addCriterion("test_plan_id >", value, "testPlanId");
return (Criteria) this;
}
public Criteria andTestPlanIdGreaterThanOrEqualTo(String value) {
addCriterion("test_plan_id >=", value, "testPlanId");
return (Criteria) this;
}
public Criteria andTestPlanIdLessThan(String value) {
addCriterion("test_plan_id <", value, "testPlanId");
return (Criteria) this;
}
public Criteria andTestPlanIdLessThanOrEqualTo(String value) {
addCriterion("test_plan_id <=", value, "testPlanId");
return (Criteria) this;
}
public Criteria andTestPlanIdLike(String value) {
addCriterion("test_plan_id like", value, "testPlanId");
return (Criteria) this;
}
public Criteria andTestPlanIdNotLike(String value) {
addCriterion("test_plan_id not like", value, "testPlanId");
return (Criteria) this;
}
public Criteria andTestPlanIdIn(List<String> values) {
addCriterion("test_plan_id in", values, "testPlanId");
return (Criteria) this;
}
public Criteria andTestPlanIdNotIn(List<String> values) {
addCriterion("test_plan_id not in", values, "testPlanId");
return (Criteria) this;
}
public Criteria andTestPlanIdBetween(String value1, String value2) {
addCriterion("test_plan_id between", value1, value2, "testPlanId");
return (Criteria) this;
}
public Criteria andTestPlanIdNotBetween(String value1, String value2) {
addCriterion("test_plan_id not between", value1, value2, "testPlanId");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {
protected Criteria() {
super();
}
}
public static class Criterion {
private String condition;
private Object value;
private Object secondValue;
private boolean noValue;
private boolean singleValue;
private boolean betweenValue;
private boolean listValue;
private String typeHandler;
public String getCondition() {
return condition;
}
public Object getValue() {
return value;
}
public Object getSecondValue() {
return secondValue;
}
public boolean isNoValue() {
return noValue;
}
public boolean isSingleValue() {
return singleValue;
}
public boolean isBetweenValue() {
return betweenValue;
}
public boolean isListValue() {
return listValue;
}
public String getTypeHandler() {
return typeHandler;
}
protected Criterion(String condition) {
super();
this.condition = condition;
this.typeHandler = null;
this.noValue = true;
}
protected Criterion(String condition, Object value, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.typeHandler = typeHandler;
if (value instanceof List<?>) {
this.listValue = true;
} else {
this.singleValue = true;
}
}
protected Criterion(String condition, Object value) {
this(condition, value, null);
}
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.secondValue = secondValue;
this.typeHandler = typeHandler;
this.betweenValue = true;
}
protected Criterion(String condition, Object value, Object secondValue) {
this(condition, value, secondValue, null);
}
}
}

View File

@ -0,0 +1,40 @@
package io.metersphere.plan.mapper;
import io.metersphere.plan.domain.TestPlanAllocation;
import io.metersphere.plan.domain.TestPlanAllocationExample;
import java.util.List;
import org.apache.ibatis.annotations.Param;
public interface TestPlanAllocationMapper {
long countByExample(TestPlanAllocationExample example);
int deleteByExample(TestPlanAllocationExample example);
int deleteByPrimaryKey(String id);
int insert(TestPlanAllocation record);
int insertSelective(TestPlanAllocation record);
List<TestPlanAllocation> selectByExampleWithBLOBs(TestPlanAllocationExample example);
List<TestPlanAllocation> selectByExample(TestPlanAllocationExample example);
TestPlanAllocation selectByPrimaryKey(String id);
int updateByExampleSelective(@Param("record") TestPlanAllocation record, @Param("example") TestPlanAllocationExample example);
int updateByExampleWithBLOBs(@Param("record") TestPlanAllocation record, @Param("example") TestPlanAllocationExample example);
int updateByExample(@Param("record") TestPlanAllocation record, @Param("example") TestPlanAllocationExample example);
int updateByPrimaryKeySelective(TestPlanAllocation record);
int updateByPrimaryKeyWithBLOBs(TestPlanAllocation record);
int updateByPrimaryKey(TestPlanAllocation record);
int batchInsert(@Param("list") List<TestPlanAllocation> list);
int batchInsertSelective(@Param("list") List<TestPlanAllocation> list, @Param("selective") TestPlanAllocation.Column ... selective);
}

View File

@ -0,0 +1,249 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.plan.mapper.TestPlanAllocationMapper">
<resultMap id="BaseResultMap" type="io.metersphere.plan.domain.TestPlanAllocation">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="test_plan_id" jdbcType="VARCHAR" property="testPlanId" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.plan.domain.TestPlanAllocation">
<result column="run_mode_config" jdbcType="LONGVARBINARY" property="runModeConfig" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Update_By_Example_Where_Clause">
<where>
<foreach collection="example.oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Base_Column_List">
id, test_plan_id
</sql>
<sql id="Blob_Column_List">
run_mode_config
</sql>
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.plan.domain.TestPlanAllocationExample" resultMap="ResultMapWithBLOBs">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from test_plan_allocation
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByExample" parameterType="io.metersphere.plan.domain.TestPlanAllocationExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from test_plan_allocation
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="ResultMapWithBLOBs">
select
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from test_plan_allocation
where id = #{id,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
delete from test_plan_allocation
where id = #{id,jdbcType=VARCHAR}
</delete>
<delete id="deleteByExample" parameterType="io.metersphere.plan.domain.TestPlanAllocationExample">
delete from test_plan_allocation
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.plan.domain.TestPlanAllocation">
insert into test_plan_allocation (id, test_plan_id, run_mode_config
)
values (#{id,jdbcType=VARCHAR}, #{testPlanId,jdbcType=VARCHAR}, #{runModeConfig,jdbcType=LONGVARBINARY}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.plan.domain.TestPlanAllocation">
insert into test_plan_allocation
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="testPlanId != null">
test_plan_id,
</if>
<if test="runModeConfig != null">
run_mode_config,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="testPlanId != null">
#{testPlanId,jdbcType=VARCHAR},
</if>
<if test="runModeConfig != null">
#{runModeConfig,jdbcType=LONGVARBINARY},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.plan.domain.TestPlanAllocationExample" resultType="java.lang.Long">
select count(*) from test_plan_allocation
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
update test_plan_allocation
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.testPlanId != null">
test_plan_id = #{record.testPlanId,jdbcType=VARCHAR},
</if>
<if test="record.runModeConfig != null">
run_mode_config = #{record.runModeConfig,jdbcType=LONGVARBINARY},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExampleWithBLOBs" parameterType="map">
update test_plan_allocation
set id = #{record.id,jdbcType=VARCHAR},
test_plan_id = #{record.testPlanId,jdbcType=VARCHAR},
run_mode_config = #{record.runModeConfig,jdbcType=LONGVARBINARY}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update test_plan_allocation
set id = #{record.id,jdbcType=VARCHAR},
test_plan_id = #{record.testPlanId,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.plan.domain.TestPlanAllocation">
update test_plan_allocation
<set>
<if test="testPlanId != null">
test_plan_id = #{testPlanId,jdbcType=VARCHAR},
</if>
<if test="runModeConfig != null">
run_mode_config = #{runModeConfig,jdbcType=LONGVARBINARY},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.plan.domain.TestPlanAllocation">
update test_plan_allocation
set test_plan_id = #{testPlanId,jdbcType=VARCHAR},
run_mode_config = #{runModeConfig,jdbcType=LONGVARBINARY}
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.plan.domain.TestPlanAllocation">
update test_plan_allocation
set test_plan_id = #{testPlanId,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<insert id="batchInsert" parameterType="map">
insert into test_plan_allocation
(id, test_plan_id, run_mode_config)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.testPlanId,jdbcType=VARCHAR}, #{item.runModeConfig,jdbcType=LONGVARBINARY}
)
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
insert into test_plan_allocation (
<foreach collection="selective" item="column" separator=",">
${column.escapedColumnName}
</foreach>
)
values
<foreach collection="list" item="item" separator=",">
(
<foreach collection="selective" item="column" separator=",">
<if test="'id'.toString() == column.value">
#{item.id,jdbcType=VARCHAR}
</if>
<if test="'test_plan_id'.toString() == column.value">
#{item.testPlanId,jdbcType=VARCHAR}
</if>
<if test="'run_mode_config'.toString() == column.value">
#{item.runModeConfig,jdbcType=LONGVARBINARY}
</if>
</foreach>
)
</foreach>
</insert>
</mapper>

View File

@ -25,6 +25,19 @@ ALTER TABLE test_resource_pool DROP COLUMN api_test;
ALTER TABLE test_resource_pool DROP COLUMN load_test;
ALTER TABLE test_resource_pool DROP COLUMN ui_test;
CREATE TABLE IF NOT EXISTS test_plan_allocation
(
`id` VARCHAR(50) NOT NULL COMMENT 'ID',
`test_plan_id` VARCHAR(50) NOT NULL COMMENT '测试计划ID',
`run_mode_config` LONGBLOB NOT NULL COMMENT '运行配置',
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '测试计划配置';
CREATE INDEX idx_test_plan_id ON test_plan_allocation(test_plan_id);
-- set innodb lock wait timeout to default
SET SESSION innodb_lock_wait_timeout = DEFAULT;

View File

@ -0,0 +1,22 @@
package io.metersphere.system.config.interceptor;
import io.metersphere.plan.domain.TestPlanAllocation;
import io.metersphere.sdk.util.CompressUtils;
import io.metersphere.system.utils.MybatisInterceptorConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class TestPlanInterceptor {
@Bean
public List<MybatisInterceptorConfig> tstPlanCompressConfigs() {
List<MybatisInterceptorConfig> configList = new ArrayList<>();
configList.add(new MybatisInterceptorConfig(TestPlanAllocation.class, "runModeConfig", CompressUtils.class, "zip", "unzip"));
return configList;
}
}

View File

@ -143,4 +143,13 @@ public class TestPlanController {
public TestPlanDetailResponse detail(@NotBlank @PathVariable String id) {
return testPlanService.detail(id);
}
@PostMapping("/batch/copy")
@Operation(summary = "测试计划-批量复制测试计划")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_UPDATE)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public void batchCopy(@Validated @RequestBody TestPlanBatchRequest request) {
testPlanService.batchCopy(request, SessionUtils.getUserId(), "/test-plan/batch/copy", HttpMethodConstants.POST.name());
}
}

View File

@ -0,0 +1,16 @@
package io.metersphere.plan.dto.request;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
/**
* @author wx
*/
@Data
public class TestPlanBatchRequest extends TestPlanBatchProcessRequest{
@Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{test_plan.module_id.not_blank}")
private String moduleId;
}

View File

@ -2,17 +2,10 @@ package io.metersphere.plan.service;
import io.metersphere.plan.domain.*;
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
import io.metersphere.plan.dto.request.TestPlanBatchProcessRequest;
import io.metersphere.plan.dto.request.TestPlanCopyRequest;
import io.metersphere.plan.dto.request.TestPlanCreateRequest;
import io.metersphere.plan.dto.request.TestPlanUpdateRequest;
import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.TestPlanCountResponse;
import io.metersphere.plan.dto.response.TestPlanDetailResponse;
import io.metersphere.plan.mapper.ExtTestPlanMapper;
import io.metersphere.plan.mapper.TestPlanConfigMapper;
import io.metersphere.plan.mapper.TestPlanFollowerMapper;
import io.metersphere.plan.mapper.TestPlanMapper;
import io.metersphere.plan.utils.TestPlanXPackFactory;
import io.metersphere.plan.mapper.*;
import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.TestPlanConstants;
@ -20,7 +13,6 @@ import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.TestPlanModule;
import io.metersphere.system.domain.TestPlanModuleExample;
import io.metersphere.system.mapper.TestPlanModuleMapper;
import io.metersphere.system.uid.IDGenerator;
@ -53,6 +45,8 @@ public class TestPlanService {
private TestPlanFollowerMapper testPlanFollowerMapper;
@Resource
private TestPlanFunctionalCaseService testPlanFunctionCaseService;
@Resource
private TestPlanAllocationMapper testPlanAllocationMapper;
public void checkModule(String moduleId) {
if (!StringUtils.equals(moduleId, ModuleConstants.DEFAULT_NODE_ID)) {
@ -161,7 +155,7 @@ public class TestPlanService {
if (testPlanMapper.countByExample(example) > 0) {
throw new MSException(Translator.get("test_plan.name.exist") + ":" + testPlan.getName());
}
}else{
} else {
//更新 校验
example.createCriteria().andNameEqualTo(testPlan.getName()).andProjectIdEqualTo(testPlan.getProjectId()).andIdNotEqualTo(testPlan.getId()).andModuleIdEqualTo(testPlan.getModuleId());
if (testPlanMapper.countByExample(example) > 0) {
@ -228,32 +222,40 @@ public class TestPlanService {
* @param requestMethod
*/
public void batchDelete(TestPlanBatchProcessRequest request, String operator, String requestUrl, String requestMethod) {
List<String> deleteIdList = request.getSelectIds();
if (request.isSelectAll()) {
deleteIdList = extTestPlanMapper.selectIdByConditions(request);
}
if (CollectionUtils.isEmpty(deleteIdList)) {
return;
}
List<TestPlan> deleteTestPlanList = extTestPlanMapper.selectBaseInfoByIds(deleteIdList);
if (CollectionUtils.isNotEmpty(deleteTestPlanList)) {
List<String> testPlanGroupList = new ArrayList<>();
List<String> testPlanIdList = new ArrayList<>();
for (TestPlan testPlan : deleteTestPlanList) {
if (StringUtils.equals(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
testPlanGroupList.add(testPlan.getId());
} else {
testPlanIdList.add(testPlan.getId());
List<String> deleteIdList = getSelectIds(request);
if (CollectionUtils.isNotEmpty(deleteIdList)) {
List<TestPlan> deleteTestPlanList = extTestPlanMapper.selectBaseInfoByIds(deleteIdList);
if (CollectionUtils.isNotEmpty(deleteTestPlanList)) {
List<String> testPlanGroupList = new ArrayList<>();
List<String> testPlanIdList = new ArrayList<>();
for (TestPlan testPlan : deleteTestPlanList) {
if (StringUtils.equals(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_GROUP)) {
testPlanGroupList.add(testPlan.getId());
} else {
testPlanIdList.add(testPlan.getId());
}
}
this.deleteByList(deleteIdList);
this.deleteGroupByList(testPlanGroupList);
//记录日志
testPlanLogService.saveBatchDeleteLog(deleteTestPlanList, operator, requestUrl, requestMethod);
}
this.deleteByList(deleteIdList);
this.deleteGroupByList(testPlanGroupList);
//记录日志
testPlanLogService.saveBatchDeleteLog(deleteTestPlanList, operator, requestUrl, requestMethod);
}
}
private List<String> getSelectIds(TestPlanBatchProcessRequest request) {
if (request.isSelectAll()) {
List<String> ids = extTestPlanMapper.selectIdByConditions(request);
if (org.apache.commons.collections.CollectionUtils.isNotEmpty(request.getExcludeIds())) {
ids.removeAll(request.getExcludeIds());
}
return ids;
} else {
return request.getSelectIds();
}
}
private void cascadeDeleteTestPlanIds(List<String> testPlanIds) {
//删除当前计划对应的资源
Map<String, TestPlanResourceService> subTypes = CommonBeanFactory.getBeansOfType(TestPlanResourceService.class);
@ -460,12 +462,12 @@ public class TestPlanService {
public TestPlanDetailResponse detail(String id) {
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(id);
TestPlanDetailResponse response = new TestPlanDetailResponse();
TestPlanModule testPlanModule = testPlanModuleMapper.selectByPrimaryKey(testPlan.getModuleId());
String moduleName = getModuleName(testPlan.getModuleId());
//计划组只有几个参数
response.setName(testPlan.getName());
response.setTags(testPlan.getTags());
response.setModuleId(testPlan.getModuleId());
response.setModuleName(testPlanModule.getName());
response.setModuleName(moduleName);
response.setDescription(testPlan.getDescription());
if (StringUtils.equalsIgnoreCase(testPlan.getType(), TestPlanConstants.TEST_PLAN_TYPE_PLAN)) {
//计划的 其他参数
@ -492,4 +494,122 @@ public class TestPlanService {
response.setGroupName(group.getName());
}
}
public String getModuleName(String id) {
if (ModuleConstants.DEFAULT_NODE_ID.equals(id)) {
return Translator.get("functional_case.module.default.name");
}
return testPlanModuleMapper.selectByPrimaryKey(id).getName();
}
/**
* 批量复制 计划/计划组
*
* @param request
* @param userId
* @param url
* @param method
* @return
*/
public void batchCopy(TestPlanBatchRequest request, String userId, String url, String method) {
List<String> copyIds = getSelectIds(request);
if (CollectionUtils.isNotEmpty(copyIds)) {
TestPlanExample example = new TestPlanExample();
example.createCriteria().andIdIn(copyIds);
List<TestPlan> copyTestPlanList = testPlanMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(copyTestPlanList)) {
Map<String, List<TestPlan>> plans = copyTestPlanList.stream().collect(Collectors.groupingBy(TestPlan::getType));
batchCopyGroup(plans, request, userId);
batchCopyPlan(plans, request, userId);
// TODO 日志
}
}
}
/**
* 批量复制计划
*
* @param plans
*/
private void batchCopyPlan(Map<String, List<TestPlan>> plans, TestPlanBatchRequest request, String userId) {
if (plans.containsKey(TestPlanConstants.TEST_PLAN_TYPE_PLAN)) {
List<TestPlan> testPlans = plans.get(TestPlanConstants.TEST_PLAN_TYPE_PLAN);
List<String> ids = testPlans.stream().map(TestPlan::getId).collect(Collectors.toList());
//额外信息
TestPlanConfigExample configExample = new TestPlanConfigExample();
configExample.createCriteria().andTestPlanIdIn(ids);
List<TestPlanConfig> testPlanConfigs = testPlanConfigMapper.selectByExample(configExample);
//测试规划配置信息
TestPlanAllocationExample allocationExample = new TestPlanAllocationExample();
allocationExample.createCriteria().andTestPlanIdIn(ids);
List<TestPlanAllocation> testPlanAllocations = testPlanAllocationMapper.selectByExampleWithBLOBs(allocationExample);
batchInsertPlan(testPlans, testPlanConfigs, testPlanAllocations, request, userId);
}
}
private void batchInsertPlan(List<TestPlan> testPlans, List<TestPlanConfig> testPlanConfigs, List<TestPlanAllocation> testPlanAllocations, TestPlanBatchRequest request, String userId) {
Map<String, List<TestPlanConfig>> configs = testPlanConfigs.stream().collect(Collectors.groupingBy(TestPlanConfig::getTestPlanId));
Map<String, List<TestPlanAllocation>> allocationsList = testPlanAllocations.stream().collect(Collectors.groupingBy(TestPlanAllocation::getTestPlanId));
List<TestPlanConfig> newConfigs = new ArrayList<>();
List<TestPlanAllocation> newAllocations = new ArrayList<>();
testPlans.forEach(testPlan -> {
List<TestPlanConfig> config = configs.get(testPlan.getId());
List<TestPlanAllocation> allocations = allocationsList.get(testPlan.getId());
Long num = testPlan.getNum();
testPlan.setId(IDGenerator.nextStr());
testPlan.setStatus(TestPlanConstants.TEST_PLAN_STATUS_PREPARED);
testPlan.setNum(NumGenerator.nextNum(testPlan.getProjectId(), ApplicationNumScope.TEST_PLAN));
testPlan.setName(getCopyName(testPlan.getName(), num, testPlan.getNum()));
testPlan.setModuleId(request.getModuleId());
testPlan.setCreateTime(System.currentTimeMillis());
testPlan.setUpdateTime(System.currentTimeMillis());
testPlan.setCreateUser(userId);
testPlan.setUpdateUser(userId);
if (CollectionUtils.isNotEmpty(config)) {
TestPlanConfig testPlanConfig = config.get(0);
testPlanConfig.setTestPlanId(testPlan.getId());
newConfigs.add(testPlanConfig);
}
if (CollectionUtils.isNotEmpty(allocations)) {
TestPlanAllocation testPlanAllocation = allocations.get(0);
testPlanAllocation.setTestPlanId(testPlan.getId());
testPlanAllocation.setId(IDGenerator.nextStr());
newAllocations.add(testPlanAllocation);
}
});
testPlanMapper.batchInsert(testPlans);
if (CollectionUtils.isNotEmpty(newConfigs)) {
testPlanConfigMapper.batchInsert(newConfigs);
}
if (CollectionUtils.isNotEmpty(newAllocations)) {
testPlanAllocationMapper.batchInsert(newAllocations);
}
}
private String getCopyName(String name, long oldNum, long newNum) {
if (!StringUtils.startsWith(name, "copy_")) {
name = "copy_" + name;
}
if (name.length() > 250) {
name = name.substring(0, 200) + "...";
}
if (StringUtils.endsWith(name, "_" + oldNum)) {
name = StringUtils.substringBeforeLast(name, "_" + oldNum);
}
name = name + "_" + newNum;
return name;
}
/**
* 批量复制组
*
* @param plans
*/
private void batchCopyGroup(Map<String, List<TestPlan>> plans, TestPlanBatchProcessRequest request, String userId) {
//TODO 批量复制计划组
}
}

View File

@ -123,6 +123,7 @@ public class TestPlanTests extends BaseTest {
private static final String URL_TEST_PLAN_ARCHIVED = "/test-plan/archived/%s";
private static final String URL_TEST_PLAN_COPY = "/test-plan/copy";
private static final String URL_TEST_PLAN_DETAIL = "/test-plan/%s";
private static final String URL_TEST_PLAN_BATCH_COPY = "/test-plan/batch/copy";
private static String groupTestPlanId7 = null;
private static String groupTestPlanId15 = null;
@ -748,7 +749,6 @@ public class TestPlanTests extends BaseTest {
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(result.getList())).size() <= testPlanTableRequest.getPageSize());
//测试根据名称模糊查询 Plan_2 预期结果 a1Node下有11条testPlan_2,testPlan_20~testPlan_29), a1b1Node下有100条testPlan_200~testPlan_299
testPlanTableRequest.setModuleIds(null);
testPlanTableRequest.initKeyword("Plan_2");
@ -767,7 +767,6 @@ public class TestPlanTests extends BaseTest {
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(result.getList())).size() <= testPlanTableRequest.getPageSize());
//测试根据名称模糊查询包含测试组的 Plan_7 预期结果 a1Node下有1条testPlan_7), a2Node下有10条testPlan_70~testPlan_79,a1b1Node下有100条testPlan_700~testPlan_799
testPlanTableRequest.initKeyword("Plan_7");
testPlanTableRequest.setSort(new HashMap<>() {{
@ -2184,4 +2183,18 @@ public class TestPlanTests extends BaseTest {
Assertions.assertNotNull(returnId2);
}
@Test
@Order(304)
public void testBatchCopy() throws Exception {
TestPlanBatchRequest request = new TestPlanBatchRequest();
request.setProjectId("123");
request.setType("ALL");
request.setSelectAll(true);
request.setModuleId("2");
this.requestPostWithOkAndReturn(URL_TEST_PLAN_BATCH_COPY, request);
}
}

View File

@ -25,4 +25,9 @@ VALUES
INSERT INTO project (id, num, organization_id, name, description, create_user, update_user, create_time, update_time, module_setting)
VALUES
('123', 2, 1, 'wx', 'wx', 'admin', 'admin', unix_timestamp() * 1000, unix_timestamp() * 1000,'["bugManagement","caseManagement","apiTest","testPlan"]');
('123', 2, 1, 'wx', 'wx', 'admin', 'admin', unix_timestamp() * 1000, unix_timestamp() * 1000,'["bugManagement","caseManagement","apiTest","testPlan"]');
INSERT INTO `test_plan_allocation`(`id`, `test_plan_id`, `run_mode_config`)
VALUES
('1', 'wx_test_plan_id_1', '111');