From a7c31c63ace10b9a1da8563f0af118412df90fd3 Mon Sep 17 00:00:00 2001 From: AgAngle <1323481023@qq.com> Date: Mon, 5 Aug 2024 17:11:48 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):=20?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=8E=A5=E5=8F=A3=E5=8F=98=E6=9B=B4=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --task=1015860 --user=陈建星 【接口测试】接口用例支持同步更新接口变更-后端-批量同步更新接口 https://www.tapd.cn/55049933/s/1558631 --- .../metersphere/api/domain/ApiTestCase.java | 7 +- .../api/domain/ApiTestCaseExample.java | 60 +++++++++++++ .../api/mapper/ApiTestCaseMapper.xml | 84 ++++++++++++------- .../migration/3.2.0/ddl/V3.2.0_2__ga_ddl.sql | 2 +- .../definition/ApiTestCaseController.java | 16 ++++ .../definition/ApiCaseBatchSyncRequest.java | 39 +++++++++ .../api/mapper/ExtApiTestCaseMapper.xml | 2 +- .../definition/ApiTestCaseService.java | 15 ++++ .../ApiScenarioControllerTests.java | 1 + .../ApiTestCaseControllerTests.java | 33 ++++++++ 10 files changed, 225 insertions(+), 34 deletions(-) create mode 100644 backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiCaseBatchSyncRequest.java diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiTestCase.java b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiTestCase.java index 1384f3e16a..444f688a4b 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiTestCase.java +++ b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiTestCase.java @@ -95,6 +95,10 @@ public class ApiTestCase implements Serializable { @NotNull(message = "{api_test_case.ignore_api_change.not_blank}", groups = {Created.class}) private Boolean ignoreApiChange; + @Schema(description = "忽略接口与用例参数不一致", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "{api_test_case.ignore_api_diff.not_blank}", groups = {Created.class}) + private Boolean ignoreApiDiff; + private static final long serialVersionUID = 1L; public enum Column { @@ -119,7 +123,8 @@ public class ApiTestCase implements Serializable { deleteUser("delete_user", "deleteUser", "VARCHAR", false), deleted("deleted", "deleted", "BIT", false), apiChange("api_change", "apiChange", "BIT", false), - ignoreApiChange("ignore_api_change", "ignoreApiChange", "BIT", false); + ignoreApiChange("ignore_api_change", "ignoreApiChange", "BIT", false), + ignoreApiDiff("ignore_api_diff", "ignoreApiDiff", "BIT", false); private static final String BEGINNING_DELIMITER = "`"; diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiTestCaseExample.java b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiTestCaseExample.java index 28f8a57c3f..9ab6e505ba 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiTestCaseExample.java +++ b/backend/framework/domain/src/main/java/io/metersphere/api/domain/ApiTestCaseExample.java @@ -1597,6 +1597,66 @@ public class ApiTestCaseExample { addCriterion("ignore_api_change not between", value1, value2, "ignoreApiChange"); return (Criteria) this; } + + public Criteria andIgnoreApiDiffIsNull() { + addCriterion("ignore_api_diff is null"); + return (Criteria) this; + } + + public Criteria andIgnoreApiDiffIsNotNull() { + addCriterion("ignore_api_diff is not null"); + return (Criteria) this; + } + + public Criteria andIgnoreApiDiffEqualTo(Boolean value) { + addCriterion("ignore_api_diff =", value, "ignoreApiDiff"); + return (Criteria) this; + } + + public Criteria andIgnoreApiDiffNotEqualTo(Boolean value) { + addCriterion("ignore_api_diff <>", value, "ignoreApiDiff"); + return (Criteria) this; + } + + public Criteria andIgnoreApiDiffGreaterThan(Boolean value) { + addCriterion("ignore_api_diff >", value, "ignoreApiDiff"); + return (Criteria) this; + } + + public Criteria andIgnoreApiDiffGreaterThanOrEqualTo(Boolean value) { + addCriterion("ignore_api_diff >=", value, "ignoreApiDiff"); + return (Criteria) this; + } + + public Criteria andIgnoreApiDiffLessThan(Boolean value) { + addCriterion("ignore_api_diff <", value, "ignoreApiDiff"); + return (Criteria) this; + } + + public Criteria andIgnoreApiDiffLessThanOrEqualTo(Boolean value) { + addCriterion("ignore_api_diff <=", value, "ignoreApiDiff"); + return (Criteria) this; + } + + public Criteria andIgnoreApiDiffIn(List values) { + addCriterion("ignore_api_diff in", values, "ignoreApiDiff"); + return (Criteria) this; + } + + public Criteria andIgnoreApiDiffNotIn(List values) { + addCriterion("ignore_api_diff not in", values, "ignoreApiDiff"); + return (Criteria) this; + } + + public Criteria andIgnoreApiDiffBetween(Boolean value1, Boolean value2) { + addCriterion("ignore_api_diff between", value1, value2, "ignoreApiDiff"); + return (Criteria) this; + } + + public Criteria andIgnoreApiDiffNotBetween(Boolean value1, Boolean value2) { + addCriterion("ignore_api_diff not between", value1, value2, "ignoreApiDiff"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { diff --git a/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiTestCaseMapper.xml b/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiTestCaseMapper.xml index 24b7c778f7..9594436221 100644 --- a/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiTestCaseMapper.xml +++ b/backend/framework/domain/src/main/java/io/metersphere/api/mapper/ApiTestCaseMapper.xml @@ -24,6 +24,7 @@ + @@ -122,9 +123,10 @@ - id, `name`, priority, num, tags, `status`, last_report_status, last_report_id, pos, - project_id, api_definition_id, version_id, environment_id, create_time, create_user, - update_time, update_user, delete_time, delete_user, deleted, api_change, ignore_api_change + id, `name`, priority, num, tags, `status`, last_report_status, last_report_id, pos, + project_id, api_definition_id, version_id, environment_id, create_time, create_user, + update_time, update_user, delete_time, delete_user, deleted, api_change, ignore_api_change, + ignore_api_diff @@ -388,6 +398,9 @@ ignore_api_change = #{record.ignoreApiChange,jdbcType=BIT}, + + ignore_api_diff = #{record.ignoreApiDiff,jdbcType=BIT}, + @@ -416,7 +429,8 @@ delete_user = #{record.deleteUser,jdbcType=VARCHAR}, deleted = #{record.deleted,jdbcType=BIT}, api_change = #{record.apiChange,jdbcType=BIT}, - ignore_api_change = #{record.ignoreApiChange,jdbcType=BIT} + ignore_api_change = #{record.ignoreApiChange,jdbcType=BIT}, + ignore_api_diff = #{record.ignoreApiDiff,jdbcType=BIT} @@ -487,6 +501,9 @@ ignore_api_change = #{ignoreApiChange,jdbcType=BIT}, + + ignore_api_diff = #{ignoreApiDiff,jdbcType=BIT}, + where id = #{id,jdbcType=VARCHAR} @@ -512,25 +529,27 @@ delete_user = #{deleteUser,jdbcType=VARCHAR}, deleted = #{deleted,jdbcType=BIT}, api_change = #{apiChange,jdbcType=BIT}, - ignore_api_change = #{ignoreApiChange,jdbcType=BIT} + ignore_api_change = #{ignoreApiChange,jdbcType=BIT}, + ignore_api_diff = #{ignoreApiDiff,jdbcType=BIT} where id = #{id,jdbcType=VARCHAR} insert into api_test_case - (id, `name`, priority, num, tags, `status`, last_report_status, last_report_id, pos, - project_id, api_definition_id, version_id, environment_id, create_time, create_user, - update_time, update_user, delete_time, delete_user, deleted, api_change, ignore_api_change - ) + (id, `name`, priority, num, tags, `status`, last_report_status, last_report_id, pos, + project_id, api_definition_id, version_id, environment_id, create_time, create_user, + update_time, update_user, delete_time, delete_user, deleted, api_change, ignore_api_change, + ignore_api_diff) values - (#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.priority,jdbcType=VARCHAR}, - #{item.num,jdbcType=BIGINT}, #{item.tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler}, - #{item.status,jdbcType=VARCHAR}, #{item.lastReportStatus,jdbcType=VARCHAR}, #{item.lastReportId,jdbcType=VARCHAR}, - #{item.pos,jdbcType=BIGINT}, #{item.projectId,jdbcType=VARCHAR}, #{item.apiDefinitionId,jdbcType=VARCHAR}, - #{item.versionId,jdbcType=VARCHAR}, #{item.environmentId,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT}, - #{item.createUser,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=BIGINT}, #{item.updateUser,jdbcType=VARCHAR}, + (#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.priority,jdbcType=VARCHAR}, + #{item.num,jdbcType=BIGINT}, #{item.tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler}, + #{item.status,jdbcType=VARCHAR}, #{item.lastReportStatus,jdbcType=VARCHAR}, #{item.lastReportId,jdbcType=VARCHAR}, + #{item.pos,jdbcType=BIGINT}, #{item.projectId,jdbcType=VARCHAR}, #{item.apiDefinitionId,jdbcType=VARCHAR}, + #{item.versionId,jdbcType=VARCHAR}, #{item.environmentId,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT}, + #{item.createUser,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=BIGINT}, #{item.updateUser,jdbcType=VARCHAR}, #{item.deleteTime,jdbcType=BIGINT}, #{item.deleteUser,jdbcType=VARCHAR}, #{item.deleted,jdbcType=BIT}, - #{item.apiChange,jdbcType=BIT}, #{item.ignoreApiChange,jdbcType=BIT}) + #{item.apiChange,jdbcType=BIT}, #{item.ignoreApiChange,jdbcType=BIT}, #{item.ignoreApiDiff,jdbcType=BIT} + ) @@ -609,6 +628,9 @@ #{item.ignoreApiChange,jdbcType=BIT} + + #{item.ignoreApiDiff,jdbcType=BIT} + ) diff --git a/backend/framework/domain/src/main/resources/migration/3.2.0/ddl/V3.2.0_2__ga_ddl.sql b/backend/framework/domain/src/main/resources/migration/3.2.0/ddl/V3.2.0_2__ga_ddl.sql index 3a1231fa7e..f3ff6b0766 100644 --- a/backend/framework/domain/src/main/resources/migration/3.2.0/ddl/V3.2.0_2__ga_ddl.sql +++ b/backend/framework/domain/src/main/resources/migration/3.2.0/ddl/V3.2.0_2__ga_ddl.sql @@ -3,7 +3,7 @@ SET SESSION innodb_lock_wait_timeout = 7200; ALTER TABLE api_test_case ADD api_change BIT(1) DEFAULT 0 NOT NULL COMMENT '接口定义参数变更标识'; ALTER TABLE api_test_case ADD ignore_api_change BIT(1) DEFAULT 0 NOT NULL COMMENT '忽略接口定义参数变更'; - +ALTER TABLE api_test_case ADD ignore_api_diff BIT(1) DEFAULT 0 NOT NULL COMMENT '忽略接口与用例参数不一致'; -- set innodb lock wait timeout to default SET SESSION innodb_lock_wait_timeout = DEFAULT; diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiTestCaseController.java b/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiTestCaseController.java index 4cbd49b661..afd5c407e0 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiTestCaseController.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiTestCaseController.java @@ -198,6 +198,14 @@ public class ApiTestCaseController { apiTestCaseRecoverService.batchRecover(request, SessionUtils.getUserId()); } + @PostMapping("/batch/api-change/sync") + @Operation(summary = "接口测试-接口管理-接口用例-批量编辑") + @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_CASE_UPDATE) + @CheckOwner(resourceId = "#request.getSelectIds()", resourceType = "api_test_case") + public void batchSyncApiChange(@Validated @RequestBody ApiCaseBatchSyncRequest request) { + apiTestCaseService.batchSyncApiChange(request, SessionUtils.getUserId()); + } + @PostMapping(value = "/trash/page") @Operation(summary = "接口测试-接口管理-接口用例-回收站-分页查询") @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_CASE_READ) @@ -310,6 +318,14 @@ public class ApiTestCaseController { apiTestCaseService.clearApiChange(id); } + @GetMapping("/api-change/ignore/{id}") + @Operation(summary = "清除接口参数变更标识") + @RequiresPermissions(logical = Logical.OR, value = {PermissionConstants.PROJECT_API_DEFINITION_CASE_ADD, PermissionConstants.PROJECT_API_DEFINITION_CASE_UPDATE}) + @CheckOwner(resourceId = "#id", resourceType = "api_test_case") + public void ignoreApiChange(@PathVariable String id) { + apiTestCaseService.ignoreApiChange(id); + } + @GetMapping("/api/compare/{id}") @Operation(summary = "与接口定义对比") @RequiresPermissions(value = PermissionConstants.PROJECT_API_DEFINITION_CASE_READ) diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiCaseBatchSyncRequest.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiCaseBatchSyncRequest.java new file mode 100644 index 0000000000..f1de230b46 --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiCaseBatchSyncRequest.java @@ -0,0 +1,39 @@ +package io.metersphere.api.dto.definition; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +@Data +@EqualsAndHashCode(callSuper = false) +public class ApiCaseBatchSyncRequest extends ApiTestCaseBatchRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "同步项") + private ApiCaseSyncItemRequest syncItems = new ApiCaseSyncItemRequest(); + @Schema(description = "是否删除多余参数", defaultValue = "false") + private boolean deleteRedundantParam = false; + @Schema(description = "通知配置") + private ApiCaseSyncNotificationRequest notificationConfig = new ApiCaseSyncNotificationRequest(); + + public class ApiCaseSyncItemRequest { + @Schema(description = "请求头", defaultValue = "true") + private Boolean header = true; + @Schema(description = "请求体", defaultValue = "true") + private Boolean body = true; + @Schema(description = "Query参数", defaultValue = "true") + private Boolean query = true; + @Schema(description = "Rest参数", defaultValue = "true") + private Boolean rest = true; + } + + public class ApiCaseSyncNotificationRequest { + @Schema(description = "是否通知接口创建人", defaultValue = "true") + private Boolean apiCreator = true; + @Schema(description = "是否通知引用该用例的场景创建人", defaultValue = "true") + private Boolean scenarioCreator = true; + } +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.xml b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.xml index 39542e50a2..a27ab58605 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.xml +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiTestCaseMapper.xml @@ -30,7 +30,7 @@ update api_test_case - set api_change = true + set api_change = true, ignore_api_diff = false where api_definition_id = #{apiDefinitionId} and api_change is false and ignore_api_change is false diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java index 5566fa34c3..7bc214995b 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java @@ -950,6 +950,7 @@ public class ApiTestCaseService extends MoveNodeService { ApiTestCase apiTestCase = new ApiTestCase(); apiTestCase.setId(id); apiTestCase.setApiChange(false); + apiTestCase.setIgnoreApiDiff(true); apiTestCaseMapper.updateByPrimaryKeySelective(apiTestCase); } @@ -978,4 +979,18 @@ public class ApiTestCaseService extends MoveNodeService { private AbstractMsTestElement getTestElement(ApiTestCaseBlob apiTestCaseBlob) { return ApiDataUtils.parseObject(new String(apiTestCaseBlob.getRequest()), AbstractMsTestElement.class); } + + public void ignoreApiChange(String id) { + checkResourceExist(id); + ApiTestCase apiTestCase = new ApiTestCase(); + apiTestCase.setId(id); + apiTestCase.setApiChange(false); + apiTestCase.setIgnoreApiDiff(true); + apiTestCase.setIgnoreApiChange(true); + apiTestCaseMapper.updateByPrimaryKeySelective(apiTestCase); + } + + public void batchSyncApiChange(ApiCaseBatchSyncRequest request, String userId) { + // todo + } } diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java index 2b375dfb77..8ded74ba11 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java @@ -2853,6 +2853,7 @@ public class ApiScenarioControllerTests extends BaseTest { apiTestCase.setLastReportStatus("未执行"); apiTestCase.setApiChange(false); apiTestCase.setIgnoreApiChange(false); + apiTestCase.setIgnoreApiDiff(false); apiTestCases.add(apiTestCase); } apiTestCaseMapper.batchInsert(apiTestCases); diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestCaseControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestCaseControllerTests.java index 6142205c47..e1b7b9864f 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestCaseControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiTestCaseControllerTests.java @@ -111,6 +111,8 @@ public class ApiTestCaseControllerTests extends BaseTest { private static final String RUN_POST = "run"; private static final String BATCH_RUN = "batch/run"; private static final String API_CHANGE_CLEAR = "api-change/clear/{0}"; + private static final String API_CHANGE_IGNORE = "api-change/ignore/{0}"; + private static final String API_CHANGE_SYNC = "batch/api-change/sync"; private static final String API_COMPARE = "api/compare/{0}"; private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError(); @@ -234,6 +236,7 @@ public class ApiTestCaseControllerTests extends BaseTest { apiTestCase.setLastReportStatus("SUCCESS"); apiTestCase.setApiChange(false); apiTestCase.setIgnoreApiChange(false); + apiTestCase.setIgnoreApiDiff(false); caseMapper.insert(apiTestCase); ApiTestCaseBlob apiTestCaseBlob = new ApiTestCaseBlob(); apiTestCaseBlob.setId(apiTestCase.getId()); @@ -437,6 +440,7 @@ public class ApiTestCaseControllerTests extends BaseTest { apiTestCaseService.handleApiParamChange(apiTestCase.getApiDefinitionId(), changeRequest, originRequest); // 校验变更通知 Assertions.assertEquals(apiTestCaseMapper.selectByPrimaryKey(apiTestCase.getId()).getApiChange(), true); + Assertions.assertEquals(apiTestCaseMapper.selectByPrimaryKey(apiTestCase.getId()).getIgnoreApiDiff(), false); } @Test @@ -460,12 +464,41 @@ public class ApiTestCaseControllerTests extends BaseTest { apiTestCaseMapper.updateByPrimaryKeySelective(updateCase); this.requestGetWithOk(API_CHANGE_CLEAR, apiTestCase.getId()); Assertions.assertFalse(apiTestCaseMapper.selectByPrimaryKey(apiTestCase.getId()).getApiChange()); + Assertions.assertTrue(apiTestCaseMapper.selectByPrimaryKey(apiTestCase.getId()).getIgnoreApiDiff()); // @@校验权限 requestGetPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_CASE_ADD, API_CHANGE_CLEAR, apiTestCase.getId()); requestGetPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_CASE_UPDATE, API_CHANGE_CLEAR, apiTestCase.getId()); } + @Test + @Order(3) + public void ignoreApiChange() throws Exception { + ApiTestCase updateCase = new ApiTestCase(); + updateCase.setApiChange(true); + updateCase.setId(apiTestCase.getId()); + apiTestCaseMapper.updateByPrimaryKeySelective(updateCase); + this.requestGetWithOk(API_CHANGE_IGNORE, apiTestCase.getId()); + Assertions.assertFalse(apiTestCaseMapper.selectByPrimaryKey(apiTestCase.getId()).getApiChange()); + Assertions.assertTrue(apiTestCaseMapper.selectByPrimaryKey(apiTestCase.getId()).getIgnoreApiDiff()); + Assertions.assertTrue(apiTestCaseMapper.selectByPrimaryKey(apiTestCase.getId()).getIgnoreApiChange()); + + // @@校验权限 + requestGetPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_CASE_ADD, API_CHANGE_IGNORE, apiTestCase.getId()); + requestGetPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_CASE_UPDATE, API_CHANGE_IGNORE, apiTestCase.getId()); + } + + @Test + @Order(4) + public void batchSyncApiChange() throws Exception { + ApiCaseBatchSyncRequest request = new ApiCaseBatchSyncRequest(); + request.setProjectId(DEFAULT_PROJECT_ID); + this.requestPostWithOk(API_CHANGE_SYNC, request); + + // @@校验权限 + requestPostPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_CASE_UPDATE, API_CHANGE_SYNC, request); + } + /** * 测试关联的文件更新 *