feat(功能用例): 用例详情添加前置用例&后置用例
This commit is contained in:
parent
d632b5e6d4
commit
4871c48661
|
@ -165,4 +165,5 @@ case_review.not.exist=Case review does not exist
|
|||
case_review_content.not.exist = Review comments cannot be empty
|
||||
case_review_history.system=System trigger
|
||||
case_review.viewFlag.not_blank=View flag cannot be empty
|
||||
functional_case_relationship_edge.type.not_blank=Relationship type cannot be empty
|
||||
functional_case_relationship_edge.type.not_blank=Relationship type cannot be empty
|
||||
cycle_relationship=There is a circular dependency after association, please check the dependency relationship
|
|
@ -165,3 +165,4 @@ case_review_content.not.exist = 评审意见不能为空
|
|||
case_review_history.system=系统触发
|
||||
case_review.viewFlag.not_blank=查看标识不能为空
|
||||
functional_case_relationship_edge.type.not_blank=类型不能为空
|
||||
cycle_relationship=关联后存在循环依赖,请检查依赖关系
|
||||
|
|
|
@ -165,4 +165,5 @@ case_review.not.exist=用例評審不存在
|
|||
case_review_content.not.exist = 評審意見不能為空
|
||||
case_review_history.system=系統觸發
|
||||
case_review.viewFlag.not_blank=查看標誌不能為空
|
||||
functional_case_relationship_edge.type.not_blank=類型不能為空
|
||||
functional_case_relationship_edge.type.not_blank=類型不能為空
|
||||
cycle_relationship=關聯后存在循環依賴,請檢查依賴關係
|
|
@ -4,6 +4,7 @@ import com.alibaba.excel.util.StringUtils;
|
|||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.functional.dto.FunctionalCasePageDTO;
|
||||
import io.metersphere.functional.request.RelationshipAddRequest;
|
||||
import io.metersphere.functional.request.RelationshipPageRequest;
|
||||
import io.metersphere.functional.service.FunctionalCaseRelationshipEdgeService;
|
||||
import io.metersphere.functional.service.FunctionalCaseService;
|
||||
|
@ -11,9 +12,11 @@ import io.metersphere.sdk.constants.PermissionConstants;
|
|||
import io.metersphere.system.security.CheckOwner;
|
||||
import io.metersphere.system.utils.PageUtils;
|
||||
import io.metersphere.system.utils.Pager;
|
||||
import io.metersphere.system.utils.SessionUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
@ -49,5 +52,16 @@ public class FunctionalCaseRelationshipController {
|
|||
return PageUtils.setPageInfo(page, functionalCaseService.getFunctionalCasePage(request, false));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/add")
|
||||
@Operation(summary = "用例管理-功能用例-用例详情-前后置关系-添加前后置关系")
|
||||
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE)
|
||||
@CheckOwner(resourceId = "#request.getCaseId()", resourceType = "project")
|
||||
public void add(@Validated @RequestBody RelationshipAddRequest request) {
|
||||
List<String> excludeIds = functionalCaseRelationshipEdgeService.getExcludeIds(request.getId());
|
||||
request.setExcludeIds(excludeIds);
|
||||
List<String> ids = functionalCaseService.doSelectIds(request, request.getProjectId());
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
functionalCaseRelationshipEdgeService.add(request, ids, SessionUtils.getUserId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package io.metersphere.functional.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtFunctionalCaseRelationshipEdgeMapper {
|
||||
|
||||
|
||||
List<String> getGraphIds(@Param("ids") List<String> ids);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?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.functional.mapper.ExtFunctionalCaseRelationshipEdgeMapper">
|
||||
|
||||
|
||||
<select id="getGraphIds" resultType="java.lang.String">
|
||||
select distinct graph_id
|
||||
from functional_case_relationship_edge
|
||||
where source_id in
|
||||
<foreach collection="ids" item="id" open="(" close=")" separator=",">
|
||||
#{id}
|
||||
</foreach>
|
||||
or target_id in
|
||||
<foreach collection="ids" item="id" open="(" close=")" separator=",">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
|
@ -1,7 +1,7 @@
|
|||
package io.metersphere.functional.request;
|
||||
|
||||
|
||||
import io.metersphere.system.dto.table.TableBatchProcessDTO;
|
||||
import io.metersphere.functional.dto.BaseFunctionalCaseBatchDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
@ -10,7 +10,7 @@ import lombok.Data;
|
|||
* @author wx
|
||||
*/
|
||||
@Data
|
||||
public class RelationshipAddRequest extends TableBatchProcessDTO {
|
||||
public class RelationshipAddRequest extends BaseFunctionalCaseBatchDTO {
|
||||
|
||||
@Schema(description = "用例id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{functional_case.id.not_blank}")
|
||||
|
|
|
@ -9,11 +9,24 @@ package io.metersphere.functional.service;
|
|||
|
||||
import io.metersphere.functional.domain.FunctionalCaseRelationshipEdge;
|
||||
import io.metersphere.functional.domain.FunctionalCaseRelationshipEdgeExample;
|
||||
import io.metersphere.functional.mapper.ExtFunctionalCaseRelationshipEdgeMapper;
|
||||
import io.metersphere.functional.mapper.FunctionalCaseRelationshipEdgeMapper;
|
||||
import io.metersphere.functional.request.RelationshipAddRequest;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
|
@ -22,6 +35,10 @@ public class FunctionalCaseRelationshipEdgeService {
|
|||
|
||||
@Resource
|
||||
private FunctionalCaseRelationshipEdgeMapper functionalCaseRelationshipEdgeMapper;
|
||||
@Resource
|
||||
private ExtFunctionalCaseRelationshipEdgeMapper extFunctionalCaseRelationshipEdgeMapper;
|
||||
@Resource
|
||||
SqlSessionFactory sqlSessionFactory;
|
||||
|
||||
|
||||
public List<String> getExcludeIds(String id) {
|
||||
|
@ -43,4 +60,163 @@ public class FunctionalCaseRelationshipEdgeService {
|
|||
return functionalCaseRelationshipEdgeMapper.selectByExample(example);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加前后置用例
|
||||
*
|
||||
* @param request request
|
||||
* @param ids ids
|
||||
*/
|
||||
public void add(RelationshipAddRequest request, List<String> ids, String userId) {
|
||||
List<FunctionalCaseRelationshipEdge> edgeList = getExistRelationshipEdges(ids, request.getId());
|
||||
Set<String> addEdgesIds = new HashSet<>();
|
||||
String graphId = IDGenerator.nextStr();
|
||||
switch (request.getType()) {
|
||||
case "PRE":
|
||||
addPre(request, ids, userId, edgeList, addEdgesIds, graphId);
|
||||
break;
|
||||
case "POST":
|
||||
addPost(request, ids, userId, edgeList, addEdgesIds, graphId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
HashSet<String> nodeIds = new HashSet<>();
|
||||
nodeIds.addAll(edgeList.stream().map(FunctionalCaseRelationshipEdge::getSourceId).collect(Collectors.toSet()));
|
||||
nodeIds.addAll(edgeList.stream().map(FunctionalCaseRelationshipEdge::getTargetId).collect(Collectors.toSet()));
|
||||
// 判断是否有环
|
||||
HashSet<String> visitedSet = new HashSet<>();
|
||||
nodeIds.forEach(nodeId -> {
|
||||
if (!visitedSet.contains(nodeId) && directedCycle(nodeId, edgeList, new HashSet<>(), visitedSet)) {
|
||||
throw new MSException(Translator.get("cycle_relationship"));
|
||||
}
|
||||
;
|
||||
});
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
FunctionalCaseRelationshipEdgeMapper batchMapper = sqlSession.getMapper(FunctionalCaseRelationshipEdgeMapper.class);
|
||||
|
||||
edgeList.forEach(item -> {
|
||||
if (addEdgesIds.contains(item.getSourceId() + item.getTargetId())) {
|
||||
if (batchMapper.selectByPrimaryKey(item.getId()) == null) {
|
||||
batchMapper.insert(item);
|
||||
} else {
|
||||
item.setGraphId(graphId); // 把原来图的id设置成合并后新的图的id
|
||||
batchMapper.updateByPrimaryKey(item);
|
||||
}
|
||||
} else {
|
||||
item.setGraphId(graphId); // 把原来图的id设置成合并后新的图的id
|
||||
batchMapper.updateByPrimaryKey(item);
|
||||
}
|
||||
});
|
||||
sqlSession.flushStatements();
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加后置用例
|
||||
*
|
||||
* @param request
|
||||
* @param ids
|
||||
* @param userId
|
||||
* @param edgeList
|
||||
* @param addEdgesIds
|
||||
* @param graphId
|
||||
*/
|
||||
private void addPost(RelationshipAddRequest request, List<String> ids, String userId, List<FunctionalCaseRelationshipEdge> edgeList, Set<String> addEdgesIds, String graphId) {
|
||||
ids.forEach(sourceId -> {
|
||||
FunctionalCaseRelationshipEdge edge = createRelationshipEdge(sourceId, request.getId(), graphId, userId);
|
||||
edgeList.add(edge);
|
||||
addEdgesIds.add(edge.getSourceId() + edge.getTargetId());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 给定一点,深度搜索该连通图中是否存在环
|
||||
*
|
||||
* @param id
|
||||
* @param edges
|
||||
* @param markSet 标记该路径上经过的节点
|
||||
* @param visitedSet 标记访问过的节点
|
||||
* @return
|
||||
*/
|
||||
public boolean directedCycle(String id, List<FunctionalCaseRelationshipEdge> edges, Set<String> markSet, Set<String> visitedSet) {
|
||||
|
||||
if (markSet.contains(id)) {
|
||||
// 如果已经访问过该节点,则说明存在环
|
||||
return true;
|
||||
}
|
||||
|
||||
markSet.add(id);
|
||||
visitedSet.add(id);
|
||||
|
||||
ArrayList<String> nextLevelNodes = new ArrayList();
|
||||
for (FunctionalCaseRelationshipEdge relationshipEdge : edges) {
|
||||
if (id.equals(relationshipEdge.getSourceId())) {
|
||||
nextLevelNodes.add(relationshipEdge.getTargetId());
|
||||
}
|
||||
}
|
||||
|
||||
for (String nextNode : nextLevelNodes) {
|
||||
if (directedCycle(nextNode, edges, markSet, visitedSet)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 关键,递归完这一条路径要把这个标记去掉,否则会误判为有环
|
||||
// 比如 1->3, 1->2->3 , 3 经过多次但是无环
|
||||
markSet.remove(id);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已经存在的依赖关系图
|
||||
*
|
||||
* @param ids
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
private List<FunctionalCaseRelationshipEdge> getExistRelationshipEdges(List<String> ids, String id) {
|
||||
List<String> graphNodes = new ArrayList<>();
|
||||
graphNodes.add(id);
|
||||
graphNodes.addAll(ids);
|
||||
List<String> graphIds = extFunctionalCaseRelationshipEdgeMapper.getGraphIds(graphNodes);
|
||||
if (CollectionUtils.isEmpty(graphIds)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
FunctionalCaseRelationshipEdgeExample example = new FunctionalCaseRelationshipEdgeExample();
|
||||
example.createCriteria()
|
||||
.andGraphIdIn(graphIds);
|
||||
|
||||
return functionalCaseRelationshipEdgeMapper.selectByExample(example);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加前置用例
|
||||
*
|
||||
* @param request request
|
||||
* @param ids ids
|
||||
*/
|
||||
private void addPre(RelationshipAddRequest request, List<String> ids, String userId, List<FunctionalCaseRelationshipEdge> edgeList, Set<String> addEdgesIds, String graphId) {
|
||||
ids.forEach(targetId -> {
|
||||
FunctionalCaseRelationshipEdge edge = createRelationshipEdge(request.getId(), targetId, graphId, userId);
|
||||
edgeList.add(edge);
|
||||
addEdgesIds.add(edge.getSourceId() + edge.getTargetId());
|
||||
});
|
||||
}
|
||||
|
||||
private FunctionalCaseRelationshipEdge createRelationshipEdge(String sourceId, String targetId, String graphId, String userId) {
|
||||
FunctionalCaseRelationshipEdge edge = new FunctionalCaseRelationshipEdge();
|
||||
edge.setId(IDGenerator.nextStr());
|
||||
edge.setSourceId(sourceId);
|
||||
edge.setTargetId(targetId);
|
||||
edge.setGraphId(graphId);
|
||||
edge.setCreateUser(userId);
|
||||
edge.setCreateTime(System.currentTimeMillis());
|
||||
edge.setUpdateTime(System.currentTimeMillis());
|
||||
return edge;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
package io.metersphere.functional.controller;
|
||||
|
||||
import io.metersphere.functional.request.RelationshipAddRequest;
|
||||
import io.metersphere.functional.request.RelationshipPageRequest;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.base.BaseTest;
|
||||
import io.metersphere.system.controller.handler.ResultHolder;
|
||||
import io.metersphere.system.controller.handler.result.MsHttpResultCode;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
@ -13,6 +15,7 @@ import org.springframework.test.web.servlet.MvcResult;
|
|||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
|
@ -20,6 +23,7 @@ import java.util.HashMap;
|
|||
public class FunctionalCaseRelationshipControllerTests extends BaseTest {
|
||||
|
||||
public static final String RELATE_PAGE = "/functional/case/relationship/relate/page";
|
||||
public static final String ADD = "/functional/case/relationship/add";
|
||||
|
||||
|
||||
@Test
|
||||
|
@ -44,4 +48,41 @@ public class FunctionalCaseRelationshipControllerTests extends BaseTest {
|
|||
}});
|
||||
this.requestPostWithOkAndReturn(RELATE_PAGE, request);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
public void testAddRelationship() throws Exception {
|
||||
//前置用例
|
||||
RelationshipAddRequest request = new RelationshipAddRequest();
|
||||
request.setId("wx_relationship_1");
|
||||
request.setProjectId("wx_relationship");
|
||||
request.setType("PRE");
|
||||
request.setSelectIds(List.of("wx_relationship_3"));
|
||||
MvcResult mvcResult = this.requestPostWithOkAndReturn(ADD, request);
|
||||
// 获取返回值
|
||||
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
// 返回请求正常
|
||||
Assertions.assertNotNull(resultHolder);
|
||||
|
||||
//测试依赖关系 形成环
|
||||
request.setId("wx_relationship_3");
|
||||
request.setProjectId("wx_relationship");
|
||||
request.setType("PRE");
|
||||
request.setSelectIds(List.of("wx_relationship_1"));
|
||||
assertErrorCode(this.requestPost(ADD, request), MsHttpResultCode.FAILED);
|
||||
|
||||
//后置用例
|
||||
request.setId("wx_relationship_4");
|
||||
request.setType("POST");
|
||||
request.setSelectIds(List.of("wx_relationship_5"));
|
||||
MvcResult postResult = this.requestPostWithOkAndReturn(ADD, request);
|
||||
// 获取返回值
|
||||
String postReturnData = postResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder postResultHolder = JSON.parseObject(postReturnData, ResultHolder.class);
|
||||
// 返回请求正常
|
||||
Assertions.assertNotNull(postResultHolder);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue