feat(功能用例): 获取关联的测试计划

This commit is contained in:
guoyuqi 2024-01-17 10:54:49 +08:00 committed by f2c-ci-robot[bot]
parent e9f234978a
commit c8ed17ff7e
8 changed files with 145 additions and 7 deletions

View File

@ -5,7 +5,9 @@ import com.github.pagehelper.PageHelper;
import io.metersphere.dto.BugProviderDTO; import io.metersphere.dto.BugProviderDTO;
import io.metersphere.dto.TestCaseProviderDTO; import io.metersphere.dto.TestCaseProviderDTO;
import io.metersphere.functional.dto.FunctionalCaseTestDTO; import io.metersphere.functional.dto.FunctionalCaseTestDTO;
import io.metersphere.functional.dto.FunctionalCaseTestPlanDTO;
import io.metersphere.functional.request.AssociateCaseModuleRequest; import io.metersphere.functional.request.AssociateCaseModuleRequest;
import io.metersphere.functional.request.AssociatePlanPageRequest;
import io.metersphere.functional.request.DisassociateOtherCaseRequest; import io.metersphere.functional.request.DisassociateOtherCaseRequest;
import io.metersphere.functional.request.FunctionalCaseTestRequest; import io.metersphere.functional.request.FunctionalCaseTestRequest;
import io.metersphere.functional.service.FunctionalCaseLogService; import io.metersphere.functional.service.FunctionalCaseLogService;
@ -51,7 +53,7 @@ public class FunctionalTestCaseController {
@PostMapping("/associate/case/module/count") @PostMapping("/associate/case/module/count")
@Operation(summary = "用例管理-功能用例-关联其他用例-统计需要关联用例模块数量") @Operation(summary = "用例管理-功能用例-关联其他用例-统计需要关联用例模块数量")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ) @RequiresPermissions(value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_DELETE}, logical = Logical.OR)
@CheckOwner(resourceId = "#request.projectId", resourceType = "project") @CheckOwner(resourceId = "#request.projectId", resourceType = "project")
public Map<String, Long> moduleCount(@Validated @RequestBody TestCasePageProviderRequest request) { public Map<String, Long> moduleCount(@Validated @RequestBody TestCasePageProviderRequest request) {
return functionalTestCaseService.moduleCount(request, false); return functionalTestCaseService.moduleCount(request, false);
@ -59,7 +61,7 @@ public class FunctionalTestCaseController {
@PostMapping("/associate/case/module/tree") @PostMapping("/associate/case/module/tree")
@Operation(summary = "用例管理-功能用例-关联其他用例-获取需要关联的用例模块树") @Operation(summary = "用例管理-功能用例-关联其他用例-获取需要关联的用例模块树")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ) @RequiresPermissions(value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_DELETE}, logical = Logical.OR)
@CheckOwner(resourceId = "#request.projectId", resourceType = "project") @CheckOwner(resourceId = "#request.projectId", resourceType = "project")
public List<BaseTreeNode> getTree(@RequestBody @Validated AssociateCaseModuleRequest request) { public List<BaseTreeNode> getTree(@RequestBody @Validated AssociateCaseModuleRequest request) {
return functionalTestCaseService.getTree(request); return functionalTestCaseService.getTree(request);
@ -67,7 +69,7 @@ public class FunctionalTestCaseController {
@PostMapping("/associate/case") @PostMapping("/associate/case")
@Operation(summary = "用例管理-功能用例-关联其他用例-关联用例") @Operation(summary = "用例管理-功能用例-关联其他用例-关联用例")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ) @RequiresPermissions(value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_DELETE}, logical = Logical.OR)
@CheckOwner(resourceId = "#request.sourceId", resourceType = "functional_case") @CheckOwner(resourceId = "#request.sourceId", resourceType = "functional_case")
public void associateCase(@Validated @RequestBody AssociateOtherCaseRequest request) { public void associateCase(@Validated @RequestBody AssociateOtherCaseRequest request) {
functionalTestCaseService.associateCase(request, false, SessionUtils.getUserId()); functionalTestCaseService.associateCase(request, false, SessionUtils.getUserId());
@ -76,7 +78,7 @@ public class FunctionalTestCaseController {
@PostMapping("/disassociate/case") @PostMapping("/disassociate/case")
@Operation(summary = "用例管理-功能用例-关联其他用例-取消关联用例") @Operation(summary = "用例管理-功能用例-关联其他用例-取消关联用例")
@Log(type = OperationLogType.DISASSOCIATE, expression = "#msClass.disassociateCaseLog(#request)", msClass = FunctionalCaseLogService.class) @Log(type = OperationLogType.DISASSOCIATE, expression = "#msClass.disassociateCaseLog(#request)", msClass = FunctionalCaseLogService.class)
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ) @RequiresPermissions(value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_DELETE}, logical = Logical.OR)
@CheckOwner(resourceId = "#request.projectId", resourceType = "project") @CheckOwner(resourceId = "#request.projectId", resourceType = "project")
public void disassociateCase(@Validated @RequestBody DisassociateOtherCaseRequest request) { public void disassociateCase(@Validated @RequestBody DisassociateOtherCaseRequest request) {
functionalTestCaseService.disassociateCase(request); functionalTestCaseService.disassociateCase(request);
@ -129,4 +131,14 @@ public class FunctionalTestCaseController {
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize()); Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize());
return PageUtils.setPageInfo(page, functionalTestCaseService.hasAssociateBugPage(request)); return PageUtils.setPageInfo(page, functionalTestCaseService.hasAssociateBugPage(request));
} }
@PostMapping("/has/associate/plan/page")
@Operation(summary = "用例管理-功能用例-关联其他用例-获取已关联的测试计划列表")
@RequiresPermissions(value = {PermissionConstants.FUNCTIONAL_CASE_READ_ADD, PermissionConstants.FUNCTIONAL_CASE_READ_UPDATE, PermissionConstants.FUNCTIONAL_CASE_READ_DELETE}, logical = Logical.OR)
@CheckOwner(resourceId = "#request.caseId", resourceType = "functional_case")
public Pager<List<FunctionalCaseTestPlanDTO>> getAssociateOtherPlanList(@Validated @RequestBody AssociatePlanPageRequest request) {
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize());
return PageUtils.setPageInfo(page, functionalTestCaseService.hasAssociatePlanPage(request));
}
} }

View File

@ -0,0 +1,18 @@
package io.metersphere.functional.dto;
import io.metersphere.plan.domain.TestPlanFunctionalCase;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class FunctionalCaseTestPlanDTO extends TestPlanFunctionalCase {
@Schema(description = "测试计划ID")
private String num;
@Schema(description = "所属项目")
private String projectName;
@Schema(description = "计划状态")
private String planStatus;
}

View File

@ -1,6 +1,8 @@
package io.metersphere.functional.mapper; package io.metersphere.functional.mapper;
import io.metersphere.functional.dto.FunctionalCaseTestDTO; import io.metersphere.functional.dto.FunctionalCaseTestDTO;
import io.metersphere.functional.dto.FunctionalCaseTestPlanDTO;
import io.metersphere.functional.request.AssociatePlanPageRequest;
import io.metersphere.functional.request.DisassociateOtherCaseRequest; import io.metersphere.functional.request.DisassociateOtherCaseRequest;
import io.metersphere.functional.request.FunctionalCaseTestRequest; import io.metersphere.functional.request.FunctionalCaseTestRequest;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -12,4 +14,7 @@ public interface ExtFunctionalCaseTestMapper {
List<String> getIds(@Param("request") DisassociateOtherCaseRequest request); List<String> getIds(@Param("request") DisassociateOtherCaseRequest request);
List<FunctionalCaseTestDTO> getList(@Param("request") FunctionalCaseTestRequest request); List<FunctionalCaseTestDTO> getList(@Param("request") FunctionalCaseTestRequest request);
List<FunctionalCaseTestPlanDTO> getPlanList(@Param("request") AssociatePlanPageRequest request);
} }

View File

@ -56,6 +56,23 @@
order by fct.create_time desc order by fct.create_time desc
</select> </select>
<select id="getPlanList" parameterType="io.metersphere.functional.request.AssociatePlanPageRequest" resultType="io.metersphere.functional.dto.FunctionalCaseTestPlanDTO">
SELECT
tpfc.*, tp.num as num, tp.status as planStatus, p.name as projectName
FROM
test_plan_functional_case tpfc
LEFT JOIN test_plan tp ON tpfc.test_plan_id = tp.id
LEFT JOIN project p ON tp.project_id = p.id
WHERE tpfc.functional_case_id = #{request.caseId}
<if test="request.keyword != null">
AND
(
tp.name LIKE concat('%', #{request.keyword},'%')
OR tp.num LIKE concat('%', #{request.keyword},'%')
)
</if>
</select>
<sql id="queryWhereConditionByBaseQueryRequest"> <sql id="queryWhereConditionByBaseQueryRequest">
<if test="request.condition.keyword != null and request.sourceType == 'API'"> <if test="request.condition.keyword != null and request.sourceType == 'API'">
functional_case_test.source_id not in functional_case_test.source_id not in

View File

@ -0,0 +1,29 @@
package io.metersphere.functional.request;
import io.metersphere.request.BaseProviderCondition;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class AssociatePlanPageRequest extends BaseProviderCondition {
@Schema(description = "功能用例id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{associate_plan_page_request.case_id.not_blank}")
private String caseId;
@Min(value = 1, message = "当前页码必须大于0")
@Schema(description = "当前页码")
private int current;
@Min(value = 5, message = "每页显示条数必须不小于5")
@Max(value = 500, message = "每页显示条数不能大于500")
@Schema(description = "每页显示条数")
private int pageSize;
}

View File

@ -7,10 +7,12 @@ import io.metersphere.functional.constants.AssociateCaseType;
import io.metersphere.functional.domain.FunctionalCaseTest; import io.metersphere.functional.domain.FunctionalCaseTest;
import io.metersphere.functional.domain.FunctionalCaseTestExample; import io.metersphere.functional.domain.FunctionalCaseTestExample;
import io.metersphere.functional.dto.FunctionalCaseTestDTO; import io.metersphere.functional.dto.FunctionalCaseTestDTO;
import io.metersphere.functional.dto.FunctionalCaseTestPlanDTO;
import io.metersphere.functional.mapper.ExtFunctionalCaseModuleMapper; import io.metersphere.functional.mapper.ExtFunctionalCaseModuleMapper;
import io.metersphere.functional.mapper.ExtFunctionalCaseTestMapper; import io.metersphere.functional.mapper.ExtFunctionalCaseTestMapper;
import io.metersphere.functional.mapper.FunctionalCaseTestMapper; import io.metersphere.functional.mapper.FunctionalCaseTestMapper;
import io.metersphere.functional.request.AssociateCaseModuleRequest; import io.metersphere.functional.request.AssociateCaseModuleRequest;
import io.metersphere.functional.request.AssociatePlanPageRequest;
import io.metersphere.functional.request.DisassociateOtherCaseRequest; import io.metersphere.functional.request.DisassociateOtherCaseRequest;
import io.metersphere.functional.request.FunctionalCaseTestRequest; import io.metersphere.functional.request.FunctionalCaseTestRequest;
import io.metersphere.provider.BaseAssociateApiProvider; import io.metersphere.provider.BaseAssociateApiProvider;
@ -207,4 +209,13 @@ public class FunctionalTestCaseService {
public List<BugProviderDTO> hasAssociateBugPage(AssociateBugPageRequest request) { public List<BugProviderDTO> hasAssociateBugPage(AssociateBugPageRequest request) {
return baseAssociateBugProvider.hasAssociateBugPage(request); return baseAssociateBugProvider.hasAssociateBugPage(request);
} }
/**
* 查询已关联的测试计划列表
* @param request request
* @return List<FunctionalCaseTestPlanDTO>
*/
public List<FunctionalCaseTestPlanDTO> hasAssociatePlanPage(AssociatePlanPageRequest request) {
return extFunctionalCaseTestMapper.getPlanList(request);
}
} }

View File

@ -3,7 +3,6 @@ package io.metersphere.functional.controller;
import io.metersphere.api.domain.ApiDefinitionModule; import io.metersphere.api.domain.ApiDefinitionModule;
import io.metersphere.api.domain.ApiTestCase; import io.metersphere.api.domain.ApiTestCase;
import io.metersphere.api.mapper.ApiDefinitionModuleMapper; import io.metersphere.api.mapper.ApiDefinitionModuleMapper;
import io.metersphere.bug.mapper.BugRelationCaseMapper;
import io.metersphere.dto.BugProviderDTO; import io.metersphere.dto.BugProviderDTO;
import io.metersphere.dto.TestCaseProviderDTO; import io.metersphere.dto.TestCaseProviderDTO;
import io.metersphere.functional.constants.AssociateCaseType; import io.metersphere.functional.constants.AssociateCaseType;
@ -11,11 +10,15 @@ import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
import io.metersphere.functional.domain.FunctionalCase; import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.functional.domain.FunctionalCaseTest; import io.metersphere.functional.domain.FunctionalCaseTest;
import io.metersphere.functional.dto.FunctionalCaseTestDTO; import io.metersphere.functional.dto.FunctionalCaseTestDTO;
import io.metersphere.functional.dto.FunctionalCaseTestPlanDTO;
import io.metersphere.functional.mapper.FunctionalCaseMapper; import io.metersphere.functional.mapper.FunctionalCaseMapper;
import io.metersphere.functional.mapper.FunctionalCaseTestMapper; import io.metersphere.functional.mapper.FunctionalCaseTestMapper;
import io.metersphere.functional.request.AssociateCaseModuleRequest; import io.metersphere.functional.request.AssociateCaseModuleRequest;
import io.metersphere.functional.request.AssociatePlanPageRequest;
import io.metersphere.functional.request.DisassociateOtherCaseRequest; import io.metersphere.functional.request.DisassociateOtherCaseRequest;
import io.metersphere.functional.request.FunctionalCaseTestRequest; import io.metersphere.functional.request.FunctionalCaseTestRequest;
import io.metersphere.plan.mapper.TestPlanFunctionalCaseMapper;
import io.metersphere.plan.mapper.TestPlanMapper;
import io.metersphere.provider.BaseAssociateApiProvider; import io.metersphere.provider.BaseAssociateApiProvider;
import io.metersphere.provider.BaseAssociateBugProvider; import io.metersphere.provider.BaseAssociateBugProvider;
import io.metersphere.request.*; import io.metersphere.request.*;
@ -62,6 +65,9 @@ public class FunctionalTestCaseControllerTests extends BaseTest {
private static final String URL_DISASSOCIATE_BUG = "/functional/case/test/disassociate/bug/"; private static final String URL_DISASSOCIATE_BUG = "/functional/case/test/disassociate/bug/";
private static final String URL_ASSOCIATE_BUG_PAGE = "/functional/case/test/has/associate/bug/page"; private static final String URL_ASSOCIATE_BUG_PAGE = "/functional/case/test/has/associate/bug/page";
private static final String URL_ASSOCIATE_TEST_PLAN_PAGE = "/functional/case/test/has/associate/plan/page";
@Resource @Resource
BaseAssociateApiProvider provider; BaseAssociateApiProvider provider;
@ -76,12 +82,15 @@ public class FunctionalTestCaseControllerTests extends BaseTest {
private ApiDefinitionModuleMapper apiDefinitionModuleMapper; private ApiDefinitionModuleMapper apiDefinitionModuleMapper;
@Resource @Resource
BaseAssociateBugProvider baseAssociateBugProvider; BaseAssociateBugProvider baseAssociateBugProvider;
@Resource @Resource
private BugRelationCaseMapper bugRelationCaseMapper; TestPlanFunctionalCaseMapper testPlanFunctionalCaseMapper;
@Resource
TestPlanMapper testPlanMapper;
@Test @Test
@Order(1) @Order(1)
@Sql(scripts = {"/dml/init_test_plan_case.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
public void getPageSuccess() throws Exception { public void getPageSuccess() throws Exception {
TestCasePageProviderRequest request = new TestCasePageProviderRequest(); TestCasePageProviderRequest request = new TestCasePageProviderRequest();
request.setSourceType(AssociateCaseType.API); request.setSourceType(AssociateCaseType.API);
@ -389,4 +398,21 @@ public class FunctionalTestCaseControllerTests extends BaseTest {
}}); }});
this.requestPostWithOkAndReturn(URL_ASSOCIATE_BUG_PAGE, request); this.requestPostWithOkAndReturn(URL_ASSOCIATE_BUG_PAGE, request);
} }
@Test
@Order(12)
public void testAssociatePlanPage() throws Exception {
AssociatePlanPageRequest request = new AssociatePlanPageRequest();
request.setCurrent(1);
request.setPageSize(10);
request.setCaseId("gyq_associate_function_case");
request.setKeyword("name");
MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_ASSOCIATE_TEST_PLAN_PAGE, request);
Pager<List<FunctionalCaseTestPlanDTO>> tableData = JSON.parseObject(JSON.toJSONString(
JSON.parseObject(mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()),
Pager.class);
Assertions.assertNotNull(tableData);
List<FunctionalCaseTestPlanDTO> list = tableData.getList();
Assertions.assertEquals(2, list.size());
}
} }

View File

@ -0,0 +1,20 @@
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)
VALUE ('test_plan_associate_case_gyq_three', 500, 'test_plan_associate_case_project', 'NONE', 'case_plan_module', 'test_plan_associate_case_name_three', 'PREPARED', 'TEST_PLAN', null, UNIX_TIMESTAMP() * 1000,'admin',
UNIX_TIMESTAMP() * 1000,'admin',UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, null);
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 ('test_plan_associate_case_gyq_one', 500, 'test_plan_associate_case_project', 'NONE', 'case_plan_module', 'test_plan_associate_case_name_one', 'PREPARED', 'TEST_PLAN', null, UNIX_TIMESTAMP() * 1000,'admin',
UNIX_TIMESTAMP() * 1000,'admin',UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, null),
('test_plan_associate_case_gyq_two', 500, 'test_plan_associate_case_project', 'NONE', 'case_plan_module', 'test_plan_associate_case_name_two', 'PREPARED', 'TEST_PLAN', null, UNIX_TIMESTAMP() * 1000,'admin',
UNIX_TIMESTAMP() * 1000,'admin',UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, null);
INSERT INTO project(id, num, organization_id, name, description, create_time, update_time, update_user, create_user, delete_time, deleted, delete_user, enable, module_setting)
VALUE ('test_plan_associate_case_project', null, 'organization_plan_associate_case_project', 'test_plan_associate_case_name', null,
UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'admin', null, false, null, true, null);
INSERT INTO test_plan_functional_case(id, test_plan_id, functional_case_id, create_time, create_user, last_exec_time, last_exec_result, pos)
VALUES ('associate_case_plan_gyq_one', 'test_plan_associate_case_gyq_one', 'gyq_associate_function_case', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'SUCCESS', 200),
('associate_case_plan_gyq_two', 'test_plan_associate_case_gyq_two', 'gyq_associate_function_case', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'SUCCESS', 200);