feat(测试计划): 测试计划详情用例批量创建缺陷

This commit is contained in:
WangXu10 2024-08-26 16:35:15 +08:00 committed by 刘瑞斌
parent bd4d0f02e9
commit 6294eb6f47
5 changed files with 184 additions and 2 deletions

View File

@ -2,6 +2,9 @@ package io.metersphere.plan.controller;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.bug.domain.Bug;
import io.metersphere.bug.dto.request.BugEditRequest;
import io.metersphere.bug.service.BugService;
import io.metersphere.dto.BugProviderDTO;
import io.metersphere.plan.constants.TestPlanResourceConfig;
import io.metersphere.plan.dto.request.*;
@ -14,6 +17,7 @@ import io.metersphere.request.AssociateBugPageRequest;
import io.metersphere.request.BugPageProviderRequest;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.system.dto.LogInsertModule;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.dto.user.UserDTO;
@ -32,6 +36,7 @@ import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.Collections;
import java.util.List;
@ -48,6 +53,8 @@ public class TestPlanFunctionalCaseController {
private TestPlanManagementService testPlanManagementService;
@Resource
private TestPlanFunctionalCaseService testPlanFunctionalCaseService;
@Resource
private BugService bugService;
@PostMapping(value = "/sort")
@Operation(summary = "测试计划功能用例-功能用例拖拽排序")
@ -201,4 +208,19 @@ public class TestPlanFunctionalCaseController {
public void batchMove(@Validated @RequestBody BaseBatchMoveRequest request) {
testPlanFunctionalCaseService.batchMove(request);
}
@PostMapping("/batch/add-bug")
@Operation(summary = "测试计划-计划详情-功能用例-批量添加缺陷")
@RequiresPermissions(PermissionConstants.TEST_PLAN_READ_EXECUTE)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public void batchAddBug(@Validated @RequestPart("request") TestPlanCaseBatchAddBugRequest request,
@RequestPart(value = "files", required = false) List<MultipartFile> files) {
BugEditRequest bugEditRequest = new BugEditRequest();
BeanUtils.copyBean(bugEditRequest, request);
Bug bug = bugService.addOrUpdate(bugEditRequest, files, SessionUtils.getUserId(), SessionUtils.getCurrentOrganizationId(), false);
testPlanFunctionalCaseService.batchAssociateBug(request, bug.getId(), SessionUtils.getUserId());
}
}

View File

@ -0,0 +1,63 @@
package io.metersphere.plan.dto.request;
import io.metersphere.bug.dto.response.BugCustomFieldDTO;
import io.metersphere.bug.dto.response.BugFileDTO;
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 lombok.Data;
import java.util.List;
/**
* @author wx
*/
@Data
public class TestPlanCaseBatchAddBugRequest extends BasePlanCaseBatchRequest {
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{bug.id.not_blank}", groups = {Updated.class})
@Size(min = 1, max = 50, message = "{bug.id.length_range}", groups = {Created.class, Updated.class})
private String id;
@Schema(description = "缺陷标题")
@Size(min = 1, max = 255, message = "{bug.title.length_range}", groups = {Created.class, Updated.class})
private String title;
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{bug.project_id.not_blank}", groups = {Created.class, Updated.class})
@Size(min = 1, max = 50, message = "{bug.project_id.length_range}", groups = {Created.class, Updated.class})
private String projectId;
@Schema(description = "模板ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{bug.template_id.not_blank}", groups = {Created.class, Updated.class})
@Size(min = 1, max = 50, message = "{bug.template_id.length_range}", groups = {Created.class, Updated.class})
private String templateId;
@Schema(description = "标签")
private List<String> tags;
@Schema(description = "缺陷内容")
private String description;
@Schema(description = "自定义字段集合")
private List<BugCustomFieldDTO> customFields;
@Schema(description = "删除的本地附件集合, {文件ID")
private List<String> deleteLocalFileIds;
@Schema(description = "取消关联附件关系ID集合, 关联关系ID")
private List<String> unLinkRefIds;
@Schema(description = "关联附件集合, 文件ID")
private List<String> linkFileIds;
@Schema(description = "复制的附件")
private List<BugFileDTO> copyFiles;
@Schema(description = "富文本临时文件ID")
private List<String> richTextTmpFileIds;
}

View File

@ -723,7 +723,7 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
public TestPlanCaseDetailResponse getFunctionalCaseDetail(String id, String userId) {
TestPlanFunctionalCase planFunctionalCase = testPlanFunctionalCaseMapper.selectByPrimaryKey(id);
if(planFunctionalCase == null){
if (planFunctionalCase == null) {
throw new MSException(Translator.get("resource_not_exist"));
}
String caseId = planFunctionalCase.getFunctionalCaseId();
@ -996,6 +996,7 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
/**
* 处理执行人为空过滤参数
*
* @param request 请求参数
*/
protected void filterCaseRequest(TestPlanCaseRequest request) {
@ -1008,4 +1009,29 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
}
}
}
public void batchAssociateBug(TestPlanCaseBatchAddBugRequest request, String bugId, String userId) {
List<String> ids = doSelectIds(request);
if (CollectionUtils.isNotEmpty(ids)) {
TestPlanFunctionalCaseExample example = new TestPlanFunctionalCaseExample();
example.createCriteria().andIdIn(ids);
List<TestPlanFunctionalCase> caseList = testPlanFunctionalCaseMapper.selectByExample(example);
Map<String, String> caseMap = caseList.stream().collect(Collectors.toMap(TestPlanFunctionalCase::getId, TestPlanFunctionalCase::getFunctionalCaseId));
List<BugRelationCase> list = new ArrayList<>();
ids.forEach(id -> {
BugRelationCase bugRelationCase = new BugRelationCase();
bugRelationCase.setId(IDGenerator.nextStr());
bugRelationCase.setBugId(bugId);
bugRelationCase.setCaseId(caseMap.get(id));
bugRelationCase.setCaseType(CaseType.FUNCTIONAL_CASE.getKey());
bugRelationCase.setCreateUser(userId);
bugRelationCase.setCreateTime(System.currentTimeMillis());
bugRelationCase.setUpdateTime(System.currentTimeMillis());
bugRelationCase.setTestPlanCaseId(id);
bugRelationCase.setTestPlanId(request.getTestPlanId());
list.add(bugRelationCase);
});
bugRelationCaseMapper.batchInsert(list);
}
}
}

View File

@ -2,6 +2,7 @@ package io.metersphere.plan.controller;
import io.metersphere.bug.domain.BugRelationCase;
import io.metersphere.bug.domain.BugRelationCaseExample;
import io.metersphere.bug.dto.response.BugCustomFieldDTO;
import io.metersphere.bug.mapper.BugRelationCaseMapper;
import io.metersphere.dto.BugProviderDTO;
import io.metersphere.functional.domain.FunctionalCaseBlob;
@ -33,9 +34,11 @@ import org.junit.jupiter.api.*;
import org.mockito.Mockito;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.SqlConfig;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.util.LinkedMultiValueMap;
import java.nio.charset.StandardCharsets;
import java.util.*;
@ -63,6 +66,7 @@ public class TestPlanCaseControllerTests extends BaseTest {
public static final String FUNCTIONAL_CASE_EXEC_HISTORY_URL = "/test-plan/functional/case/exec/history";
public static final String USER_URL = "/test-plan/functional/case/user-option/";
public static final String FUNCTIONAL_CASE_BATCH_MOVE_URL = "/test-plan/functional/case/batch/move";
public static final String FUNCTIONAL_CASE_BATCH_ADD_BUG_URL = "/test-plan/functional/case/batch/add-bug";
@Resource
private TestPlanFunctionalCaseMapper testPlanFunctionalCaseMapper;
@Resource
@ -284,7 +288,7 @@ public class TestPlanCaseControllerTests extends BaseTest {
functionalCaseStepDTO.setNum(1);
functionalCaseStepDTO.setDesc("步骤描述");
functionalCaseStepDTO.setResult("结果");
List<FunctionalCaseStepDTO>list = new ArrayList<>();
List<FunctionalCaseStepDTO> list = new ArrayList<>();
list.add(functionalCaseStepDTO);
testPlanCaseExecuteHistory.setSteps(JSON.toJSONString(list).getBytes());
testPlanCaseExecuteHistoryMapper.updateByPrimaryKeySelective(testPlanCaseExecuteHistory);
@ -438,4 +442,53 @@ public class TestPlanCaseControllerTests extends BaseTest {
this.requestPostWithOk(FUNCTIONAL_CASE_BATCH_MOVE_URL, request);
}
@Test
@Order(19)
public void testBatchAddBug() throws Exception {
TestPlanCaseBatchAddBugRequest request = buildRequest(false);
List<MockMultipartFile> files = new ArrayList<>();
LinkedMultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
paramMap.add("request", JSON.toJSONString(request));
paramMap.add("files", files);
this.requestMultipartWithOkAndReturn(FUNCTIONAL_CASE_BATCH_ADD_BUG_URL, paramMap);
request.setSelectAll(true);
paramMap = new LinkedMultiValueMap<>();
paramMap.add("request", JSON.toJSONString(request));
paramMap.add("files", files);
this.requestMultipartWithOkAndReturn(FUNCTIONAL_CASE_BATCH_ADD_BUG_URL, paramMap);
}
private TestPlanCaseBatchAddBugRequest buildRequest(boolean isUpdate) {
TestPlanCaseBatchAddBugRequest request = new TestPlanCaseBatchAddBugRequest();
request.setTestPlanId("plan_1");
request.setProjectId("123");
request.setTitle("default-bug-title");
request.setDescription("default-bug-description");
request.setTemplateId("default-bug-template");
request.setLinkFileIds(List.of("default-bug-file-id-1"));
if (isUpdate) {
request.setId("default-bug-id");
request.setUnLinkRefIds(List.of("default-file-association-id"));
request.setDeleteLocalFileIds(List.of("default-bug-file-id"));
request.setLinkFileIds(List.of("default-bug-file-id-2"));
}
BugCustomFieldDTO fieldDTO1 = new BugCustomFieldDTO();
fieldDTO1.setId("custom-field");
fieldDTO1.setName("oasis");
BugCustomFieldDTO fieldDTO2 = new BugCustomFieldDTO();
fieldDTO2.setId("test_field");
fieldDTO2.setName(JSON.toJSONString(List.of("test")));
BugCustomFieldDTO handleUserField = new BugCustomFieldDTO();
handleUserField.setId("handleUser");
handleUserField.setName("处理人");
handleUserField.setValue("admin");
BugCustomFieldDTO statusField = new BugCustomFieldDTO();
statusField.setId("status");
statusField.setName("状态");
statusField.setValue("1");
request.setCustomFields(List.of(fieldDTO1, fieldDTO2, handleUserField, statusField));
return request;
}
}

View File

@ -74,3 +74,21 @@ VALUES
INSERT INTO `test_plan_config`(`test_plan_id`, `automatic_status_update`, `repeat_case`, `pass_threshold`, `case_run_mode`)
VALUES ('plan_1', b'0', b'0', 100.00, 'PARALLEL');
INSERT INTO project_application (project_id, type, type_value) VALUES
('123', 'BUG_DEFAULT_TEMPLATE', 'default-bug-template-id'),
('123', 'BUG_SYNC_BUG_PLATFORM_CONFIG', '{"jiraKey":"TES","jiraBugTypeId":"10009"}'),
('123', 'BUG_SYNC_CRON_EXPRESSION', '0 0 0/1 * * ?'),
('123', 'BUG_SYNC_MECHANISM', 'increment'),
('123', 'BUG_SYNC_PLATFORM_KEY', 'jira'),
('123-integration', 'BUG_SYNC_PLATFORM_KEY', 'jira'),
('123', 'BUG_SYNC_SYNC_ENABLE', 'true'),
('123', 'CASE_RELATED_CASE_ENABLE', 'false'),
('123', 'CASE_RELATED_DEMAND_PLATFORM_CONFIG', '{"jiraKey":"TES","jiraDemandTypeId":"10007"}'),
('123', 'CASE_RELATED_PLATFORM_KEY', 'jira');
INSERT INTO service_integration(`id`, `plugin_id`, `enable`, `configuration`, `organization_id`) VALUES
('621103810617343', 'jira', true, 0x504B0304140008080800BC517657000000000000000000000000030000007A6970258DC10EC2201044FF65CF06D2C498D89347B5574FBD6D8158222CD85D6268E3BF4BE3F5CDBC990DD0DAC531430FB348E65EEBE06B41AAA9289480CC1E4991130D07C022F3A366D7DA13B2373B32261592469AF1572FCF883E289362CB735BF8A4C5EE073474C3CB8E59A6F85EEFF12AE676EC4E67F8FE00504B0708384DA4307800000087000000504B01021400140008080800BC517657384DA43078000000870000000300000000000000000000000000000000007A6970504B0506000000000100010031000000A90000000000, '1'),
('652096294625284', 'zentao', true, 0x504B030414000808080093756458000000000000000000000000030000007A6970AB564A4C49294A2D2E56B252CA282929B0D2D7373437D23334D3333230D033B3B4B230B0B050D2514A4C4ECE2FCD2B01AA4A4CC9CDCC038A1424161797E717A500859C1373F2F3D21D8C0C0C4D811245A985A5A9C525219505A940B900C7108F784F3F377FA55A00504B07088A813510680000006C000000504B01021400140008080800937564588A813510680000006C0000000300000000000000000000000000000000007A6970504B0506000000000100010031000000990000000000, '1');