fix(接口测试): 接口定义用例数统计和模块显示不正确
This commit is contained in:
parent
1248028981
commit
5f6299b8d5
|
@ -3,7 +3,6 @@ package io.metersphere.api.controller.definition;
|
|||
import com.fasterxml.jackson.databind.node.TextNode;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.api.constants.ApiResourceType;
|
||||
import io.metersphere.api.domain.ApiDefinition;
|
||||
import io.metersphere.api.dto.ReferenceDTO;
|
||||
import io.metersphere.api.dto.ReferenceRequest;
|
||||
|
|
|
@ -45,6 +45,9 @@ public class ApiDefinitionDTO extends ApiDefinition{
|
|||
@Schema(description = "是否关注")
|
||||
private Boolean follow;
|
||||
|
||||
@Schema(description = "模块名称")
|
||||
private String moduleName;
|
||||
|
||||
@Schema(description = "自定义字段集合")
|
||||
private List<ApiDefinitionCustomFieldDTO> customFields;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import jakarta.validation.constraints.NotBlank;
|
|||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
||||
|
@ -81,6 +82,10 @@ public class CsvVariable {
|
|||
return StringUtils.isNotBlank(name) && file != null;
|
||||
}
|
||||
|
||||
public boolean isEnable() {
|
||||
return BooleanUtils.isTrue(enable);
|
||||
}
|
||||
|
||||
public enum CsvEncodingType implements ValueEnum {
|
||||
UTF8("UTF-8"), UFT16("UTF-16"), ISO885915("ISO-8859-15"), US_ASCII("US-ASCII"), GBK("GBK");
|
||||
private String value;
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.api.mapper;
|
|||
|
||||
import io.metersphere.api.domain.ApiDefinition;
|
||||
import io.metersphere.api.domain.ApiDefinitionCustomField;
|
||||
import io.metersphere.api.domain.ApiTestCase;
|
||||
import io.metersphere.api.dto.ApiDefinitionExecuteInfo;
|
||||
import io.metersphere.api.dto.ReferenceDTO;
|
||||
import io.metersphere.api.dto.ReferenceRequest;
|
||||
|
@ -23,7 +24,7 @@ public interface ExtApiDefinitionMapper {
|
|||
|
||||
List<ApiDefinitionDTO> listDoc(@Param("request") ApiDefinitionDocRequest request);
|
||||
|
||||
List<ApiCaseComputeDTO> selectApiCaseByIdsAndStatusIsNotTrash(@Param("ids") List<String> ids, @Param("projectId") String projectId);
|
||||
List<ApiTestCase> selectNotInTrashCaseIdsByApiIds(@Param("apiIds") List<String> apiIds);
|
||||
|
||||
Long getPos(@Param("projectId") String projectId);
|
||||
|
||||
|
|
|
@ -46,27 +46,11 @@
|
|||
<include refid="queryDocWhereCondition"/>
|
||||
</select>
|
||||
|
||||
<select id="selectApiCaseByIdsAndStatusIsNotTrash"
|
||||
resultType="io.metersphere.api.dto.definition.ApiCaseComputeDTO">
|
||||
select
|
||||
t1.api_definition_id apiDefinitionId,
|
||||
count( t1.id ) caseTotal,
|
||||
SUM( CASE WHEN t2.`status` = 'SUCCESS' THEN 1 ELSE 0 END ) AS `success`,
|
||||
SUM( CASE WHEN t2.`status` = 'ERROR' THEN 1 ELSE 0 END ) AS `error`,
|
||||
SUM( CASE WHEN t2.`status` = 'FAKE_ERROR' THEN 1 ELSE 0 END ) AS `fakeError`,
|
||||
CONCAT( FORMAT( SUM( IF ( t2.`status` = 'SUCCESS', 1, 0 ))/ COUNT( t1.id )* 100, 2 ), '%' ) casePassRate
|
||||
FROM
|
||||
api_test_case t1
|
||||
LEFT JOIN api_test_case_record t3 on t1.id = t3.api_test_case_id
|
||||
LEFT JOIN api_report t2 ON t2.id = t3.api_report_id
|
||||
WHERE
|
||||
t1.project_id = #{projectId} and t1.deleted = 0
|
||||
|
||||
GROUP BY
|
||||
t1.api_definition_id
|
||||
HAVING
|
||||
t1.api_definition_id IN
|
||||
<foreach collection="ids" item="value" separator="," open="(" close=")">
|
||||
<select id="selectNotInTrashCaseIdsByApiIds" resultType="io.metersphere.api.domain.ApiTestCase">
|
||||
select atc.id, atc.api_definition_id
|
||||
FROM api_test_case atc
|
||||
WHERE atc.deleted = 0 and atc.api_definition_id IN
|
||||
<foreach collection="apiIds" item="value" separator="," open="(" close=")">
|
||||
#{value}
|
||||
</foreach>
|
||||
</select>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.metersphere.api.mapper;
|
||||
|
||||
import io.metersphere.api.domain.ApiDefinitionModule;
|
||||
import io.metersphere.api.dto.debug.ApiTreeNode;
|
||||
import io.metersphere.api.dto.definition.ApiModuleRequest;
|
||||
import io.metersphere.project.dto.ModuleCountDTO;
|
||||
|
@ -36,4 +37,6 @@ public interface ExtApiDefinitionModuleMapper {
|
|||
List<BaseTreeNode> selectBaseByIds(@Param("ids") List<String> ids);
|
||||
|
||||
List<String> getModuleIdsByParentIds(@Param("parentIds") List<String> parentIds);
|
||||
|
||||
List<ApiDefinitionModule> getNameInfoByIds(@Param("ids") List<String> ids);
|
||||
}
|
||||
|
|
|
@ -123,6 +123,14 @@
|
|||
#{parentId}
|
||||
</foreach>
|
||||
</select>
|
||||
<select id="getNameInfoByIds" resultType="io.metersphere.api.domain.ApiDefinitionModule">
|
||||
SELECT id, name
|
||||
FROM api_definition_module
|
||||
WHERE id IN
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<sql id="api_request">
|
||||
<where>
|
||||
|
|
|
@ -47,7 +47,7 @@ public class MsCsvChildPreConverter extends AbstractJmeterElementConverter<Abstr
|
|||
}
|
||||
|
||||
private static void addCsvDataSet(HashTree tree, String shareMode, CsvVariable csvVariable) {
|
||||
if (!csvVariable.isValid()) {
|
||||
if (!csvVariable.isValid() || !csvVariable.isEnable()) {
|
||||
return;
|
||||
}
|
||||
// 执行机执行文件存放的缓存目录
|
||||
|
|
|
@ -25,10 +25,7 @@ import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
|||
import io.metersphere.project.service.EnvironmentService;
|
||||
import io.metersphere.project.service.MoveNodeService;
|
||||
import io.metersphere.project.service.ProjectService;
|
||||
import io.metersphere.sdk.constants.ApiFileResourceType;
|
||||
import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.constants.*;
|
||||
import io.metersphere.sdk.domain.OperationLogBlob;
|
||||
import io.metersphere.sdk.dto.api.task.TaskRequestDTO;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
|
@ -79,6 +76,9 @@ public class ApiDefinitionService extends MoveNodeService {
|
|||
@Resource
|
||||
private ExtApiDefinitionMapper extApiDefinitionMapper;
|
||||
|
||||
@Resource
|
||||
private ExtApiDefinitionModuleMapper extApiDefinitionModuleMapper;
|
||||
|
||||
@Resource
|
||||
private ApiDefinitionFollowerMapper apiDefinitionFollowerMapper;
|
||||
|
||||
|
@ -117,8 +117,6 @@ public class ApiDefinitionService extends MoveNodeService {
|
|||
|
||||
@Resource
|
||||
private ApiDefinitionLogService apiDefinitionLogService;
|
||||
@Resource
|
||||
private ApiDefinitionImportUtilService apiDefinitionImportUtilService;
|
||||
|
||||
@Resource
|
||||
private ApiDefinitionMockService apiDefinitionMockService;
|
||||
|
@ -136,9 +134,7 @@ public class ApiDefinitionService extends MoveNodeService {
|
|||
public List<ApiDefinitionDTO> getApiDefinitionPage(ApiDefinitionPageRequest request, String userId) {
|
||||
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request, userId);
|
||||
List<ApiDefinitionDTO> list = extApiDefinitionMapper.list(request);
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
processApiDefinitions(list, request.getProjectId());
|
||||
}
|
||||
processApiDefinitions(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -437,45 +433,42 @@ public class ApiDefinitionService extends MoveNodeService {
|
|||
}
|
||||
}
|
||||
|
||||
private void processApiDefinitions(List<ApiDefinitionDTO> list, String projectId) {
|
||||
private void processApiDefinitions(List<ApiDefinitionDTO> list) {
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
Set<String> userIds = extractUserIds(list);
|
||||
Map<String, String> userMap = userLoginService.getUserNameMap(new ArrayList<>(userIds));
|
||||
/* List<String> apiDefinitionIds = list.stream().map(ApiDefinitionDTO::getId).toList();
|
||||
List<ApiCaseComputeDTO> apiCaseComputeList = extApiDefinitionMapper.selectApiCaseByIdsAndStatusIsNotTrash(apiDefinitionIds, projectId);
|
||||
Map<String, ApiCaseComputeDTO> resultMap = apiCaseComputeList.stream().collect(Collectors.toMap(ApiCaseComputeDTO::getApiDefinitionId, Function.identity()));
|
||||
|
||||
List<ApiDefinitionCustomFieldDTO> customFields = extApiDefinitionCustomFieldMapper.getApiCustomFields(apiDefinitionIds, projectId);
|
||||
Map<String, List<ApiDefinitionCustomFieldDTO>> customFieldMap = customFields.stream().collect(Collectors.groupingBy(ApiDefinitionCustomFieldDTO::getApiId));
|
||||
*/
|
||||
List<String> apiDefinitionIds = list.stream().map(ApiDefinitionDTO::getId).toList();
|
||||
List<ApiTestCase> apiCaseList = extApiDefinitionMapper.selectNotInTrashCaseIdsByApiIds(apiDefinitionIds);
|
||||
Map<String, List<ApiTestCase>> apiCaseMap = apiCaseList.stream().
|
||||
collect(Collectors.groupingBy(ApiTestCase::getApiDefinitionId));
|
||||
|
||||
List<String> moduleIds = list.stream().map(ApiDefinitionDTO::getModuleId).toList();
|
||||
List<ApiDefinitionModule> modules = extApiDefinitionModuleMapper.getNameInfoByIds(moduleIds);
|
||||
Map<String, String> moduleNameMap = modules.stream()
|
||||
.collect(Collectors.toMap(ApiDefinitionModule::getId, ApiDefinitionModule::getName));
|
||||
|
||||
list.forEach(item -> {
|
||||
// Convert User IDs to Names
|
||||
item.setCreateUserName(userMap.get(item.getCreateUser()));
|
||||
item.setDeleteUserName(userMap.get(item.getDeleteUser()));
|
||||
item.setUpdateUserName(userMap.get(item.getUpdateUser()));
|
||||
|
||||
// Custom Fields
|
||||
/*item.setCustomFields(customFieldMap.get(item.getId()));
|
||||
|
||||
// Calculate API Case Metrics
|
||||
ApiCaseComputeDTO apiCaseComputeDTO = resultMap.get(item.getId());
|
||||
if (apiCaseComputeDTO != null) {
|
||||
item.setCaseTotal(apiCaseComputeDTO.getCaseTotal());
|
||||
item.setCasePassRate(apiCaseComputeDTO.getCasePassRate());
|
||||
// 状态优先级 未执行,未通过,误报(FAKE_ERROR),通过
|
||||
if ((apiCaseComputeDTO.getError() + apiCaseComputeDTO.getFakeError() + apiCaseComputeDTO.getSuccess()) < apiCaseComputeDTO.getCaseTotal()) {
|
||||
item.setCaseStatus(ApiReportStatus.PENDING.name());
|
||||
} else if (apiCaseComputeDTO.getError() > 0) {
|
||||
item.setCaseStatus(ApiReportStatus.ERROR.name());
|
||||
} else if (apiCaseComputeDTO.getFakeError() > 0) {
|
||||
item.setCaseStatus(ApiReportStatus.FAKE_ERROR.name());
|
||||
} else {
|
||||
item.setCaseStatus(ApiReportStatus.SUCCESS.name());
|
||||
}
|
||||
List<ApiTestCase> apiTestCases = apiCaseMap.get(item.getId());
|
||||
if (apiTestCases != null) {
|
||||
item.setCaseTotal(apiTestCases.size());
|
||||
} else {
|
||||
item.setCaseTotal(0);
|
||||
item.setCasePassRate("-");
|
||||
item.setCaseStatus("-");
|
||||
}*/
|
||||
}
|
||||
|
||||
if (moduleNameMap.get(item.getModuleId()) == null) {
|
||||
item.setModuleName(Translator.get("api_unplanned_request"));
|
||||
} else {
|
||||
item.setModuleName(moduleNameMap.get(item.getModuleId()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,9 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
@Resource
|
||||
private ExtApiTestCaseMapper extApiTestCaseMapper;
|
||||
|
||||
@Resource
|
||||
private ApiTestCaseMapper apiTestCaseMapper;
|
||||
|
||||
@Resource
|
||||
private ApiDefinitionModuleMapper apiDefinitionModuleMapper;
|
||||
|
||||
|
@ -879,14 +882,35 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
@Order(9)
|
||||
@Sql(scripts = {"/dml/init_api_definition.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
|
||||
public void getPage() throws Exception {
|
||||
doApiDefinitionPage("All", PAGE);
|
||||
doApiDefinitionPage("KEYWORD", PAGE);
|
||||
assertPateDate(doApiDefinitionPage("All", PAGE));
|
||||
assertPateDate(doApiDefinitionPage("KEYWORD", PAGE));
|
||||
//doApiDefinitionPage("FILTER", PAGE);
|
||||
doApiDefinitionPage("COMBINE", PAGE);
|
||||
doApiDefinitionPage("DELETED", PAGE);
|
||||
assertPateDate(doApiDefinitionPage("COMBINE", PAGE));
|
||||
assertPateDate(doApiDefinitionPage("DELETED", PAGE));
|
||||
}
|
||||
|
||||
private void doApiDefinitionPage(String search, String url) throws Exception {
|
||||
private void assertPateDate(Pager pageData) {
|
||||
List<ApiDefinitionDTO> apiDefinitions = ApiDataUtils.parseArray(JSON.toJSONString(pageData.getList()), ApiDefinitionDTO.class);
|
||||
if (CollectionUtils.isNotEmpty(apiDefinitions)) {
|
||||
ApiDefinitionDTO apiDefinitionDTO = apiDefinitions.get(0);
|
||||
// 判断用例数是否正确
|
||||
ApiTestCaseExample example = new ApiTestCaseExample();
|
||||
example.createCriteria()
|
||||
.andApiDefinitionIdEqualTo(apiDefinitionDTO.getId())
|
||||
.andDeletedEqualTo(false);
|
||||
List<ApiTestCase> apiTestCases = apiTestCaseMapper.selectByExample(example);
|
||||
Assertions.assertEquals(apiDefinitionDTO.getCaseTotal(), apiTestCases.size());
|
||||
// 判断模块名是否正确
|
||||
ApiDefinitionModule apiDefinitionModule = apiDefinitionModuleMapper.selectByPrimaryKey(apiDefinitionDTO.getModuleId());
|
||||
if (apiDefinitionModule == null) {
|
||||
Assertions.assertEquals(apiDefinitionDTO.getModuleName(), Translator.get("api_unplanned_request"));
|
||||
} else {
|
||||
Assertions.assertEquals(apiDefinitionDTO.getModuleName(), apiDefinitionModule.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Pager doApiDefinitionPage(String search, String url) throws Exception {
|
||||
ApiDefinitionPageRequest request = new ApiDefinitionPageRequest();
|
||||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
request.setCurrent(1);
|
||||
|
@ -905,19 +929,15 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
}
|
||||
|
||||
MvcResult mvcResult = this.requestPostWithOkAndReturn(url, request);
|
||||
// 获取返回值
|
||||
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
// 返回请求正常
|
||||
Assertions.assertNotNull(resultHolder);
|
||||
Pager<?> pageData = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
|
||||
Pager pageData = getResultData(mvcResult, Pager.class);
|
||||
// 返回值不为空
|
||||
Assertions.assertNotNull(pageData);
|
||||
// 返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(pageData.getCurrent(), request.getCurrent());
|
||||
// 返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= request.getPageSize());
|
||||
|
||||
return pageData;
|
||||
}
|
||||
|
||||
private void configureAllSearch(ApiDefinitionPageRequest request) {
|
||||
|
|
Loading…
Reference in New Issue