perf(接口测试): 优化接口测试首页统计,部分涉及到计算的数据单开接口处理
--bug=1028467 --user=宋天阳 【接口测试】github#26028,api-test模块,接口数量很多,8k+,页面接口查询响应时间很慢,页面需要十几秒才会加载出来 https://www.tapd.cn/55049933/s/1410126
This commit is contained in:
parent
8fc7fb5261
commit
98b52d0c32
|
@ -22,7 +22,7 @@ public interface ExtApiDefinitionMapper {
|
||||||
|
|
||||||
List<ApiComputeResult> selectByIds(@Param("ids") List<String> ids, @Param("projectId") String projectId);
|
List<ApiComputeResult> selectByIds(@Param("ids") List<String> ids, @Param("projectId") String projectId);
|
||||||
|
|
||||||
List<ApiComputeResult> selectByIdsAndStatusIsNotTrash(@Param("ids") List<String> ids, @Param("projectId") String projectId);
|
List<ApiComputeResult> countByApiIdAndStatusIsNotTrash(@Param("ids") List<String> ids, @Param("projectId") String projectId);
|
||||||
|
|
||||||
int removeToGcByExample(ApiDefinitionExampleWithOperation example);
|
int removeToGcByExample(ApiDefinitionExampleWithOperation example);
|
||||||
|
|
||||||
|
|
|
@ -117,15 +117,10 @@
|
||||||
</foreach>
|
</foreach>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectByIdsAndStatusIsNotTrash" resultType="io.metersphere.api.dto.definition.ApiComputeResult">
|
<select id="countByApiIdAndStatusIsNotTrash" resultType="io.metersphere.api.dto.definition.ApiComputeResult">
|
||||||
SELECT t1.api_definition_id apiDefinitionId,count(t1.id) caseTotal,
|
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 in
|
|
||||||
('ERROR','FAKE_ERROR') then 1 else 0
|
|
||||||
end) as ERROR,
|
|
||||||
CONCAT(FORMAT(SUM(IF (t2.`status`='SUCCESS',1,0))/COUNT(t1.id)*100,2),'%') passRate
|
|
||||||
FROM api_test_case t1
|
FROM api_test_case t1
|
||||||
LEFT JOIN api_definition_exec_result t2 ON t1.last_result_id=t2.id
|
WHERE (t1.status is null or t1.status != 'Trash')
|
||||||
WHERE t1.project_id = #{projectId} and (t1.status is null or t1.status != 'Trash')
|
|
||||||
group by t1.api_definition_id having t1.api_definition_id in
|
group by t1.api_definition_id having t1.api_definition_id in
|
||||||
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
<foreach collection="ids" item="v" separator="," open="(" close=")">
|
||||||
#{v}
|
#{v}
|
||||||
|
@ -368,13 +363,12 @@
|
||||||
api_definition.description,api_definition.environment_id,
|
api_definition.description,api_definition.environment_id,
|
||||||
api_definition.status, api_definition.user_id, api_definition.create_time, api_definition.update_time,
|
api_definition.status, api_definition.user_id, api_definition.create_time, api_definition.update_time,
|
||||||
project.name as
|
project.name as
|
||||||
project_name, user.name as user_name,deleteUser.name AS delete_user,api_definition.delete_time,
|
project_name, user.name as user_name,api_definition.delete_user_id AS delete_user,api_definition.delete_time,
|
||||||
api_definition.remark
|
api_definition.remark
|
||||||
from (select * from api_definition where update_time >= #{startTimestamp} order by update_time
|
from (select * from api_definition where update_time >= #{startTimestamp} order by update_time
|
||||||
desc)api_definition
|
desc)api_definition
|
||||||
left join project on api_definition.project_id = project.id
|
INNER join project on api_definition.project_id = project.id
|
||||||
left join user on api_definition.user_id = user.id
|
INNER join user on api_definition.user_id = user.id
|
||||||
left join user deleteUser on api_definition.delete_user_id = deleteUser.id
|
|
||||||
<include refid="queryWhereConditionWidthProject"/>
|
<include refid="queryWhereConditionWidthProject"/>
|
||||||
<if test="request.orders != null and request.orders.size() > 0">
|
<if test="request.orders != null and request.orders.size() > 0">
|
||||||
order by
|
order by
|
||||||
|
@ -1134,7 +1128,7 @@
|
||||||
<select id="scenarioList" resultType="io.metersphere.base.domain.ApiScenario">
|
<select id="scenarioList" resultType="io.metersphere.base.domain.ApiScenario">
|
||||||
SELECT DISTINCT t1.id
|
SELECT DISTINCT t1.id
|
||||||
FROM api_scenario t1
|
FROM api_scenario t1
|
||||||
JOIN api_scenario_reference_id t2 ON t1.id = t2.api_scenario_id AND t1.`status` != 'Trash'
|
INNER JOIN api_scenario_reference_id t2 ON t1.id = t2.api_scenario_id AND t1.`status` != 'Trash'
|
||||||
WHERE t2.reference_id = #{apiDefinitionId}
|
WHERE t2.reference_id = #{apiDefinitionId}
|
||||||
</select>
|
</select>
|
||||||
<select id="countByIds" resultType="java.lang.Integer">
|
<select id="countByIds" resultType="java.lang.Integer">
|
||||||
|
|
|
@ -1053,6 +1053,7 @@
|
||||||
WHERE id IN (
|
WHERE id IN (
|
||||||
SELECT last_result_id FROM api_test_case testCase
|
SELECT last_result_id FROM api_test_case testCase
|
||||||
WHERE ( testCase.`status` IS NULL OR testCase.`status` != 'Trash')
|
WHERE ( testCase.`status` IS NULL OR testCase.`status` != 'Trash')
|
||||||
|
AND last_result_id IS NOT NULL
|
||||||
AND testCase.api_definition_id IN (
|
AND testCase.api_definition_id IN (
|
||||||
SELECT id FROM api_definition WHERE project_id = #{projectId}
|
SELECT id FROM api_definition WHERE project_id = #{projectId}
|
||||||
<if test="versionId != null">
|
<if test="versionId != null">
|
||||||
|
|
|
@ -35,6 +35,7 @@ import java.text.DecimalFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(value = "/home")
|
@RequestMapping(value = "/home")
|
||||||
|
@ -79,27 +80,6 @@ public class ApiHomeController {
|
||||||
//没有任何接口数据
|
//没有任何接口数据
|
||||||
apiCountResult.setCoveredCount(0);
|
apiCountResult.setCoveredCount(0);
|
||||||
apiCountResult.setNotCoveredCount(0);
|
apiCountResult.setNotCoveredCount(0);
|
||||||
} else {
|
|
||||||
|
|
||||||
//统计覆盖率. 覆盖:接口下挂有用例/接口路径被场景引用
|
|
||||||
//带有用例的接口
|
|
||||||
List<ApiDefinition> apiDefinitionHasCase = apiDefinitionService.selectBaseInfoByProjectIdAndHasCase(projectId, versionId);
|
|
||||||
//没有case的接口
|
|
||||||
List<ApiDefinition> apiNoCaseList = apiDefinitionService.getAPiNotInCollection(protocolAllDefinitionMap, apiDefinitionHasCase);
|
|
||||||
Map<String, Map<String, String>> scenarioUrlList = apiAutomationService.selectScenarioUseUrlByProjectId(projectId, null);
|
|
||||||
List<String> apiIdInScenario = apiAutomationService.getApiIdInScenario(projectId, scenarioUrlList, apiNoCaseList);
|
|
||||||
|
|
||||||
Map<String, List<ApiDefinition>> unCoverageApiMap = apiDefinitionService.getUnCoverageApiMap(apiNoCaseList, apiIdInScenario);
|
|
||||||
Map<String, List<ApiDefinition>> coverageApiMap = apiDefinitionService.filterMap(protocolAllDefinitionMap, unCoverageApiMap);
|
|
||||||
apiCountResult.countCovered(coverageApiMap, false);
|
|
||||||
apiCountResult.countCovered(unCoverageApiMap, true);
|
|
||||||
try {
|
|
||||||
float coveredRateNumber = (float) apiCountResult.getCoveredCount() * 100 / apiCountResult.getTotal();
|
|
||||||
DecimalFormat df = new DecimalFormat("0.0");
|
|
||||||
apiCountResult.setApiCoveredRate(df.format(coveredRateNumber) + "%");
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogUtil.error("转化通过率失败:[" + apiCountResult.getCoveredCount() + "," + apiCountResult.getTotal() + "]", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return apiCountResult;
|
return apiCountResult;
|
||||||
}
|
}
|
||||||
|
@ -108,7 +88,6 @@ public class ApiHomeController {
|
||||||
public ApiDataCountDTO apiCaseCount(@PathVariable String projectId, @PathVariable String versionId) {
|
public ApiDataCountDTO apiCaseCount(@PathVariable String projectId, @PathVariable String versionId) {
|
||||||
versionId = this.initializationVersionId(versionId);
|
versionId = this.initializationVersionId(versionId);
|
||||||
ApiDataCountDTO apiCountResult = new ApiDataCountDTO();
|
ApiDataCountDTO apiCountResult = new ApiDataCountDTO();
|
||||||
//todo 性能优化
|
|
||||||
List<ApiDataCountResult> countResultList = apiTestCaseService.countProtocolByProjectID(projectId, versionId);
|
List<ApiDataCountResult> countResultList = apiTestCaseService.countProtocolByProjectID(projectId, versionId);
|
||||||
apiCountResult.countProtocol(countResultList);
|
apiCountResult.countProtocol(countResultList);
|
||||||
//本周创建、本周执行、总执行
|
//本周创建、本周执行、总执行
|
||||||
|
@ -118,31 +97,6 @@ public class ApiHomeController {
|
||||||
apiCountResult.setExecutedTimesInWeek(executedInThisWeekCountNumber);
|
apiCountResult.setExecutedTimesInWeek(executedInThisWeekCountNumber);
|
||||||
long executedCount = apiTestCaseService.countExecutedTimesByProjectId(projectId, ExecutionExecuteTypeEnum.BASIC.name(), versionId);
|
long executedCount = apiTestCaseService.countExecutedTimesByProjectId(projectId, ExecutionExecuteTypeEnum.BASIC.name(), versionId);
|
||||||
apiCountResult.setExecutedTimes(executedCount);
|
apiCountResult.setExecutedTimes(executedCount);
|
||||||
//未覆盖 已覆盖: 统计当前接口下是否含有案例
|
|
||||||
List<ApiDataCountResult> countResultByApiCoverageList = apiDefinitionService.countApiCoverageByProjectID(projectId, versionId);
|
|
||||||
apiCountResult.countApiCoverage(countResultByApiCoverageList);
|
|
||||||
long allCount = apiCountResult.getCoveredCount() + apiCountResult.getNotCoveredCount();
|
|
||||||
if (allCount != 0) {
|
|
||||||
float coveredRateNumber = (float) apiCountResult.getCoveredCount() * 100 / allCount;
|
|
||||||
DecimalFormat df = new DecimalFormat("0.0");
|
|
||||||
apiCountResult.setApiCoveredRate(df.format(coveredRateNumber) + "%");
|
|
||||||
}
|
|
||||||
//计算用例的通过率和执行率
|
|
||||||
List<ExecuteResultCountDTO> apiCaseExecResultList = apiTestCaseService.selectExecuteResultByProjectId(apiCountResult.getTotal(), projectId, versionId);
|
|
||||||
apiCountResult.countApiCaseRunResult(apiCaseExecResultList);
|
|
||||||
if (apiCountResult.getExecutedCount() > 0) {
|
|
||||||
//通过率
|
|
||||||
float coveredRateNumber = (float) apiCountResult.getPassCount() * 100 / apiCountResult.getTotal();
|
|
||||||
DecimalFormat coveredRateFormat = new DecimalFormat("0.0");
|
|
||||||
apiCountResult.setPassRate(coveredRateFormat.format(coveredRateNumber) + "%");
|
|
||||||
|
|
||||||
float executedRateNumber = (float) apiCountResult.getExecutedData() * 100 / apiCountResult.getTotal();
|
|
||||||
DecimalFormat executedRateFormat = new DecimalFormat("0.0");
|
|
||||||
apiCountResult.setExecutedRate(executedRateFormat.format(executedRateNumber) + "%");
|
|
||||||
} else {
|
|
||||||
apiCountResult.setPassRate("0%");
|
|
||||||
apiCountResult.setExecutedRate("0%");
|
|
||||||
}
|
|
||||||
return apiCountResult;
|
return apiCountResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +127,90 @@ public class ApiHomeController {
|
||||||
apiCountResult.setExecutedRate(df.format(executedRateNumber) + "%");
|
apiCountResult.setExecutedRate(df.format(executedRateNumber) + "%");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return apiCountResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/api/covered/{projectId}/{versionId}")
|
||||||
|
public ApiDataCountDTO apiCovered(@PathVariable String projectId, @PathVariable String versionId) {
|
||||||
|
versionId = this.initializationVersionId(versionId);
|
||||||
|
ApiDataCountDTO apiCountResult = new ApiDataCountDTO();
|
||||||
|
Map<String, List<ApiDefinition>> protocolAllDefinitionMap = apiDefinitionService.countEffectiveByProjectId(projectId, versionId);
|
||||||
|
//统计覆盖率. 覆盖:接口下挂有用例/接口路径被场景引用
|
||||||
|
//带有用例的接口
|
||||||
|
List<ApiDefinition> apiDefinitionHasCase = apiDefinitionService.selectBaseInfoByProjectIdAndHasCase(projectId, versionId);
|
||||||
|
//没有case的接口
|
||||||
|
List<ApiDefinition> apiNoCaseList = apiDefinitionService.getAPiNotInCollection(protocolAllDefinitionMap, apiDefinitionHasCase);
|
||||||
|
Map<String, Map<String, String>> scenarioUrlList = apiAutomationService.selectScenarioUseUrlByProjectId(projectId, null);
|
||||||
|
List<String> apiIdInScenario = apiAutomationService.getApiIdInScenario(projectId, scenarioUrlList, apiNoCaseList);
|
||||||
|
|
||||||
|
Map<String, List<ApiDefinition>> unCoverageApiMap = apiDefinitionService.getUnCoverageApiMap(apiNoCaseList, apiIdInScenario);
|
||||||
|
Map<String, List<ApiDefinition>> coverageApiMap = apiDefinitionService.filterMap(protocolAllDefinitionMap, unCoverageApiMap);
|
||||||
|
apiCountResult.countCovered(coverageApiMap, false);
|
||||||
|
apiCountResult.countCovered(unCoverageApiMap, true);
|
||||||
|
|
||||||
|
long total = apiCountResult.getCoveredCount() + apiCountResult.getNotCoveredCount();
|
||||||
|
if (total > 0) {
|
||||||
|
try {
|
||||||
|
float coveredRateNumber = (float) apiCountResult.getCoveredCount() * 100 / total;
|
||||||
|
DecimalFormat df = new DecimalFormat("0.0");
|
||||||
|
apiCountResult.setApiCoveredRate(df.format(coveredRateNumber) + "%");
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error("转化通过率失败:[" + apiCountResult.getCoveredCount() + "," + apiCountResult.getTotal() + "]", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiCountResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/api/case/covered/{projectId}/{versionId}")
|
||||||
|
public ApiDataCountDTO caseCovered(@PathVariable String projectId, @PathVariable String versionId) throws Exception {
|
||||||
|
versionId = this.initializationVersionId(versionId);
|
||||||
|
ApiDataCountDTO apiCountResult = new ApiDataCountDTO();
|
||||||
|
//两个大数据量下耗时比较长的查询同时进行
|
||||||
|
CountDownLatch countDownLatch = new CountDownLatch(2);
|
||||||
|
try {
|
||||||
|
//未覆盖 已覆盖: 统计当前接口下是否含有案例
|
||||||
|
List<ApiDataCountResult> countResultByApiCoverageList = apiDefinitionService.countApiCoverageByProjectID(projectId, versionId);
|
||||||
|
apiCountResult.countApiCoverage(countResultByApiCoverageList);
|
||||||
|
long allCount = apiCountResult.getCoveredCount() + apiCountResult.getNotCoveredCount();
|
||||||
|
if (allCount != 0) {
|
||||||
|
float coveredRateNumber = (float) apiCountResult.getCoveredCount() * 100 / allCount;
|
||||||
|
DecimalFormat df = new DecimalFormat("0.0");
|
||||||
|
apiCountResult.setApiCoveredRate(df.format(coveredRateNumber) + "%");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
countDownLatch.countDown();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
//计算用例的通过率和执行率
|
||||||
|
List<ExecuteResultCountDTO> apiCaseExecResultList = apiTestCaseService.selectExecuteResultByProjectId(apiCountResult.getTotal(), projectId, versionId);
|
||||||
|
apiCountResult.countApiCaseRunResult(apiCaseExecResultList);
|
||||||
|
long allCount = apiCountResult.getExecutedCount() + apiCountResult.getNotExecutedCount();
|
||||||
|
if (apiCountResult.getExecutedCount() > 0) {
|
||||||
|
//通过率
|
||||||
|
float coveredRateNumber = (float) apiCountResult.getPassCount() * 100 / allCount;
|
||||||
|
DecimalFormat coveredRateFormat = new DecimalFormat("0.0");
|
||||||
|
apiCountResult.setPassRate(coveredRateFormat.format(coveredRateNumber) + "%");
|
||||||
|
|
||||||
|
float executedRateNumber = (float) apiCountResult.getExecutedData() * 100 / allCount;
|
||||||
|
DecimalFormat executedRateFormat = new DecimalFormat("0.0");
|
||||||
|
apiCountResult.setExecutedRate(executedRateFormat.format(executedRateNumber) + "%");
|
||||||
|
} else {
|
||||||
|
apiCountResult.setPassRate("0%");
|
||||||
|
apiCountResult.setExecutedRate("0%");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
countDownLatch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
countDownLatch.await();
|
||||||
|
return apiCountResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/scenario/covered/{projectId}/{versionId}")
|
||||||
|
public ApiDataCountDTO scenarioCovered(@PathVariable String projectId, @PathVariable String versionId) {
|
||||||
|
versionId = this.initializationVersionId(versionId);
|
||||||
|
ApiDataCountDTO apiCountResult = new ApiDataCountDTO();
|
||||||
//统计覆盖率
|
//统计覆盖率
|
||||||
CoveredDTO coveredDTO = new CoveredDTO();
|
CoveredDTO coveredDTO = new CoveredDTO();
|
||||||
Map<String, Map<String, String>> scenarioUrlList = apiAutomationService.selectScenarioUseUrlByProjectId(projectId, versionId);
|
Map<String, Map<String, String>> scenarioUrlList = apiAutomationService.selectScenarioUseUrlByProjectId(projectId, versionId);
|
||||||
|
|
|
@ -1287,9 +1287,7 @@ public class ApiDefinitionService {
|
||||||
List<ApiDataCountResult> apiDataCountResultList = extApiDefinitionMapper.countApiHasNotCaseByProjectID(projectId, versionId);
|
List<ApiDataCountResult> apiDataCountResultList = extApiDefinitionMapper.countApiHasNotCaseByProjectID(projectId, versionId);
|
||||||
|
|
||||||
AtomicLong unCoveredAtomicLong = new AtomicLong();
|
AtomicLong unCoveredAtomicLong = new AtomicLong();
|
||||||
apiDataCountResultList.forEach(item -> {
|
apiDataCountResultList.forEach(item -> unCoveredAtomicLong.addAndGet(item.getCountNumber()));
|
||||||
unCoveredAtomicLong.addAndGet(item.getCountNumber());
|
|
||||||
});
|
|
||||||
long coveredLong = apiCount - unCoveredAtomicLong.get();
|
long coveredLong = apiCount - unCoveredAtomicLong.get();
|
||||||
ApiDataCountResult coveredResult = new ApiDataCountResult();
|
ApiDataCountResult coveredResult = new ApiDataCountResult();
|
||||||
coveredResult.setGroupField("covered");
|
coveredResult.setGroupField("covered");
|
||||||
|
@ -1382,27 +1380,16 @@ public class ApiDefinitionService {
|
||||||
public void calculateResult(List<ApiDefinitionResult> resList, String projectId) {
|
public void calculateResult(List<ApiDefinitionResult> resList, String projectId) {
|
||||||
if (!resList.isEmpty()) {
|
if (!resList.isEmpty()) {
|
||||||
List<String> ids = resList.stream().map(ApiDefinitionResult::getId).collect(Collectors.toList());
|
List<String> ids = resList.stream().map(ApiDefinitionResult::getId).collect(Collectors.toList());
|
||||||
List<ApiComputeResult> results = extApiDefinitionMapper.selectByIdsAndStatusIsNotTrash(ids, projectId);
|
List<ApiComputeResult> results = extApiDefinitionMapper.countByApiIdAndStatusIsNotTrash(ids, projectId);
|
||||||
Map<String, ApiComputeResult> resultMap = results.stream().collect(Collectors.toMap(ApiComputeResult::getApiDefinitionId, Function.identity()));
|
Map<String, ApiComputeResult> resultMap = results.stream().collect(Collectors.toMap(ApiComputeResult::getApiDefinitionId, Function.identity()));
|
||||||
for (ApiDefinitionResult res : resList) {
|
for (ApiDefinitionResult res : resList) {
|
||||||
ApiComputeResult compRes = resultMap.get(res.getId());
|
ApiComputeResult compRes = resultMap.get(res.getId());
|
||||||
if (compRes != null) {
|
if (compRes != null) {
|
||||||
res.setCaseType("apiCase");
|
res.setCaseType("apiCase");
|
||||||
res.setCaseTotal(String.valueOf(compRes.getCaseTotal()));
|
res.setCaseTotal(String.valueOf(compRes.getCaseTotal()));
|
||||||
res.setCasePassingRate(compRes.getPassRate());
|
|
||||||
// 状态优先级 未执行,未通过,通过
|
|
||||||
if ((compRes.getError() + compRes.getSuccess()) < compRes.getCaseTotal()) {
|
|
||||||
res.setCaseStatus(ApiReportStatus.PENDING.name());
|
|
||||||
} else if (compRes.getError() > 0) {
|
|
||||||
res.setCaseStatus(ApiReportStatus.ERROR.name());
|
|
||||||
} else {
|
|
||||||
res.setCaseStatus(ApiReportStatus.SUCCESS.name());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
res.setCaseType("apiCase");
|
res.setCaseType("apiCase");
|
||||||
res.setCaseTotal("0");
|
res.setCaseTotal("0");
|
||||||
res.setCasePassingRate("-");
|
|
||||||
res.setCaseStatus("-");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,26 @@ export function apiCountByProjectId(projectId, versionId) {
|
||||||
return get('/home/api/count/' + projectId + '/' + versionId);
|
return get('/home/api/count/' + projectId + '/' + versionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function apiCoveredByProjectId(projectId, versionId) {
|
||||||
|
return get('/home/api/covered/' + projectId + '/' + versionId);
|
||||||
|
}
|
||||||
|
|
||||||
export function scenarioCountByProjectId(projectId, versionId) {
|
export function scenarioCountByProjectId(projectId, versionId) {
|
||||||
return get('/home/scenario/count/' + projectId + '/' + versionId);
|
return get('/home/scenario/count/' + projectId + '/' + versionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function scenarioCoveredByProjectId(projectId, versionId) {
|
||||||
|
return get('/home/scenario/covered/' + projectId + '/' + versionId);
|
||||||
|
}
|
||||||
|
|
||||||
export function apiCaseCountByProjectId(projectId, versionId) {
|
export function apiCaseCountByProjectId(projectId, versionId) {
|
||||||
return get('/home/api/case/count/' + projectId + '/' + versionId);
|
return get('/home/api/case/count/' + projectId + '/' + versionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function apiCaseCoveredByProjectId(projectId, versionId) {
|
||||||
|
return get('/home/api/case/covered/' + projectId + '/' + versionId);
|
||||||
|
}
|
||||||
|
|
||||||
export function scheduleTaskCountByProjectId(projectId, versionId) {
|
export function scheduleTaskCountByProjectId(projectId, versionId) {
|
||||||
return get('/home/schedule/task/count/' + projectId + '/' + versionId);
|
return get('/home/schedule/task/count/' + projectId + '/' + versionId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
:link-permission="['PROJECT_API_DEFINITION:READ']"
|
:link-permission="['PROJECT_API_DEFINITION:READ']"
|
||||||
@redirectPage="redirectPage" />
|
@redirectPage="redirectPage" />
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12" v-loading="coveredLoading">
|
||||||
<main-info-card
|
<main-info-card
|
||||||
:title="$t('home.dashboard.public.executed_times_in_week')"
|
:title="$t('home.dashboard.public.executed_times_in_week')"
|
||||||
:count-data="apiCaseData"
|
:count-data="apiCaseData"
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
<div class="addition-info">
|
<div class="addition-info">
|
||||||
<el-row :gutter="16" style="margin: 0">
|
<el-row :gutter="16" style="margin: 0" v-loading="coveredLoading">
|
||||||
<!--接口覆盖率-->
|
<!--接口覆盖率-->
|
||||||
<el-col :span="8" style="padding-left: 0">
|
<el-col :span="8" style="padding-left: 0">
|
||||||
<hover-card
|
<hover-card
|
||||||
|
@ -175,7 +175,7 @@
|
||||||
<script>
|
<script>
|
||||||
import hoverCard from '@/business/home/components/card/HoverCard';
|
import hoverCard from '@/business/home/components/card/HoverCard';
|
||||||
import mainInfoCard from '@/business/home/components/card/MainInfoCard';
|
import mainInfoCard from '@/business/home/components/card/MainInfoCard';
|
||||||
import { apiCaseCountByProjectId, formatNumber } from '@/api/home';
|
import {apiCaseCountByProjectId, apiCaseCoveredByProjectId, formatNumber} from '@/api/home';
|
||||||
import {getCurrentProjectID} from 'metersphere-frontend/src/utils/token';
|
import {getCurrentProjectID} from 'metersphere-frontend/src/utils/token';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -184,6 +184,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
|
coveredLoading: false,
|
||||||
loadError: false,
|
loadError: false,
|
||||||
apiCoveredRateToolTip: this.$t('api_test.home_page.formula.coverage'),
|
apiCoveredRateToolTip: this.$t('api_test.home_page.formula.coverage'),
|
||||||
executeRateToolTip: this.$t('api_test.home_page.formula.case_execute'),
|
executeRateToolTip: this.$t('api_test.home_page.formula.case_execute'),
|
||||||
|
@ -209,18 +210,47 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
search(versionId) {
|
search(versionId) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
this.coveredLoading = false;
|
||||||
this.loadError = false;
|
this.loadError = false;
|
||||||
let selectProjectId = getCurrentProjectID();
|
let selectProjectId = getCurrentProjectID();
|
||||||
apiCaseCountByProjectId(selectProjectId, versionId)
|
apiCaseCountByProjectId(selectProjectId, versionId)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.loadError = false;
|
this.loadError = false;
|
||||||
this.apiCaseData = response.data;
|
this.formatApiCaseData(response.data, false);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.loadError = true;
|
this.loadError = true;
|
||||||
});
|
});
|
||||||
|
apiCaseCoveredByProjectId(selectProjectId, versionId)
|
||||||
|
.then((response) => {
|
||||||
|
this.coveredLoading = false;
|
||||||
|
this.formatApiCaseData(response.data, true);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.coveredLoading = false;
|
||||||
|
this.loadError = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
formatApiCaseData(apiCaseResponse, isCovered) {
|
||||||
|
if (isCovered) {
|
||||||
|
this.apiCaseData.coveredCount = apiCaseResponse.coveredCount;
|
||||||
|
this.apiCaseData.notCoveredCount = apiCaseResponse.notCoveredCount;
|
||||||
|
this.apiCaseData.executedCount = apiCaseResponse.executedCount;
|
||||||
|
this.apiCaseData.notExecutedCount = apiCaseResponse.notExecutedCount;
|
||||||
|
this.apiCaseData.passCount = apiCaseResponse.passCount;
|
||||||
|
this.apiCaseData.unPassCount = apiCaseResponse.unPassCount;
|
||||||
|
this.apiCaseData.fakeErrorCount = apiCaseResponse.fakeErrorCount;
|
||||||
|
this.apiCaseData.executedRate = apiCaseResponse.executedRate;
|
||||||
|
this.apiCaseData.passRate = apiCaseResponse.passRate;
|
||||||
|
this.apiCaseData.apiCoveredRate = apiCaseResponse.apiCoveredRate;
|
||||||
|
} else {
|
||||||
|
this.apiCaseData.total = apiCaseResponse.total;
|
||||||
|
this.apiCaseData.createdInWeek = apiCaseResponse.createdInWeek;
|
||||||
|
this.apiCaseData.executedTimesInWeek = apiCaseResponse.executedTimesInWeek;
|
||||||
|
this.apiCaseData.executedTimes = apiCaseResponse.executedTimes;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
formatAmount(number) {
|
formatAmount(number) {
|
||||||
return formatNumber(number);
|
return formatNumber(number);
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="addition-info">
|
<div class="addition-info">
|
||||||
<el-row :gutter="16" style="margin: 0">
|
<el-row :gutter="16" style="margin: 0">
|
||||||
<el-col :span="12" style="padding-left: 0">
|
<el-col :span="12" style="padding-left: 0" v-loading="coveredLoading">
|
||||||
<hover-card
|
<hover-card
|
||||||
:title="$t('home.dashboard.api.covered_rate')"
|
:title="$t('home.dashboard.api.covered_rate')"
|
||||||
:main-info="apiData.apiCoveredRate"
|
:main-info="apiData.apiCoveredRate"
|
||||||
|
@ -278,7 +278,7 @@
|
||||||
import countChart from '@/business/home/components/chart/CountChart';
|
import countChart from '@/business/home/components/chart/CountChart';
|
||||||
import hoverCard from '@/business/home/components/card/HoverCard';
|
import hoverCard from '@/business/home/components/card/HoverCard';
|
||||||
import {getCurrentProjectID} from 'metersphere-frontend/src/utils/token';
|
import {getCurrentProjectID} from 'metersphere-frontend/src/utils/token';
|
||||||
import { apiCountByProjectId, formatNumber } from '@/api/home';
|
import {apiCountByProjectId, apiCoveredByProjectId, formatNumber} from '@/api/home';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ApiDashboard',
|
name: 'ApiDashboard',
|
||||||
|
@ -286,6 +286,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
|
coveredLoading: false,
|
||||||
loadError: false,
|
loadError: false,
|
||||||
apiCoveredRageToolTip: this.$t('api_test.home_page.formula.api_coverage'),
|
apiCoveredRageToolTip: this.$t('api_test.home_page.formula.api_coverage'),
|
||||||
completedRageToolTip: this.$t('api_test.home_page.formula.completion'),
|
completedRageToolTip: this.$t('api_test.home_page.formula.completion'),
|
||||||
|
@ -317,14 +318,17 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
search(versionId) {
|
search(versionId) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
this.coveredLoading = true;
|
||||||
this.loadError = false;
|
this.loadError = false;
|
||||||
this.versionId = versionId;
|
this.versionId = versionId;
|
||||||
let selectProjectId = getCurrentProjectID();
|
let selectProjectId = getCurrentProjectID();
|
||||||
|
|
||||||
apiCountByProjectId(selectProjectId, versionId)
|
apiCountByProjectId(selectProjectId, versionId)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.loadError = false;
|
this.loadError = false;
|
||||||
this.apiData = response.data;
|
this.parseApiData(response.data, false);
|
||||||
|
// this.apiData = response.data;
|
||||||
this.$refs.countChart.reload();
|
this.$refs.countChart.reload();
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
@ -332,7 +336,47 @@ export default {
|
||||||
this.loadError = true;
|
this.loadError = true;
|
||||||
this.$refs.countChart.reload();
|
this.$refs.countChart.reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
apiCoveredByProjectId(selectProjectId, versionId)
|
||||||
|
.then((response) => {
|
||||||
|
this.coveredLoading = false;
|
||||||
|
this.loadError = false;
|
||||||
|
this.parseApiData(response.data, true);
|
||||||
|
// this.apiData = response.data;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.coveredLoading = false;
|
||||||
|
this.loadError = true;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
parseApiData(apiResponse, isCovered) {
|
||||||
|
if (isCovered) {
|
||||||
|
this.apiData.apiCoveredRate = apiResponse.apiCoveredRate;
|
||||||
|
this.apiData.httpCovered = apiResponse.httpCovered;
|
||||||
|
this.apiData.rpcCovered = apiResponse.rpcCovered;
|
||||||
|
this.apiData.tcpCovered = apiResponse.tcpCovered;
|
||||||
|
this.apiData.sqlCovered = apiResponse.sqlCovered;
|
||||||
|
this.apiData.httpNotCovered = apiResponse.httpNotCovered;
|
||||||
|
this.apiData.rpcNotCovered = apiResponse.rpcNotCovered;
|
||||||
|
this.apiData.tcpNotCovered = apiResponse.tcpNotCovered;
|
||||||
|
this.apiData.sqlNotCovered = apiResponse.sqlNotCovered;
|
||||||
|
this.apiData.coveredCount = apiResponse.coveredCount;
|
||||||
|
this.apiData.notCoveredCount = apiResponse.notCoveredCount;
|
||||||
|
} else {
|
||||||
|
this.apiData.httpCount = apiResponse.httpCount;
|
||||||
|
this.apiData.tcpCount = apiResponse.tcpCount;
|
||||||
|
this.apiData.rpcCount = apiResponse.rpcCount;
|
||||||
|
this.apiData.sqlCount = apiResponse.sqlCount;
|
||||||
|
this.apiData.createdInWeek = apiResponse.createdInWeek;
|
||||||
|
this.apiData.apiCoveredRate = apiResponse.apiCoveredRate;
|
||||||
|
this.apiData.completedRate = apiResponse.completedRate;
|
||||||
|
this.apiData.runningCount = apiResponse.runningCount;
|
||||||
|
this.apiData.finishedCount = apiResponse.finishedCount;
|
||||||
|
this.apiData.notRunCount = apiResponse.notRunCount;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
formatAmount(number) {
|
formatAmount(number) {
|
||||||
return formatNumber(number);
|
return formatNumber(number);
|
||||||
},
|
},
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
<div class="addition-info">
|
<div class="addition-info">
|
||||||
<el-row :gutter="16" style="margin: 0">
|
<el-row :gutter="16" style="margin: 0">
|
||||||
<!--接口覆盖率-->
|
<!--接口覆盖率-->
|
||||||
<el-col :span="8" style="padding-left: 0">
|
<el-col :span="8" style="padding-left: 0" v-loading="coveredLoading">
|
||||||
<hover-card
|
<hover-card
|
||||||
:title="$t('home.dashboard.scenario.covered_rate')"
|
:title="$t('home.dashboard.scenario.covered_rate')"
|
||||||
:main-info="scenarioData.apiCoveredRate"
|
:main-info="scenarioData.apiCoveredRate"
|
||||||
|
@ -176,7 +176,7 @@
|
||||||
<script>
|
<script>
|
||||||
import hoverCard from '@/business/home/components/card/HoverCard';
|
import hoverCard from '@/business/home/components/card/HoverCard';
|
||||||
import mainInfoCard from '@/business/home/components/card/MainInfoCard';
|
import mainInfoCard from '@/business/home/components/card/MainInfoCard';
|
||||||
import { formatNumber, scenarioCountByProjectId } from '@/api/home';
|
import {formatNumber, scenarioCountByProjectId, scenarioCoveredByProjectId} from '@/api/home';
|
||||||
import {getCurrentProjectID} from 'metersphere-frontend/src/utils/token';
|
import {getCurrentProjectID} from 'metersphere-frontend/src/utils/token';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -185,6 +185,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
|
coveredLoading: false,
|
||||||
loadError: false,
|
loadError: false,
|
||||||
apiCoveredRateToolTip: this.$t('api_test.home_page.formula.interface_coverage'),
|
apiCoveredRateToolTip: this.$t('api_test.home_page.formula.interface_coverage'),
|
||||||
executeRateToolTip: this.$t('api_test.home_page.formula.scenario_execute'),
|
executeRateToolTip: this.$t('api_test.home_page.formula.scenario_execute'),
|
||||||
|
@ -210,18 +211,48 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
search(versionId) {
|
search(versionId) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
this.coveredLoading = true;
|
||||||
this.loadError = false;
|
this.loadError = false;
|
||||||
let selectProjectId = getCurrentProjectID();
|
let selectProjectId = getCurrentProjectID();
|
||||||
scenarioCountByProjectId(selectProjectId, versionId)
|
scenarioCountByProjectId(selectProjectId, versionId)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.loadError = false;
|
this.loadError = false;
|
||||||
this.scenarioData = response.data;
|
this.parserScenarioData(response.data, false);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.loadError = true;
|
this.loadError = true;
|
||||||
});
|
});
|
||||||
|
scenarioCoveredByProjectId(selectProjectId, versionId)
|
||||||
|
.then((response) => {
|
||||||
|
this.coveredLoading = false;
|
||||||
|
this.loadError = false;
|
||||||
|
this.parserScenarioData(response.data, true);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.coveredLoading = false;
|
||||||
|
this.loadError = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
parserScenarioData(scenarioResponse, isCovered) {
|
||||||
|
if (isCovered) {
|
||||||
|
this.scenarioData.apiCoveredRate = scenarioResponse.apiCoveredRate;
|
||||||
|
this.scenarioData.coveredCount = scenarioResponse.coveredCount;
|
||||||
|
this.scenarioData.notCoveredCount = scenarioResponse.notCoveredCount;
|
||||||
|
} else {
|
||||||
|
this.scenarioData.total = scenarioResponse.total;
|
||||||
|
this.scenarioData.createdInWeek = scenarioResponse.createdInWeek;
|
||||||
|
this.scenarioData.executedTimesInWeek = scenarioResponse.executedTimesInWeek;
|
||||||
|
this.scenarioData.executedTimes = scenarioResponse.executedTimes;
|
||||||
|
this.scenarioData.executedRate = scenarioResponse.executedRate;
|
||||||
|
this.scenarioData.passRate = scenarioResponse.passRate;
|
||||||
|
this.scenarioData.executedCount = scenarioResponse.executedCount;
|
||||||
|
this.scenarioData.notExecutedCount = scenarioResponse.notExecutedCount;
|
||||||
|
this.scenarioData.passCount = scenarioResponse.passCount;
|
||||||
|
this.scenarioData.unPassCount = scenarioResponse.unPassCount;
|
||||||
|
this.scenarioData.fakeErrorCount = scenarioResponse.fakeErrorCount;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
formatAmount(number) {
|
formatAmount(number) {
|
||||||
return formatNumber(number);
|
return formatNumber(number);
|
||||||
|
|
Loading…
Reference in New Issue