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

View File

@ -1,10 +1,7 @@
package io.metersphere.api.controller; package io.metersphere.api.controller;
import io.metersphere.api.constants.ShareInfoType; import io.metersphere.api.constants.ShareInfoType;
import io.metersphere.api.domain.ApiReport; import io.metersphere.api.domain.*;
import io.metersphere.api.domain.ApiReportDetail;
import io.metersphere.api.domain.ApiReportStep;
import io.metersphere.api.domain.ApiTestCaseRecord;
import io.metersphere.api.dto.definition.ApiReportBatchRequest; import io.metersphere.api.dto.definition.ApiReportBatchRequest;
import io.metersphere.api.dto.definition.ApiReportDTO; import io.metersphere.api.dto.definition.ApiReportDTO;
import io.metersphere.api.dto.definition.ApiReportDetailDTO; 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.scenario.ApiScenarioDTO;
import io.metersphere.api.dto.share.ShareInfoDTO; import io.metersphere.api.dto.share.ShareInfoDTO;
import io.metersphere.api.mapper.ApiReportDetailMapper; import io.metersphere.api.mapper.ApiReportDetailMapper;
import io.metersphere.api.mapper.ApiReportLogMapper;
import io.metersphere.api.mapper.ApiReportMapper; import io.metersphere.api.mapper.ApiReportMapper;
import io.metersphere.api.service.definition.ApiReportService; import io.metersphere.api.service.definition.ApiReportService;
import io.metersphere.api.utils.ApiDataUtils; 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.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.controller.handler.ResultHolder;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.Pager; import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.junit.jupiter.api.*; import org.junit.jupiter.api.*;
@ -60,6 +59,8 @@ public class ApiReportControllerTests extends BaseTest {
private ShareInfoMapper shareInfoMapper; private ShareInfoMapper shareInfoMapper;
@Resource @Resource
private ProjectApplicationMapper projectApplicationMapper; private ProjectApplicationMapper projectApplicationMapper;
@Resource
private ApiReportLogMapper apiReportLogMapper;
private static final String BASIC = "/api/report/case"; private static final String BASIC = "/api/report/case";
private static final String PAGE = BASIC + "/page"; private static final String PAGE = BASIC + "/page";
@ -250,6 +251,7 @@ public class ApiReportControllerTests extends BaseTest {
apiReport.setRunMode("api-run-mode"); apiReport.setRunMode("api-run-mode");
apiReport.setStatus(ApiReportStatus.SUCCESS.name()); apiReport.setStatus(ApiReportStatus.SUCCESS.name());
apiReport.setTriggerMode("api-trigger-mode"); apiReport.setTriggerMode("api-trigger-mode");
apiReport.setIntegrated(true);
reports.add(apiReport); reports.add(apiReport);
ApiTestCaseRecord record = new ApiTestCaseRecord(); ApiTestCaseRecord record = new ApiTestCaseRecord();
record.setApiTestCaseId("api-resource-id"); record.setApiTestCaseId("api-resource-id");
@ -273,14 +275,81 @@ public class ApiReportControllerTests extends BaseTest {
Assertions.assertNotNull(apiReportDTO); Assertions.assertNotNull(apiReportDTO);
Assertions.assertEquals(apiReportDTO.getId(), "test-report-id"); 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")) mockMvc.perform(getRequestBuilder(GET + "test"))
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().is5xxServerError()); .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(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(status().is5xxServerError()); .andExpect(status().is5xxServerError());
// @@校验权限 // @@校验权限
requestGetPermissionTest(PermissionConstants.PROJECT_API_REPORT_READ, GET + "api-report-id0"); requestGetPermissionTest(PermissionConstants.PROJECT_API_REPORT_READ, GET + "api-report-id0");
} }
@ -302,6 +371,11 @@ public class ApiReportControllerTests extends BaseTest {
reports.add(apiReportDetail); reports.add(apiReportDetail);
} }
apiReportDetailMapper.batchInsert(reports); 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") MvcResult mvcResult = this.requestGetWithOk(DETAIL + "test-report-id" + "/" + "test-report-step-id1")
.andReturn(); .andReturn();

View File

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

View File

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

View File

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