feat(接口测试): 接口定义页面增加覆盖和不覆盖的筛选
This commit is contained in:
parent
b96433eb75
commit
c71fd05a7c
|
@ -0,0 +1,11 @@
|
||||||
|
package io.metersphere.api.constants;
|
||||||
|
|
||||||
|
public class ApiCoverageConstants {
|
||||||
|
|
||||||
|
public static final String COVER_FROM = "coverFrom";
|
||||||
|
public static final String UN_COVER_FROM = "unCoverFrom";
|
||||||
|
|
||||||
|
public static final String API_DEFINITION = "apiDefinition";
|
||||||
|
public static final String API_CASE = "apiCase";
|
||||||
|
public static final String API_SCENARIO = "apiScenario";
|
||||||
|
}
|
|
@ -98,7 +98,7 @@ public class ApiDefinitionController {
|
||||||
@CheckOwner(resourceId = "#projectId", resourceType = "project")
|
@CheckOwner(resourceId = "#projectId", resourceType = "project")
|
||||||
public ApiCoverageDTO rage(@PathVariable String projectId) {
|
public ApiCoverageDTO rage(@PathVariable String projectId) {
|
||||||
// 筛选出所有 API 的 ID 和 HTTP 类型的 API
|
// 筛选出所有 API 的 ID 和 HTTP 类型的 API
|
||||||
List<ApiDefinition> apiDefinitions = extApiDefinitionMapper.selectBaseInfoByProjectId(projectId);
|
List<ApiDefinition> apiDefinitions = extApiDefinitionMapper.selectBaseInfoByProjectId(projectId, null, null);
|
||||||
List<String> apiAllIds = apiDefinitions.stream().map(ApiDefinition::getId).toList();
|
List<String> apiAllIds = apiDefinitions.stream().map(ApiDefinition::getId).toList();
|
||||||
List<ApiDefinition> httpApiList = apiDefinitions.stream()
|
List<ApiDefinition> httpApiList = apiDefinitions.stream()
|
||||||
.filter(api -> StringUtils.equalsIgnoreCase(api.getProtocol(), "http"))
|
.filter(api -> StringUtils.equalsIgnoreCase(api.getProtocol(), "http"))
|
||||||
|
@ -106,12 +106,12 @@ public class ApiDefinitionController {
|
||||||
|
|
||||||
// 获取 API 定义、测试用例 ID 和场景步骤中的 API ID
|
// 获取 API 定义、测试用例 ID 和场景步骤中的 API ID
|
||||||
List<String> apiDefinitionIdFromCase = extApiTestCaseMapper.selectApiId(projectId);
|
List<String> apiDefinitionIdFromCase = extApiTestCaseMapper.selectApiId(projectId);
|
||||||
List<String> apiInScenarioStep = new ArrayList<>(extApiScenarioStepMapper.selectResourceId(projectId, ApiScenarioStepType.API.name()));
|
List<String> apiInScenarioStep = new ArrayList<>(extApiScenarioStepMapper.selectResourceId(projectId, ApiScenarioStepType.API.name(), null));
|
||||||
List<String> apiCaseIdInStep = extApiScenarioStepMapper.selectResourceId(projectId, ApiScenarioStepType.API_CASE.name());
|
List<String> apiCaseIdInStep = extApiScenarioStepMapper.selectResourceId(projectId, ApiScenarioStepType.API_CASE.name(), null);
|
||||||
|
|
||||||
// 如果有场景步骤中的 API 用例 ID,追加相关 API ID
|
// 如果有场景步骤中的 API 用例 ID,追加相关 API ID
|
||||||
if (CollectionUtils.isNotEmpty(apiCaseIdInStep)) {
|
if (CollectionUtils.isNotEmpty(apiCaseIdInStep)) {
|
||||||
List<String> apiCaseIdInScenarioStep = extApiTestCaseMapper.selectApiIdByCaseId(apiCaseIdInStep);
|
List<String> apiCaseIdInScenarioStep = extApiTestCaseMapper.selectApiIdByCaseId(apiCaseIdInStep, null, null);
|
||||||
apiInScenarioStep.addAll(apiCaseIdInScenarioStep);
|
apiInScenarioStep.addAll(apiCaseIdInScenarioStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,6 +198,7 @@ public class ApiDefinitionController {
|
||||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ)
|
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ)
|
||||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||||
public Pager<List<ApiDefinitionDTO>> getPage(@Validated @RequestBody ApiDefinitionPageRequest request) {
|
public Pager<List<ApiDefinitionDTO>> getPage(@Validated @RequestBody ApiDefinitionPageRequest request) {
|
||||||
|
apiDefinitionService.initApiSelectIds(request);
|
||||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
||||||
StringUtils.isNotBlank(request.getSortString("id")) ? request.getSortString("id") : request.getDeleted() ? "delete_time desc, id desc" : "pos desc, id desc");
|
StringUtils.isNotBlank(request.getSortString("id")) ? request.getSortString("id") : request.getDeleted() ? "delete_time desc, id desc" : "pos desc, id desc");
|
||||||
return PageUtils.setPageInfo(page, apiDefinitionService.getApiDefinitionPage(request, SessionUtils.getUserId()));
|
return PageUtils.setPageInfo(page, apiDefinitionService.getApiDefinitionPage(request, SessionUtils.getUserId()));
|
||||||
|
|
|
@ -46,4 +46,10 @@ public class ApiDefinitionPageRequest extends BasePageRequest {
|
||||||
|
|
||||||
@Schema(description = "删除状态(状态为 1 时为回收站数据)")
|
@Schema(description = "删除状态(状态为 1 时为回收站数据)")
|
||||||
private Boolean deleted = false;
|
private Boolean deleted = false;
|
||||||
|
|
||||||
|
@Schema(description = "本次查询包含的ID(一般由后台计算后得出)")
|
||||||
|
private List<String> includeIds = new ArrayList<>();
|
||||||
|
|
||||||
|
@Schema(description = "本次查询不包含的ID(一般由后台计算后得出)")
|
||||||
|
private List<String> excludeIds = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,4 +34,11 @@ public class ApiModuleRequest extends BaseCondition {
|
||||||
|
|
||||||
@Schema(description = "测试计划id")
|
@Schema(description = "测试计划id")
|
||||||
private String testPlanId;
|
private String testPlanId;
|
||||||
|
|
||||||
|
@Schema(description = "本次查询包含的ID(一般由后台计算后得出)")
|
||||||
|
private List<String> includeIds = new ArrayList<>();
|
||||||
|
|
||||||
|
@Schema(description = "本次查询不包含的ID(一般由后台计算后得出)")
|
||||||
|
private List<String> excludeIds = new ArrayList<>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ public interface ExtApiDefinitionMapper {
|
||||||
Long getPos(@Param("projectId") String projectId);
|
Long getPos(@Param("projectId") String projectId);
|
||||||
|
|
||||||
@BaseConditionFilter
|
@BaseConditionFilter
|
||||||
List<String> getIds(@Param("request") TableBatchProcessDTO request, @Param("projectId") String projectId, @Param("protocols") List<String> protocols, @Param("deleted") boolean deleted);
|
List<String> getIds(@Param("request") TableBatchProcessDTO request, @Param("projectId") String projectId, @Param("protocols") List<String> protocols, @Param("deleted") boolean deleted, @Param("includeIds") List<String> includeIds, @Param("excludeIds") List<String> excludeIds);
|
||||||
|
|
||||||
@BaseConditionFilter
|
@BaseConditionFilter
|
||||||
List<String> getIdsBySort(@Param("request") TableBatchProcessDTO request, @Param("projectId") String projectId, @Param("protocols") List<String> protocols, @Param("orderColumns") String orderColumns, @Param("deleted") boolean deleted);
|
List<String> getIdsBySort(@Param("request") TableBatchProcessDTO request, @Param("projectId") String projectId, @Param("protocols") List<String> protocols, @Param("orderColumns") String orderColumns, @Param("deleted") boolean deleted);
|
||||||
|
@ -129,5 +129,5 @@ public interface ExtApiDefinitionMapper {
|
||||||
|
|
||||||
List<ApiDefinition> getCreateApiList(@Param("projectId") String projectId, @Param("startTime") Long startTime, @Param("endTime") Long endTime);
|
List<ApiDefinition> getCreateApiList(@Param("projectId") String projectId, @Param("startTime") Long startTime, @Param("endTime") Long endTime);
|
||||||
|
|
||||||
List<ApiDefinition> selectBaseInfoByProjectId(String projectId);
|
List<ApiDefinition> selectBaseInfoByProjectId(@Param("projectId") String projectId, @Param("protocols") List<String> protocols, @Param("ignoreApiIds") List<String> ignoreApiIds);
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,18 @@
|
||||||
#{item}
|
#{item}
|
||||||
</foreach>
|
</foreach>
|
||||||
</if>
|
</if>
|
||||||
|
<if test="includeIds != null and includeIds.size() > 0">
|
||||||
|
and api_definition.id in
|
||||||
|
<foreach collection="includeIds" item="includeId" separator="," open="(" close=")">
|
||||||
|
#{includeId}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
<if test="excludeIds != null and excludeIds.size() > 0">
|
||||||
|
and api_definition.id not in
|
||||||
|
<foreach collection="excludeIds" item="excludeId" separator="," open="(" close=")">
|
||||||
|
#{excludeId}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
<include refid="queryWhereConditionByBaseQueryRequest"/>
|
<include refid="queryWhereConditionByBaseQueryRequest"/>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
@ -264,6 +276,18 @@
|
||||||
<if test="request.projectId != null and request.projectId != ''">
|
<if test="request.projectId != null and request.projectId != ''">
|
||||||
and api_definition.project_id = #{request.projectId}
|
and api_definition.project_id = #{request.projectId}
|
||||||
</if>
|
</if>
|
||||||
|
<if test="request.includeIds != null and request.includeIds.size() > 0">
|
||||||
|
and api_definition.id in
|
||||||
|
<foreach collection="request.includeIds" item="includeId" separator="," open="(" close=")">
|
||||||
|
#{includeId}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
<if test="request.excludeIds != null and request.excludeIds.size() > 0">
|
||||||
|
and api_definition.id not in
|
||||||
|
<foreach collection="request.excludeIds" item="excludeId" separator="," open="(" close=")">
|
||||||
|
#{excludeId}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
<if test="request.protocols != null and request.protocols.size() > 0">
|
<if test="request.protocols != null and request.protocols.size() > 0">
|
||||||
and api_definition.protocol in
|
and api_definition.protocol in
|
||||||
<foreach collection="request.protocols" item="protocol" separator="," open="(" close=")">
|
<foreach collection="request.protocols" item="protocol" separator="," open="(" close=")">
|
||||||
|
@ -843,7 +867,19 @@
|
||||||
<select id="selectBaseInfoByProjectId" resultType="io.metersphere.api.domain.ApiDefinition">
|
<select id="selectBaseInfoByProjectId" resultType="io.metersphere.api.domain.ApiDefinition">
|
||||||
SELECT id, path, method, protocol
|
SELECT id, path, method, protocol
|
||||||
FROM api_definition
|
FROM api_definition
|
||||||
WHERE project_id = #{0}
|
WHERE project_id = #{projectId}
|
||||||
AND deleted IS FALSE
|
AND deleted IS FALSE
|
||||||
|
<if test="protocols != null and protocols.size() > 0">
|
||||||
|
AND protocol IN
|
||||||
|
<foreach collection="protocols" item="protocol" separator="," open="(" close=")">
|
||||||
|
#{protocol}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
<if test="ignoreApiIds!= null and ignoreApiIds.size > 0">
|
||||||
|
AND id NOT IN
|
||||||
|
<foreach collection="ignoreApiIds" item="ignoreApiId" open="(" separator="," close=")">
|
||||||
|
#{ignoreApiId}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
</select>
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
@ -26,7 +26,7 @@ public interface ExtApiScenarioStepMapper {
|
||||||
*/
|
*/
|
||||||
List<String> getHasBlobRequestStepIds(@Param("scenarioId") String scenarioId);
|
List<String> getHasBlobRequestStepIds(@Param("scenarioId") String scenarioId);
|
||||||
|
|
||||||
List<String> selectResourceId(@Param("projectId") String projectId, @Param("stepType") String stepType);
|
List<String> selectResourceId(@Param("projectId") String projectId, @Param("stepType") String stepType, @Param("protocols") List<String> apiProtocols);
|
||||||
|
|
||||||
List<String> selectCustomRequestConfigByProjectId(String projectId);
|
List<String> selectCustomRequestConfigByProjectId(String projectId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,16 @@
|
||||||
where step.step_type = #{stepType}
|
where step.step_type = #{stepType}
|
||||||
AND scenario.project_id = #{projectId}
|
AND scenario.project_id = #{projectId}
|
||||||
AND scenario.deleted IS FALSE
|
AND scenario.deleted IS FALSE
|
||||||
|
<if test="protocols!= null and protocols.size > 0">
|
||||||
|
AND step.resource_id IN (
|
||||||
|
select distinct apiCase.id FROM api_definition api
|
||||||
|
INNER JOIN api_test_case apiCase ON api.id = apiCase.api_definition_id
|
||||||
|
WHERE api.project_id = #{projectId} AND api.deleted IS FALSE and api.deleted IS FALSE AND api.protocol IN
|
||||||
|
<foreach collection="protocols" item="protocol" open="(" separator="," close=")">
|
||||||
|
#{protocol}
|
||||||
|
</foreach>
|
||||||
|
)
|
||||||
|
</if>
|
||||||
</select>
|
</select>
|
||||||
<select id="selectCustomRequestConfigByProjectId" resultType="java.lang.String">
|
<select id="selectCustomRequestConfigByProjectId" resultType="java.lang.String">
|
||||||
select step.id
|
select step.id
|
||||||
|
|
|
@ -143,5 +143,7 @@ public interface ExtApiTestCaseMapper {
|
||||||
|
|
||||||
List<String> selectApiId(String projectId);
|
List<String> selectApiId(String projectId);
|
||||||
|
|
||||||
List<String> selectApiIdByCaseId(@Param("ids") List<String> apiCaseIdInStep);
|
List<String> selectApiIdByProjectAndProtocol(@Param("projectId") String projectId, @Param("protocols") List<String> protocols);
|
||||||
|
|
||||||
|
List<String> selectApiIdByCaseId(@Param("ids") List<String> apiCaseIdInStep, @Param("protocols") List<String> apiProtocols, @Param("ignoreApiIds") List<String> ignoreApiIds);
|
||||||
}
|
}
|
|
@ -1040,9 +1040,36 @@
|
||||||
AND api.project_id = #{0}
|
AND api.project_id = #{0}
|
||||||
</select>
|
</select>
|
||||||
<select id="selectApiIdByCaseId" resultType="java.lang.String">
|
<select id="selectApiIdByCaseId" resultType="java.lang.String">
|
||||||
SELECT api_definition_id FROM api_test_case WHERE deleted is false AND id in
|
SELECT DISTINCT apiCase.api_definition_id FROM api_test_case apiCase
|
||||||
|
INNER JOIN api_definition api ON apiCase.api_definition_id = api.id
|
||||||
|
|
||||||
|
WHERE apiCase.deleted IS FALSE AND api.deleted IS FALSE AND apiCase.id in
|
||||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||||
#{id}
|
#{id}
|
||||||
</foreach>
|
</foreach>
|
||||||
|
<if test="protocols!= null and protocols.size > 0">
|
||||||
|
AND api.protocol IN
|
||||||
|
<foreach collection="protocols" item="protocol" open="(" separator="," close=")">
|
||||||
|
#{protocol}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
<if test="ignoreApiIds!= null and ignoreApiIds.size > 0">
|
||||||
|
AND api.id NOT IN
|
||||||
|
<foreach collection="ignoreApiIds" item="ignoreApiId" open="(" separator="," close=")">
|
||||||
|
#{ignoreApiId}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
|
<select id="selectApiIdByProjectAndProtocol" resultType="java.lang.String">
|
||||||
|
SELECT distinct api.id
|
||||||
|
FROM api_test_case apiCase
|
||||||
|
INNER JOIN api_definition api ON apiCase.api_definition_id = api.id
|
||||||
|
WHERE apiCase.deleted is FALSE
|
||||||
|
AND api.deleted is FALSE
|
||||||
|
AND api.project_id = #{projectId}
|
||||||
|
AND api.protocol IN
|
||||||
|
<foreach collection="protocols" item="protocol" separator="," open="(" close=")">
|
||||||
|
#{protocol}
|
||||||
|
</foreach>
|
||||||
</select>
|
</select>
|
||||||
</mapper>
|
</mapper>
|
|
@ -18,6 +18,7 @@ import io.metersphere.project.dto.NodeSortDTO;
|
||||||
import io.metersphere.project.service.ModuleTreeService;
|
import io.metersphere.project.service.ModuleTreeService;
|
||||||
import io.metersphere.sdk.constants.ModuleConstants;
|
import io.metersphere.sdk.constants.ModuleConstants;
|
||||||
import io.metersphere.sdk.exception.MSException;
|
import io.metersphere.sdk.exception.MSException;
|
||||||
|
import io.metersphere.sdk.util.CommonBeanFactory;
|
||||||
import io.metersphere.sdk.util.Translator;
|
import io.metersphere.sdk.util.Translator;
|
||||||
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
import io.metersphere.system.dto.sdk.BaseTreeNode;
|
||||||
import io.metersphere.system.dto.sdk.request.NodeMoveRequest;
|
import io.metersphere.system.dto.sdk.request.NodeMoveRequest;
|
||||||
|
@ -73,6 +74,9 @@ public class ApiDefinitionModuleService extends ModuleTreeService {
|
||||||
if (!containRequest || CollectionUtils.isEmpty(request.getProtocols())) {
|
if (!containRequest || CollectionUtils.isEmpty(request.getProtocols())) {
|
||||||
return baseTreeNodes;
|
return baseTreeNodes;
|
||||||
}
|
}
|
||||||
|
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
|
||||||
|
request.setExcludeIds(apiDefinitionService.getQueryExcludeIds(request.getFilter(), request.getProjectId(), request.getProtocols()));
|
||||||
|
request.setIncludeIds(apiDefinitionService.getQueryIncludeIds(request.getFilter(), request.getProjectId(), request.getProtocols()));
|
||||||
List<ApiTreeNode> apiTreeNodeList = extApiDefinitionModuleMapper.selectApiDataByRequest(request, deleted);
|
List<ApiTreeNode> apiTreeNodeList = extApiDefinitionModuleMapper.selectApiDataByRequest(request, deleted);
|
||||||
return apiDebugModuleService.getBaseTreeNodes(apiTreeNodeList, baseTreeNodes);
|
return apiDebugModuleService.getBaseTreeNodes(apiTreeNodeList, baseTreeNodes);
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package io.metersphere.api.service.definition;
|
package io.metersphere.api.service.definition;
|
||||||
|
|
||||||
import io.metersphere.api.constants.ApiConstants;
|
import io.metersphere.api.constants.*;
|
||||||
import io.metersphere.api.constants.ApiDefinitionDocType;
|
|
||||||
import io.metersphere.api.constants.ApiResourceType;
|
|
||||||
import io.metersphere.api.controller.result.ApiResultCode;
|
import io.metersphere.api.controller.result.ApiResultCode;
|
||||||
import io.metersphere.api.domain.*;
|
import io.metersphere.api.domain.*;
|
||||||
import io.metersphere.api.dto.*;
|
import io.metersphere.api.dto.*;
|
||||||
|
@ -16,6 +14,7 @@ import io.metersphere.api.mapper.*;
|
||||||
import io.metersphere.api.service.ApiCommonService;
|
import io.metersphere.api.service.ApiCommonService;
|
||||||
import io.metersphere.api.service.ApiExecuteService;
|
import io.metersphere.api.service.ApiExecuteService;
|
||||||
import io.metersphere.api.service.ApiFileResourceService;
|
import io.metersphere.api.service.ApiFileResourceService;
|
||||||
|
import io.metersphere.api.service.scenario.ApiScenarioService;
|
||||||
import io.metersphere.api.utils.ApiDataUtils;
|
import io.metersphere.api.utils.ApiDataUtils;
|
||||||
import io.metersphere.api.utils.JsonSchemaBuilder;
|
import io.metersphere.api.utils.JsonSchemaBuilder;
|
||||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||||
|
@ -53,6 +52,7 @@ import io.metersphere.system.uid.NumGenerator;
|
||||||
import io.metersphere.system.utils.ServiceUtils;
|
import io.metersphere.system.utils.ServiceUtils;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.collections4.ListUtils;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.ibatis.session.ExecutorType;
|
import org.apache.ibatis.session.ExecutorType;
|
||||||
|
@ -83,6 +83,9 @@ public class ApiDefinitionService extends MoveNodeService {
|
||||||
@Resource
|
@Resource
|
||||||
private ExtApiDefinitionMapper extApiDefinitionMapper;
|
private ExtApiDefinitionMapper extApiDefinitionMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ExtApiScenarioStepMapper extApiScenarioStepMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ExtApiDefinitionModuleMapper extApiDefinitionModuleMapper;
|
private ExtApiDefinitionModuleMapper extApiDefinitionModuleMapper;
|
||||||
|
|
||||||
|
@ -133,8 +136,10 @@ public class ApiDefinitionService extends MoveNodeService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private OperationLogBlobMapper operationLogBlobMapper;
|
private OperationLogBlobMapper operationLogBlobMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ApiExecuteService apiExecuteService;
|
private ApiExecuteService apiExecuteService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ApiDefinitionNoticeService apiDefinitionNoticeService;
|
private ApiDefinitionNoticeService apiDefinitionNoticeService;
|
||||||
|
|
||||||
|
@ -147,6 +152,77 @@ public class ApiDefinitionService extends MoveNodeService {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void initApiSelectIds(ApiDefinitionPageRequest request) {
|
||||||
|
request.setExcludeIds(this.getQueryExcludeIds(request.getFilter(), request.getProjectId(), request.getProtocols()));
|
||||||
|
request.setIncludeIds(this.getQueryIncludeIds(request.getFilter(), request.getProjectId(), request.getProtocols()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getQueryIncludeIds(Map<String, List<String>> queryFilter, String projectId, List<String> protocol) {
|
||||||
|
if (queryFilter != null && CollectionUtils.isNotEmpty(queryFilter.get("coverFrom"))) {
|
||||||
|
String coverFrom = queryFilter.get("coverFrom").getFirst();
|
||||||
|
if (ApiCoverageConstants.API_DEFINITION.equals(coverFrom)) {
|
||||||
|
return this.selectApiIdInCaseAndScenarioStep(projectId, protocol);
|
||||||
|
} else if (ApiCoverageConstants.API_CASE.equals(coverFrom)) {
|
||||||
|
return this.selectApiIdInCase(projectId, protocol);
|
||||||
|
} else if (ApiCoverageConstants.API_SCENARIO.equals(coverFrom)) {
|
||||||
|
return this.selectApiIdInScenarioStep(projectId, protocol, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getQueryExcludeIds(Map<String, List<String>> queryFilter, String projectId, List<String> protocol) {
|
||||||
|
if (queryFilter != null && CollectionUtils.isNotEmpty(queryFilter.get("unCoverFrom"))) {
|
||||||
|
String unCoverFrom = queryFilter.get("unCoverFrom").getFirst();
|
||||||
|
if (ApiCoverageConstants.API_DEFINITION.equals(unCoverFrom)) {
|
||||||
|
return this.selectApiIdInCaseAndScenarioStep(projectId, protocol);
|
||||||
|
} else if (ApiCoverageConstants.API_CASE.equals(unCoverFrom)) {
|
||||||
|
return this.selectApiIdInCase(projectId, protocol);
|
||||||
|
} else if (ApiCoverageConstants.API_SCENARIO.equals(unCoverFrom)) {
|
||||||
|
return this.selectApiIdInScenarioStep(projectId, protocol, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> selectApiIdInCaseAndScenarioStep(String projectId, List<String> protocols) {
|
||||||
|
List<String> apiInCase = this.selectApiIdInCase(projectId, protocols);
|
||||||
|
List<String> apiInScenarioStep = this.selectApiIdInScenarioStep(projectId, protocols, apiInCase);
|
||||||
|
return ListUtils.union(apiInCase, apiInScenarioStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> selectApiIdInCase(String projectId, List<String> protocols) {
|
||||||
|
if (CollectionUtils.isEmpty(protocols)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return extApiTestCaseMapper.selectApiIdByProjectAndProtocol(projectId, protocols);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> selectApiIdInScenarioStep(String projectId, List<String> protocols, List<String> ignoreApiIds) {
|
||||||
|
|
||||||
|
List<String> apiInScenarioStep = new ArrayList<>(extApiScenarioStepMapper.selectResourceId(projectId, ApiScenarioStepType.API.name(), protocols));
|
||||||
|
List<String> apiCaseIdInStep = extApiScenarioStepMapper.selectResourceId(projectId, ApiScenarioStepType.API_CASE.name(), protocols);
|
||||||
|
// 如果有场景步骤中的 API 用例 ID,追加相关 API ID
|
||||||
|
if (CollectionUtils.isNotEmpty(apiCaseIdInStep)) {
|
||||||
|
List<String> apiCaseIdInScenarioStep = extApiTestCaseMapper.selectApiIdByCaseId(apiCaseIdInStep, protocols, ignoreApiIds);
|
||||||
|
apiInScenarioStep.addAll(apiCaseIdInScenarioStep);
|
||||||
|
apiCaseIdInScenarioStep = null;
|
||||||
|
apiCaseIdInStep = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (protocols.contains("HTTP")) {
|
||||||
|
List<ApiDefinition> apiDefinitions = extApiDefinitionMapper.selectBaseInfoByProjectId(projectId, List.of("HTTP"), ignoreApiIds);
|
||||||
|
List<ApiDefinition> httpApiList = apiDefinitions.stream()
|
||||||
|
.filter(api -> StringUtils.equalsIgnoreCase(api.getProtocol(), "http"))
|
||||||
|
.toList();
|
||||||
|
apiDefinitions = null;
|
||||||
|
List<String> apiInStepList = new ArrayList<>(CommonBeanFactory.getBean(ApiScenarioService.class).selectApiIdInCustomRequest(projectId, httpApiList));
|
||||||
|
apiInScenarioStep.addAll(apiInStepList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiInScenarioStep;
|
||||||
|
}
|
||||||
|
|
||||||
public List<ApiDefinitionDTO> getDocPage(ApiDefinitionPageRequest request, String userId) {
|
public List<ApiDefinitionDTO> getDocPage(ApiDefinitionPageRequest request, String userId) {
|
||||||
if (CollectionUtils.isEmpty(request.getProtocols())) {
|
if (CollectionUtils.isEmpty(request.getProtocols())) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
|
@ -907,7 +983,9 @@ public class ApiDefinitionService extends MoveNodeService {
|
||||||
public <T> List<String> getBatchApiIds(T dto, String projectId, List<String> protocols, boolean deleted, String userId) {
|
public <T> List<String> getBatchApiIds(T dto, String projectId, List<String> protocols, boolean deleted, String userId) {
|
||||||
TableBatchProcessDTO request = (TableBatchProcessDTO) dto;
|
TableBatchProcessDTO request = (TableBatchProcessDTO) dto;
|
||||||
if (request.isSelectAll() && CollectionUtils.isNotEmpty(protocols)) {
|
if (request.isSelectAll() && CollectionUtils.isNotEmpty(protocols)) {
|
||||||
List<String> ids = extApiDefinitionMapper.getIds(request, projectId, protocols, deleted);
|
List<String> includeIds = this.getQueryIncludeIds(request.getCondition().getFilter(), projectId, protocols);
|
||||||
|
List<String> excludeIds = this.getQueryExcludeIds(request.getCondition().getFilter(), projectId, protocols);
|
||||||
|
List<String> ids = extApiDefinitionMapper.getIds(request, projectId, protocols, deleted, includeIds, excludeIds);
|
||||||
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
||||||
ids.removeAll(request.getExcludeIds());
|
ids.removeAll(request.getExcludeIds());
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,7 @@ import io.metersphere.api.domain.ApiDefinition;
|
||||||
import io.metersphere.api.domain.ApiDefinitionExample;
|
import io.metersphere.api.domain.ApiDefinitionExample;
|
||||||
import io.metersphere.api.domain.ApiScenario;
|
import io.metersphere.api.domain.ApiScenario;
|
||||||
import io.metersphere.api.domain.ApiTestCase;
|
import io.metersphere.api.domain.ApiTestCase;
|
||||||
import io.metersphere.api.dto.definition.ApiCoverageDTO;
|
import io.metersphere.api.dto.definition.*;
|
||||||
import io.metersphere.api.dto.definition.ApiDefinitionAddRequest;
|
|
||||||
import io.metersphere.api.dto.definition.ApiTestCaseAddRequest;
|
|
||||||
import io.metersphere.api.dto.definition.HttpResponse;
|
|
||||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||||
import io.metersphere.api.dto.scenario.ApiScenarioAddRequest;
|
import io.metersphere.api.dto.scenario.ApiScenarioAddRequest;
|
||||||
import io.metersphere.api.dto.scenario.ApiScenarioStepRequest;
|
import io.metersphere.api.dto.scenario.ApiScenarioStepRequest;
|
||||||
|
@ -22,16 +19,19 @@ import io.metersphere.project.mapper.ProjectMapper;
|
||||||
import io.metersphere.sdk.util.CalculateUtils;
|
import io.metersphere.sdk.util.CalculateUtils;
|
||||||
import io.metersphere.sdk.util.JSON;
|
import io.metersphere.sdk.util.JSON;
|
||||||
import io.metersphere.system.base.BaseTest;
|
import io.metersphere.system.base.BaseTest;
|
||||||
|
import io.metersphere.system.controller.handler.ResultHolder;
|
||||||
import io.metersphere.system.dto.AddProjectRequest;
|
import io.metersphere.system.dto.AddProjectRequest;
|
||||||
import io.metersphere.system.log.constants.OperationLogModule;
|
import io.metersphere.system.log.constants.OperationLogModule;
|
||||||
import io.metersphere.system.service.CommonProjectService;
|
import io.metersphere.system.service.CommonProjectService;
|
||||||
import io.metersphere.system.uid.IDGenerator;
|
import io.metersphere.system.uid.IDGenerator;
|
||||||
|
import io.metersphere.system.utils.Pager;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
|
@ -222,6 +222,31 @@ public class ApiCalculateTest extends BaseTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
本次接口定义相关数据:
|
||||||
|
"GET":"/api/get-test/1",
|
||||||
|
"/api/get-test/2",
|
||||||
|
"/api/{/get-test}/3/withCase",
|
||||||
|
"/api/get-test/4/withCase",// 场景关联它的用例
|
||||||
|
"/api/get-test/5/never-compare",
|
||||||
|
"/{api}/{/get-test}/{6}",//这个在接口程度覆盖率和场景程度覆盖率计算中一定会被匹配到
|
||||||
|
"/api/get-test/{7}",// 这个在接口程度覆盖率和场景程度覆盖率计算中一定会被匹配到
|
||||||
|
"/api/get-test/8",// 场景关联它的自定义请求
|
||||||
|
"/api/get-test/9",// 场景关联这个接口
|
||||||
|
"/api/get-test/10"
|
||||||
|
|
||||||
|
"POST":"/post/api/test/1",
|
||||||
|
"/post/api/test/2",
|
||||||
|
"/post/api/{test}/3/withCase",
|
||||||
|
"/post/api/test/4/withCase",// 场景关联它的用例
|
||||||
|
"/post/api/test/5/never-compare",
|
||||||
|
"/{post}/{api}/{/get-test}/{6}", //这个在接口程度覆盖率和场景程度覆盖率计算中一定会被匹配到
|
||||||
|
"/post/api/test/{7}", // 这个在接口程度覆盖率和场景程度覆盖率计算中一定会被匹配到
|
||||||
|
"/post/api/test/8", // 场景关联它的自定义请求
|
||||||
|
"/post/api/test/9", // 场景关联这个接口
|
||||||
|
"/post/api/test/10"
|
||||||
|
|
||||||
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void calculateTest() throws Exception {
|
public void calculateTest() throws Exception {
|
||||||
ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample();
|
ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample();
|
||||||
|
@ -244,6 +269,67 @@ public class ApiCalculateTest extends BaseTest {
|
||||||
Assertions.assertEquals(apiCoverageDTO.getApiCoverage(), CalculateUtils.reportPercentage(apiCoverageDTO.getCoverWithApiDefinition(), apiCoverageDTO.getAllApiCount()));
|
Assertions.assertEquals(apiCoverageDTO.getApiCoverage(), CalculateUtils.reportPercentage(apiCoverageDTO.getCoverWithApiDefinition(), apiCoverageDTO.getAllApiCount()));
|
||||||
|
|
||||||
Assertions.assertEquals("0.00%", CalculateUtils.reportPercentage(0, 0));
|
Assertions.assertEquals("0.00%", CalculateUtils.reportPercentage(0, 0));
|
||||||
|
|
||||||
|
// 表格筛选测试
|
||||||
|
ApiDefinitionPageRequest request = new ApiDefinitionPageRequest();
|
||||||
|
request.setProjectId(project.getId());
|
||||||
|
request.setCurrent(1);
|
||||||
|
request.setPageSize(10);
|
||||||
|
request.setDeleted(false);
|
||||||
|
request.setSort(Map.of("createTime", "asc"));
|
||||||
|
request.setProtocols(List.of("HTTP"));
|
||||||
|
Map<String, List<String>> filters = new HashMap<>();
|
||||||
|
request.setSort(Map.of());
|
||||||
|
filters.put("coverFrom", List.of(ApiCoverageConstants.API_DEFINITION));
|
||||||
|
request.setFilter(filters);
|
||||||
|
|
||||||
|
MvcResult pageResult = this.requestPostWithOkAndReturn("/api/definition/page", request);
|
||||||
|
|
||||||
|
Pager<Object> result = JSON.parseObject(JSON.toJSONString(JSON.parseObject(
|
||||||
|
pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()), Pager.class);
|
||||||
|
Assertions.assertEquals(result.getTotal(), 10);
|
||||||
|
|
||||||
|
filters = new HashMap<>();
|
||||||
|
filters.put("unCoverFrom", List.of(ApiCoverageConstants.API_DEFINITION));
|
||||||
|
request.setFilter(filters);
|
||||||
|
pageResult = this.requestPostWithOkAndReturn("/api/definition/page", request);
|
||||||
|
result = JSON.parseObject(JSON.toJSONString(JSON.parseObject(
|
||||||
|
pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()), Pager.class);
|
||||||
|
Assertions.assertEquals(result.getTotal(), 10);
|
||||||
|
|
||||||
|
|
||||||
|
filters = new HashMap<>();
|
||||||
|
filters.put("coverFrom", List.of(ApiCoverageConstants.API_CASE));
|
||||||
|
request.setFilter(filters);
|
||||||
|
pageResult = this.requestPostWithOkAndReturn("/api/definition/page", request);
|
||||||
|
result = JSON.parseObject(JSON.toJSONString(JSON.parseObject(
|
||||||
|
pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()), Pager.class);
|
||||||
|
Assertions.assertEquals(result.getTotal(), 4);
|
||||||
|
|
||||||
|
filters = new HashMap<>();
|
||||||
|
filters.put("unCoverFrom", List.of(ApiCoverageConstants.API_CASE));
|
||||||
|
request.setFilter(filters);
|
||||||
|
pageResult = this.requestPostWithOkAndReturn("/api/definition/page", request);
|
||||||
|
result = JSON.parseObject(JSON.toJSONString(JSON.parseObject(
|
||||||
|
pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()), Pager.class);
|
||||||
|
Assertions.assertEquals(result.getTotal(), 16);
|
||||||
|
|
||||||
|
|
||||||
|
filters = new HashMap<>();
|
||||||
|
filters.put("coverFrom", List.of(ApiCoverageConstants.API_SCENARIO));
|
||||||
|
request.setFilter(filters);
|
||||||
|
pageResult = this.requestPostWithOkAndReturn("/api/definition/page", request);
|
||||||
|
result = JSON.parseObject(JSON.toJSONString(JSON.parseObject(
|
||||||
|
pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()), Pager.class);
|
||||||
|
Assertions.assertEquals(result.getTotal(), 8);
|
||||||
|
|
||||||
|
filters = new HashMap<>();
|
||||||
|
filters.put("unCoverFrom", List.of(ApiCoverageConstants.API_SCENARIO));
|
||||||
|
request.setFilter(filters);
|
||||||
|
pageResult = this.requestPostWithOkAndReturn("/api/definition/page", request);
|
||||||
|
result = JSON.parseObject(JSON.toJSONString(JSON.parseObject(
|
||||||
|
pageResult.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()), Pager.class);
|
||||||
|
Assertions.assertEquals(result.getTotal(), 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue