refactor(接口测试): 优化接口报告查询逻辑

This commit is contained in:
wxg0103 2024-03-18 20:15:04 +08:00 committed by 刘瑞斌
parent 488a93ea2c
commit c9063b4196
6 changed files with 132 additions and 27 deletions

View File

@ -72,6 +72,11 @@ public class ApiReportDetailDTO {
*/
@Schema(description = "结果内容详情")
private RequestResult content;
/**
* 结果内容详情
*/
@Schema(description = "控制台")
private String console;
}

View File

@ -14,6 +14,7 @@ import io.metersphere.sdk.util.Translator;
import io.metersphere.system.service.UserLoginService;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
@ -43,6 +44,10 @@ public class ApiReportService {
private ApiReportDetailMapper apiReportDetailMapper;
@Resource
private ApiReportLogService apiReportLogService;
@Resource
private ApiTestCaseRecordMapper apiTestCaseRecordMapper;
@Resource
private ApiReportLogMapper apiReportLogMapper;
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
@ -159,11 +164,25 @@ public class ApiReportService {
ApiReport apiReport = checkResource(id);
BeanUtils.copyBean(apiReportDTO, apiReport);
//需要查询出所有的步骤
List<ApiReportStepDTO> apiReportSteps = extApiReportMapper.selectStepsByReportId(id);
if (CollectionUtils.isEmpty(apiReportSteps)) {
if (BooleanUtils.isTrue(apiReport.getIntegrated())) {
List<ApiReportStepDTO> apiReportSteps = extApiReportMapper.selectStepsByReportId(id);
if (CollectionUtils.isEmpty(apiReportSteps)) {
throw new MSException(Translator.get("api_case_report_not_exist"));
}
apiReportSteps.sort(Comparator.comparingLong(ApiReportStepDTO::getSort));
apiReportDTO.setChildren(apiReportSteps);
return apiReportDTO;
}
ApiTestCaseRecordExample example = new ApiTestCaseRecordExample();
example.createCriteria().andApiReportIdEqualTo(id);
List<ApiTestCaseRecord> apiTestCaseRecords = apiTestCaseRecordMapper.selectByExample(example);
if (CollectionUtils.isEmpty(apiTestCaseRecords)) {
throw new MSException(Translator.get("api_case_report_not_exist"));
}
apiReportSteps.sort(Comparator.comparingLong(ApiReportStepDTO::getSort));
ApiReportStepDTO apiReportStepDTO = new ApiReportStepDTO();
apiReportStepDTO.setStepId(apiTestCaseRecords.getFirst().getApiTestCaseId());
List<ApiReportStepDTO> apiReportSteps = new ArrayList<>();
apiReportSteps.add(apiReportStepDTO);
apiReportDTO.setChildren(apiReportSteps);
return apiReportDTO;
}
@ -171,10 +190,17 @@ public class ApiReportService {
public List<ApiReportDetailDTO> getDetail(String stepId, String reportId) {
List<ApiReportDetail> apiReportDetails = checkResourceStep(stepId, reportId);
List<ApiReportDetailDTO> results = new ArrayList<>();
//查询console
ApiReportLogExample example = new ApiReportLogExample();
example.createCriteria().andReportIdEqualTo(reportId);
List<ApiReportLog> apiReportLogs = apiReportLogMapper.selectByExampleWithBLOBs(example);
apiReportDetails.forEach(apiReportDetail -> {
ApiReportDetailDTO apiReportDetailDTO = new ApiReportDetailDTO();
BeanUtils.copyBean(apiReportDetailDTO, apiReportDetail);
apiReportDetailDTO.setContent(ApiDataUtils.parseObject(new String(apiReportDetail.getContent()), RequestResult.class));
if (CollectionUtils.isNotEmpty(apiReportLogs)) {
apiReportDetailDTO.setConsole(new String(apiReportLogs.getFirst().getConsole()));
}
results.add(apiReportDetailDTO);
});
return results;

View File

@ -1,10 +1,7 @@
package io.metersphere.api.controller;
import io.metersphere.api.constants.ShareInfoType;
import io.metersphere.api.domain.ApiReport;
import io.metersphere.api.domain.ApiReportDetail;
import io.metersphere.api.domain.ApiReportStep;
import io.metersphere.api.domain.ApiTestCaseRecord;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.definition.ApiReportBatchRequest;
import io.metersphere.api.dto.definition.ApiReportDTO;
import io.metersphere.api.dto.definition.ApiReportDetailDTO;
@ -12,6 +9,7 @@ import io.metersphere.api.dto.definition.ApiReportPageRequest;
import io.metersphere.api.dto.scenario.ApiScenarioDTO;
import io.metersphere.api.dto.share.ShareInfoDTO;
import io.metersphere.api.mapper.ApiReportDetailMapper;
import io.metersphere.api.mapper.ApiReportLogMapper;
import io.metersphere.api.mapper.ApiReportMapper;
import io.metersphere.api.service.definition.ApiReportService;
import io.metersphere.api.utils.ApiDataUtils;
@ -27,6 +25,7 @@ import io.metersphere.sdk.mapper.ShareInfoMapper;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.*;
@ -60,6 +59,8 @@ public class ApiReportControllerTests extends BaseTest {
private ShareInfoMapper shareInfoMapper;
@Resource
private ProjectApplicationMapper projectApplicationMapper;
@Resource
private ApiReportLogMapper apiReportLogMapper;
private static final String BASIC = "/api/report/case";
private static final String PAGE = BASIC + "/page";
@ -250,6 +251,7 @@ public class ApiReportControllerTests extends BaseTest {
apiReport.setRunMode("api-run-mode");
apiReport.setStatus(ApiReportStatus.SUCCESS.name());
apiReport.setTriggerMode("api-trigger-mode");
apiReport.setIntegrated(true);
reports.add(apiReport);
ApiTestCaseRecord record = new ApiTestCaseRecord();
record.setApiTestCaseId("api-resource-id");
@ -273,14 +275,81 @@ public class ApiReportControllerTests extends BaseTest {
Assertions.assertNotNull(apiReportDTO);
Assertions.assertEquals(apiReportDTO.getId(), "test-report-id");
reports = new ArrayList<>();
apiReport = new ApiReport();
apiReport.setId("test-report-id-no-step-true");
apiReport.setProjectId(DEFAULT_PROJECT_ID);
apiReport.setName("test-report-name");
apiReport.setStartTime(System.currentTimeMillis());
apiReport.setCreateUser("admin");
apiReport.setUpdateUser("admin");
apiReport.setUpdateTime(System.currentTimeMillis());
apiReport.setPoolId("api-pool-id");
apiReport.setEnvironmentId("api-environment-id");
apiReport.setRunMode("api-run-mode");
apiReport.setStatus(ApiReportStatus.SUCCESS.name());
apiReport.setTriggerMode("api-trigger-mode");
apiReport.setIntegrated(true);
reports.add(apiReport);
apiReportService.insertApiReport(reports, new ArrayList<>());
mockMvc.perform(getRequestBuilder(GET + "test-report-id-no-step-true"))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().is5xxServerError());
mockMvc.perform(getRequestBuilder(GET + "test"))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().is5xxServerError());
mockMvc.perform(getRequestBuilder(GET + "api-report-id10"))
reports = new ArrayList<>();
apiReport = new ApiReport();
apiReport.setId("test-report-id-no-step");
apiReport.setProjectId(DEFAULT_PROJECT_ID);
apiReport.setName("test-report-name");
apiReport.setStartTime(System.currentTimeMillis());
apiReport.setCreateUser("admin");
apiReport.setUpdateUser("admin");
apiReport.setUpdateTime(System.currentTimeMillis());
apiReport.setPoolId("api-pool-id");
apiReport.setEnvironmentId("api-environment-id");
apiReport.setRunMode("api-run-mode");
apiReport.setStatus(ApiReportStatus.SUCCESS.name());
apiReport.setTriggerMode("api-trigger-mode");
apiReport.setIntegrated(false);
reports.add(apiReport);
record = new ApiTestCaseRecord();
record.setApiTestCaseId("api-resource-id");
record.setApiReportId(apiReport.getId());
apiReportService.insertApiReport(reports, List.of(record));
mockMvc.perform(getRequestBuilder(GET + "test-report-id-no-step"))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().is2xxSuccessful());
reports = new ArrayList<>();
apiReport = new ApiReport();
apiReport.setId("test-report-id-no-step-no-record");
apiReport.setProjectId(DEFAULT_PROJECT_ID);
apiReport.setName("test-report-name");
apiReport.setStartTime(System.currentTimeMillis());
apiReport.setCreateUser("admin");
apiReport.setUpdateUser("admin");
apiReport.setUpdateTime(System.currentTimeMillis());
apiReport.setPoolId("api-pool-id");
apiReport.setEnvironmentId("api-environment-id");
apiReport.setRunMode("api-run-mode");
apiReport.setStatus(ApiReportStatus.SUCCESS.name());
apiReport.setTriggerMode("api-trigger-mode");
apiReport.setIntegrated(false);
reports.add(apiReport);
apiReportService.insertApiReport(reports, new ArrayList<>());
mockMvc.perform(getRequestBuilder(GET + "test-report-id-no-step-no-record"))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().is5xxServerError());
// @@校验权限
requestGetPermissionTest(PermissionConstants.PROJECT_API_REPORT_READ, GET + "api-report-id0");
}
@ -302,6 +371,11 @@ public class ApiReportControllerTests extends BaseTest {
reports.add(apiReportDetail);
}
apiReportDetailMapper.batchInsert(reports);
ApiReportLog apiReportLog = new ApiReportLog();
apiReportLog.setReportId("test-report-id");
apiReportLog.setId(IDGenerator.nextStr());
apiReportLog.setConsole("test-console".getBytes());
apiReportLogMapper.insert(apiReportLog);
MvcResult mvcResult = this.requestGetWithOk(DETAIL + "test-report-id" + "/" + "test-report-step-id1")
.andReturn();

View File

@ -25,16 +25,16 @@ export const requestBodyTypeMap = {
};
// 请求/响应头选项
export const responseHeaderOption = [
{ label: 'Accept', value: 'accept' },
{ label: 'Accept-Encoding', value: 'acceptEncoding' },
{ label: 'Accept-Language', value: 'acceptLanguage' },
{ label: 'Cache-Control', value: 'cacheControl' },
{ label: 'Content-Type', value: 'contentType' },
{ label: 'Content-Length', value: 'contentLength' },
{ label: 'User-Agent', value: 'userAgent' },
{ label: 'Referer', value: 'referer' },
{ label: 'Cookie', value: 'cookie' },
{ label: 'Authorization', value: 'authorization' },
{ label: 'If-None-Match', value: 'ifNoneMatch' },
{ label: 'If-Modified-Since', value: 'ifModifiedSince' },
{ label: 'Accept', value: 'Accept' },
{ label: 'Accept-Encoding', value: 'Accept-Encoding' },
{ label: 'Accept-Language', value: 'Accept-Language' },
{ label: 'Cache-Control', value: 'Cache-Control' },
{ label: 'Content-Type', value: 'Content-Type' },
{ label: 'Content-Length', value: 'Content-Length' },
{ label: 'User-Agent', value: 'User-Agent' },
{ label: 'Referer', value: 'Referer' },
{ label: 'Cookie', value: 'Cookie' },
{ label: 'Authorization', value: 'Authorization' },
{ label: 'If-None-Match', value: 'If-None-Match' },
{ label: 'If-Modified-Since', value: 'If-Modified-Since' },
];

View File

@ -394,4 +394,5 @@ export interface ApiCaseExecuteHistoryItem {
startTime: number;
status: string;
triggerMode: string;
deleted: boolean;
}

View File

@ -226,9 +226,8 @@
async function loadedReport(detail: Record<string, any>) {
if (detail.id) {
if (detail.children && detail.children.length > 0) {
const { stepId } = detail.children[0].stepId;
try {
const caseReportDetail = getCaseReportDetail(detail.id, stepId);
const caseReportDetail = getCaseReportDetail(detail.id, detail.children[0].stepId);
loadedReportDetail(await caseReportDetail);
} catch (e) {
console.error(e);
@ -237,10 +236,10 @@
}
}
function showResult(record: ApiCaseExecuteHistoryItem) {
async function showResult(record: ApiCaseExecuteHistoryItem) {
try {
const result = getReportById(record.id);
loadedReport(result);
const result = await getReportById(record.id);
await loadedReport(result);
} catch (error) {
console.error(error);
}
@ -259,8 +258,8 @@
}
.history-table-before {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
align-items: center;
flex-direction: row;
}
</style>