feat(测试计划): 新增测试计划功能用例脑图

This commit is contained in:
guoyuqi 2024-07-25 11:26:15 +08:00 committed by 刘瑞斌
parent f9a2ebce22
commit 134d8b09eb
8 changed files with 98 additions and 14 deletions

View File

@ -98,6 +98,7 @@ minder_extra_node.module=模块
minder_extra_node.prerequisite=前置条件 minder_extra_node.prerequisite=前置条件
minder_extra_node.steps=步骤描述 minder_extra_node.steps=步骤描述
minder_extra_node.steps_expected_result=预期结果 minder_extra_node.steps_expected_result=预期结果
minder_extra_node.steps_actual_result=实际结果
minder_extra_node.text_description=文本描述 minder_extra_node.text_description=文本描述
minder_extra_node.text_expected_result=预期结果 minder_extra_node.text_expected_result=预期结果
minder_extra_node.description=备注信息 minder_extra_node.description=备注信息
@ -169,3 +170,8 @@ case_review_user=您没有评审权限
#minder #minder
case.minder.all.case=全部用例 case.minder.all.case=全部用例
case.minder.status.success=成功
case.minder.status.error=失败
case.minder.status.blocked=阻塞

View File

@ -134,6 +134,7 @@ minder_extra_node.module=Module
minder_extra_node.prerequisite=Prerequisite minder_extra_node.prerequisite=Prerequisite
minder_extra_node.steps=Steps minder_extra_node.steps=Steps
minder_extra_node.steps_expected_result=ExpectedResult minder_extra_node.steps_expected_result=ExpectedResult
minder_extra_node.steps_actual_result=ActualResult
minder_extra_node.text_description=TextDescription minder_extra_node.text_description=TextDescription
minder_extra_node.text_expected_result=ExpectedResult minder_extra_node.text_expected_result=ExpectedResult
minder_extra_node.description=Description minder_extra_node.description=Description
@ -241,4 +242,8 @@ functional_case_relationship_edge.type.not_blank=Relationship type cannot be emp
cycle_relationship=There is a circular dependency after association, please check the dependency relationship cycle_relationship=There is a circular dependency after association, please check the dependency relationship
case_review_user=You do not have review permission case_review_user=You do not have review permission
#minder #minder
case.minder.all.case=All Case case.minder.all.case=All Case
case.minder.status.success=success
case.minder.status.error=error
case.minder.status.blocked=blocked

View File

@ -133,6 +133,7 @@ minder_extra_node.module=模块
minder_extra_node.prerequisite=前置条件 minder_extra_node.prerequisite=前置条件
minder_extra_node.steps=步骤描述 minder_extra_node.steps=步骤描述
minder_extra_node.steps_expected_result=预期结果 minder_extra_node.steps_expected_result=预期结果
minder_extra_node.steps_actual_result=实际结果
minder_extra_node.text_description=文本描述 minder_extra_node.text_description=文本描述
minder_extra_node.text_expected_result=预期结果 minder_extra_node.text_expected_result=预期结果
minder_extra_node.description=备注信息 minder_extra_node.description=备注信息
@ -240,3 +241,8 @@ cycle_relationship=关联后存在循环依赖,请检查依赖关系
case_review_user=您没有评审权限 case_review_user=您没有评审权限
#minder #minder
case.minder.all.case=全部用例 case.minder.all.case=全部用例
case.minder.status.success=成功
case.minder.status.error=失败
case.minder.status.blocked=阻塞

View File

@ -134,6 +134,7 @@ minder_extra_node.module=模塊
minder_extra_node.prerequisite=前置條件 minder_extra_node.prerequisite=前置條件
minder_extra_node.steps=步驟描述 minder_extra_node.steps=步驟描述
minder_extra_node.steps_expected_result=預期結果 minder_extra_node.steps_expected_result=預期結果
minder_extra_node.steps_actual_result=實際結果
minder_extra_node.text_description=文字描述 minder_extra_node.text_description=文字描述
minder_extra_node.text_expected_result=預期結果 minder_extra_node.text_expected_result=預期結果
minder_extra_node.description=備註資訊 minder_extra_node.description=備註資訊
@ -241,3 +242,8 @@ cycle_relationship=關聯后存在循環依賴,請檢查依賴關係
case_review_user=您沒有評審權限 case_review_user=您沒有評審權限
#minder #minder
case.minder.all.case=全部用例 case.minder.all.case=全部用例
case.minder.status.success=成功
case.minder.status.error=失敗
case.minder.status.blocked=阻塞

View File

@ -880,12 +880,12 @@
fc.name as name, fc.name as name,
fc.id as caseId, fc.id as caseId,
fc.project_id, fc.template_id, fc.review_status, fc.pos, fc.case_edit_type, fc.project_id, fc.template_id, fc.review_status, fc.pos, fc.case_edit_type,
fcb.steps, fcb.text_description, fcb.expected_result, fcb.prerequisite, fcb.description IFNULL(history.`steps`, fcb.steps) as steps, fcb.text_description, fcb.expected_result, fcb.prerequisite, fcb.description
FROM FROM
test_plan_functional_case tpfc test_plan_functional_case tpfc
LEFT JOIN functional_case fc ON tpfc.functional_case_id = fc.id LEFT JOIN functional_case fc ON tpfc.functional_case_id = fc.id
LEFT JOIN functional_case_blob fcb ON fcb.id = fc.id LEFT JOIN functional_case_blob fcb ON fcb.id = fc.id
LEFT JOIN ( SELECT GROUP_CONCAT(DISTINCT tpceh.test_plan_case_id) AS test_plan_case_id, tpceh.`status` from test_plan_case_execute_history tpceh where tpceh.test_plan_id = #{request.planId} LEFT JOIN ( SELECT GROUP_CONCAT(DISTINCT tpceh.test_plan_case_id) AS test_plan_case_id, tpceh.`status`, tpceh.`steps` from test_plan_case_execute_history tpceh where tpceh.test_plan_id = #{request.planId}
GROUP BY test_plan_case_id order by tpceh.create_time desc ) as history ON history.test_plan_case_id = tpfc.id GROUP BY test_plan_case_id order by tpceh.create_time desc ) as history ON history.test_plan_case_id = tpfc.id
WHERE WHERE
tpfc.test_plan_id = #{request.planId} tpfc.test_plan_id = #{request.planId}

View File

@ -11,10 +11,7 @@ import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.project.service.ProjectTemplateService; import io.metersphere.project.service.ProjectTemplateService;
import io.metersphere.project.utils.NodeSortUtils; import io.metersphere.project.utils.NodeSortUtils;
import io.metersphere.sdk.constants.ExecStatus; import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.TemplateScene;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
@ -141,7 +138,7 @@ public class FunctionalCaseMinderService {
Map<String, String> priorityMap = caseCustomFieldList.stream().collect(Collectors.toMap(FunctionalCaseCustomField::getCaseId, FunctionalCaseCustomField::getValue)); Map<String, String> priorityMap = caseCustomFieldList.stream().collect(Collectors.toMap(FunctionalCaseCustomField::getCaseId, FunctionalCaseCustomField::getValue));
//构造父子级数据 //构造父子级数据
buildList(functionalCaseMindDTOList, list, priorityMap); buildList(functionalCaseMindDTOList, list, priorityMap, false);
return list; return list;
} }
@ -152,7 +149,7 @@ public class FunctionalCaseMinderService {
return customFields.stream().map(TemplateCustomFieldDTO::getFieldId).toList(); return customFields.stream().map(TemplateCustomFieldDTO::getFieldId).toList();
} }
private void buildList(List<FunctionalCaseMindDTO> functionalCaseMindDTOList, List<FunctionalMinderTreeDTO> list, Map<String, String> priorityMap) { private void buildList(List<FunctionalCaseMindDTO> functionalCaseMindDTOList, List<FunctionalMinderTreeDTO> list, Map<String, String> priorityMap, boolean addActualResult) {
//构造父子级数据 //构造父子级数据
for (FunctionalCaseMindDTO functionalCaseMindDTO : functionalCaseMindDTOList) { for (FunctionalCaseMindDTO functionalCaseMindDTO : functionalCaseMindDTOList) {
FunctionalMinderTreeDTO root = new FunctionalMinderTreeDTO(); FunctionalMinderTreeDTO root = new FunctionalMinderTreeDTO();
@ -164,14 +161,14 @@ public class FunctionalCaseMinderService {
rootData.setPriority(StringUtils.isNotBlank(priorityMap.get(functionalCaseMindDTO.getCaseId())) ? Integer.parseInt(priorityMap.get(functionalCaseMindDTO.getCaseId()).substring(1)) + 1 : 1); rootData.setPriority(StringUtils.isNotBlank(priorityMap.get(functionalCaseMindDTO.getCaseId())) ? Integer.parseInt(priorityMap.get(functionalCaseMindDTO.getCaseId()).substring(1)) + 1 : 1);
rootData.setStatus(functionalCaseMindDTO.getReviewStatus()); rootData.setStatus(functionalCaseMindDTO.getReviewStatus());
rootData.setResource(List.of(Translator.get("minder_extra_node.case"))); rootData.setResource(List.of(Translator.get("minder_extra_node.case")));
List<FunctionalMinderTreeDTO> children = buildChildren(functionalCaseMindDTO); List<FunctionalMinderTreeDTO> children = buildChildren(functionalCaseMindDTO, addActualResult);
root.setChildren(children); root.setChildren(children);
root.setData(rootData); root.setData(rootData);
list.add(root); list.add(root);
} }
} }
private List<FunctionalMinderTreeDTO> buildChildren(FunctionalCaseMindDTO functionalCaseMindDTO) { private List<FunctionalMinderTreeDTO> buildChildren(FunctionalCaseMindDTO functionalCaseMindDTO, boolean addActualResult) {
List<FunctionalMinderTreeDTO> children = new ArrayList<>(); List<FunctionalMinderTreeDTO> children = new ArrayList<>();
if (functionalCaseMindDTO.getPrerequisite() != null) { if (functionalCaseMindDTO.getPrerequisite() != null) {
String prerequisiteText = new String(functionalCaseMindDTO.getPrerequisite(), StandardCharsets.UTF_8); String prerequisiteText = new String(functionalCaseMindDTO.getPrerequisite(), StandardCharsets.UTF_8);
@ -216,6 +213,27 @@ public class FunctionalCaseMinderService {
} else { } else {
expectedResultFunctionalMinderTreeDTO = getFunctionalMinderTreeDTO(result, Translator.get("minder_extra_node.steps_expected_result"), Long.valueOf(functionalCaseStepDTO.getNum())); expectedResultFunctionalMinderTreeDTO = getFunctionalMinderTreeDTO(result, Translator.get("minder_extra_node.steps_expected_result"), Long.valueOf(functionalCaseStepDTO.getNum()));
} }
if (addActualResult) {
Map<String, String>statusMap = new HashMap<>();
statusMap.put(ResultStatus.SUCCESS.name(), Translator.get("case.minder.status.success"));
statusMap.put(ResultStatus.ERROR.name(), Translator.get("case.minder.status.error"));
statusMap.put(ResultStatus.BLOCKED.name(), Translator.get("case.minder.status.blocked"));
String actualResult = "";
FunctionalMinderTreeDTO actualResultFunctionalMinderTreeDTO;
if (StringUtils.isNotBlank(functionalCaseStepDTO.getActualResult())) {
actualResult = functionalCaseStepDTO.getActualResult();
actualResultFunctionalMinderTreeDTO = getFunctionalMinderTreeDTO(actualResult, Translator.get("minder_extra_node.steps_actual_result"), Long.valueOf(functionalCaseStepDTO.getNum()));
} else {
actualResultFunctionalMinderTreeDTO = getFunctionalMinderTreeDTO(actualResult, Translator.get("minder_extra_node.steps_actual_result"), Long.valueOf(functionalCaseStepDTO.getNum()));
}
expectedResultFunctionalMinderTreeDTO.getChildren().add(actualResultFunctionalMinderTreeDTO);
if (StringUtils.isNotBlank(functionalCaseStepDTO.getExecuteResult())) {
List<String> resource = stepFunctionalMinderTreeDTO.getData().getResource();
List<String> list = new ArrayList<>(resource);
list.add(statusMap.get(functionalCaseStepDTO.getExecuteResult()));
stepFunctionalMinderTreeDTO.getData().setResource(list);
}
}
stepFunctionalMinderTreeDTO.getChildren().add(expectedResultFunctionalMinderTreeDTO); stepFunctionalMinderTreeDTO.getChildren().add(expectedResultFunctionalMinderTreeDTO);
if (StringUtils.isNotBlank(desc) || StringUtils.isNotBlank(result)) { if (StringUtils.isNotBlank(desc) || StringUtils.isNotBlank(result)) {
children.add(stepFunctionalMinderTreeDTO); children.add(stepFunctionalMinderTreeDTO);
@ -1173,7 +1191,7 @@ public class FunctionalCaseMinderService {
List<FunctionalCaseCustomField> caseCustomFieldList = extFunctionalCaseMapper.getCaseCustomFieldList(request, deleted, fieldIds); List<FunctionalCaseCustomField> caseCustomFieldList = extFunctionalCaseMapper.getCaseCustomFieldList(request, deleted, fieldIds);
Map<String, String> priorityMap = caseCustomFieldList.stream().collect(Collectors.toMap(FunctionalCaseCustomField::getCaseId, FunctionalCaseCustomField::getValue)); Map<String, String> priorityMap = caseCustomFieldList.stream().collect(Collectors.toMap(FunctionalCaseCustomField::getCaseId, FunctionalCaseCustomField::getValue));
//构造父子级数据 //构造父子级数据
buildList(functionalCaseMindDTOList, list, priorityMap); buildList(functionalCaseMindDTOList, list, priorityMap, false);
return list; return list;
} }
@ -1185,7 +1203,7 @@ public class FunctionalCaseMinderService {
List<FunctionalCaseCustomField> caseCustomFieldList = extFunctionalCaseMapper.getCaseCustomFieldList(request, deleted, fieldIds); List<FunctionalCaseCustomField> caseCustomFieldList = extFunctionalCaseMapper.getCaseCustomFieldList(request, deleted, fieldIds);
Map<String, String> priorityMap = caseCustomFieldList.stream().collect(Collectors.toMap(FunctionalCaseCustomField::getCaseId, FunctionalCaseCustomField::getValue)); Map<String, String> priorityMap = caseCustomFieldList.stream().collect(Collectors.toMap(FunctionalCaseCustomField::getCaseId, FunctionalCaseCustomField::getValue));
//构造父子级数据 //构造父子级数据
buildList(functionalCaseMindDTOList, list, priorityMap); buildList(functionalCaseMindDTOList, list, priorityMap, true);
return list; return list;
} }

View File

@ -1,14 +1,20 @@
package io.metersphere.functional.controller; package io.metersphere.functional.controller;
import io.metersphere.functional.domain.*; import io.metersphere.functional.domain.*;
import io.metersphere.functional.dto.*; import io.metersphere.functional.dto.CaseCustomFieldDTO;
import io.metersphere.functional.dto.FunctionalCaseStepDTO;
import io.metersphere.functional.dto.FunctionalMinderTreeDTO;
import io.metersphere.functional.dto.MinderOptionDTO;
import io.metersphere.functional.mapper.*; import io.metersphere.functional.mapper.*;
import io.metersphere.functional.request.*; import io.metersphere.functional.request.*;
import io.metersphere.plan.domain.TestPlanCaseExecuteHistory;
import io.metersphere.plan.mapper.TestPlanCaseExecuteHistoryMapper;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.base.BaseTest; import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder; import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.dto.sdk.BaseTreeNode; import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.Pager; import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
@ -57,6 +63,8 @@ public class FunctionalCaseMinderControllerTest extends BaseTest {
private MindAdditionalNodeMapper mindAdditionalNodeMapper; private MindAdditionalNodeMapper mindAdditionalNodeMapper;
@Resource @Resource
private FunctionalCaseCustomFieldMapper functionalCaseCustomFieldMapper; private FunctionalCaseCustomFieldMapper functionalCaseCustomFieldMapper;
@Resource
private TestPlanCaseExecuteHistoryMapper testPlanCaseExecuteHistoryMapper;
@Test @Test
@Order(1) @Order(1)
@ -410,12 +418,46 @@ public class FunctionalCaseMinderControllerTest extends BaseTest {
request.setModuleId("TEST_MINDER_MODULE_ID_GYQ4"); request.setModuleId("TEST_MINDER_MODULE_ID_GYQ4");
request.setPlanId("TEST_MINDER_PLAN_ID_1"); request.setPlanId("TEST_MINDER_PLAN_ID_1");
request.setCurrent(1); request.setCurrent(1);
TestPlanCaseExecuteHistory executeHistory = new TestPlanCaseExecuteHistory();
String nextStr = IDGenerator.nextStr();
executeHistory.setId(nextStr);
executeHistory.setTestPlanCaseId("test_plan_functional_case_minder_id1");
executeHistory.setTestPlanId("TEST_MINDER_PLAN_ID_1");
executeHistory.setCaseId("TEST_FUNCTIONAL_MINDER_CASE_ID_5");
executeHistory.setStatus("SUCCESS");
List<FunctionalCaseStepDTO> list = new ArrayList<>();
FunctionalCaseStepDTO functionalCaseStepDTO = new FunctionalCaseStepDTO();
functionalCaseStepDTO.setId("12455");
functionalCaseStepDTO.setNum(0);
functionalCaseStepDTO.setDesc("ddd");
functionalCaseStepDTO.setResult("步骤一结果");
functionalCaseStepDTO.setActualResult("实际结果");
functionalCaseStepDTO.setExecuteResult("SUCCESS");
list.add(functionalCaseStepDTO);
functionalCaseStepDTO = new FunctionalCaseStepDTO();
functionalCaseStepDTO.setId("12ddd455");
functionalCaseStepDTO.setNum(1);
functionalCaseStepDTO.setDesc("步骤二");
functionalCaseStepDTO.setResult("fff");
functionalCaseStepDTO.setActualResult("实际结果二");
functionalCaseStepDTO.setExecuteResult("BLOCKED");
list.add(functionalCaseStepDTO);
executeHistory.setSteps(JSON.toJSONString(list).getBytes(StandardCharsets.UTF_8));
executeHistory.setDeleted(false);
executeHistory.setNotifier("admin");
executeHistory.setCreateUser("admin");
executeHistory.setCreateTime(System.currentTimeMillis());
testPlanCaseExecuteHistoryMapper.insert(executeHistory);
TestPlanCaseExecuteHistory testPlanCaseExecuteHistory = testPlanCaseExecuteHistoryMapper.selectByPrimaryKey(nextStr);
Assertions.assertNotNull(testPlanCaseExecuteHistory);
String prerequisiteText = new String(testPlanCaseExecuteHistory.getSteps(), StandardCharsets.UTF_8);
MvcResult mvcResultPage = this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_PLAN_LIST_URL, request); MvcResult mvcResultPage = this.requestPostWithOkAndReturn(FUNCTIONAL_CASE_PLAN_LIST_URL, request);
Pager<List<FunctionalMinderTreeDTO>> tableData = JSON.parseObject(JSON.toJSONString( Pager<List<FunctionalMinderTreeDTO>> tableData = JSON.parseObject(JSON.toJSONString(
JSON.parseObject(mvcResultPage.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()), JSON.parseObject(mvcResultPage.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()),
Pager.class); Pager.class);
Assertions.assertNotNull(tableData.getList()); Assertions.assertNotNull(tableData.getList());
Assertions.assertEquals(2, tableData.getList().size()); Assertions.assertEquals(2, tableData.getList().size());
// System.out.println(JSON.toJSONString(tableData.getList()));
} }
} }

View File

@ -22,6 +22,7 @@ VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_1', 1, 'TEST_MINDER_MODULE_ID_GYQ', 'pro
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_1', NULL, NULL, NULL, NULL, NULL); INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_1', NULL, NULL, NULL, NULL, NULL);
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_3', NULL, NULL, NULL, NULL, NULL); INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_3', NULL, NULL, NULL, NULL, NULL);
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_5', NULL, NULL, NULL, NULL, NULL);
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_6', NULL, NULL, NULL, NULL, NULL); INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('TEST_FUNCTIONAL_MINDER_CASE_ID_6', NULL, NULL, NULL, NULL, NULL);