From d62391e6ca59bd55af60a7f508b0753a0c8e8686 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Wed, 31 Mar 2021 13:20:53 +0800 Subject: [PATCH 1/7] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E6=B3=A8=E9=87=8A=E5=85=A8=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business/components/api/automation/scenario/EnvSelect.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/business/components/api/automation/scenario/EnvSelect.vue b/frontend/src/business/components/api/automation/scenario/EnvSelect.vue index 5bdd88307f..27a4cb1918 100644 --- a/frontend/src/business/components/api/automation/scenario/EnvSelect.vue +++ b/frontend/src/business/components/api/automation/scenario/EnvSelect.vue @@ -246,8 +246,8 @@ sign = false; } // 校验是否全是全路径 - this.checkFullUrl(data); - sign = this.isFullUrl; + //this.checkFullUrl(data); + //sign = this.isFullUrl; } if (!sign) { From 0cb2188cd23c3283c24684b32b5f2a6a792a93d0 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Wed, 31 Mar 2021 13:24:50 +0800 Subject: [PATCH 2/7] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E6=81=A2=E5=A4=8Dxpack?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/business/components/xpack | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/business/components/xpack b/frontend/src/business/components/xpack index 07951ba17a..a37e6bb56f 160000 --- a/frontend/src/business/components/xpack +++ b/frontend/src/business/components/xpack @@ -1 +1 @@ -Subproject commit 07951ba17aef6f29e50cfd68e40de3266f9a60cd +Subproject commit a37e6bb56ffaa7ecc4ee128640e9415304ad41b6 From d55bbc6dd8fd24ee330ce39c2d127f23bf7b70fb Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Wed, 31 Mar 2021 13:43:43 +0800 Subject: [PATCH 3/7] =?UTF-8?q?fix:=20=E6=8E=A5=E5=8F=A3=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E6=B2=A1=E6=9C=89=E5=B8=A6=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/definition/components/module/ApiModule.vue | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/business/components/api/definition/components/module/ApiModule.vue b/frontend/src/business/components/api/definition/components/module/ApiModule.vue index 1d2e735ff6..22a88d9139 100644 --- a/frontend/src/business/components/api/definition/components/module/ApiModule.vue +++ b/frontend/src/business/components/api/definition/components/module/ApiModule.vue @@ -133,11 +133,16 @@ this.data.forEach(node => { buildTree(node, {path: ''}); }); - this.$emit('setModuleOptions', this.data); this.$emit('setNodeTree', this.data); if (this.$refs.nodeTree) { this.$refs.nodeTree.filter(this.condition.filterText); } + let moduleOptions = []; + this.data.forEach(node => { + buildNodePath(node, {path: ''}, moduleOptions); + }); + this.moduleOptions = moduleOptions; + this.$emit('setModuleOptions', moduleOptions); } }); }, From 57bddf4bd09ccf362d9351b0049086a94c870a11 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Wed, 31 Mar 2021 14:21:56 +0800 Subject: [PATCH 4/7] =?UTF-8?q?fix:=20=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/listener/TestCaseDataListener.java | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/io/metersphere/excel/listener/TestCaseDataListener.java b/backend/src/main/java/io/metersphere/excel/listener/TestCaseDataListener.java index ba941aad35..05615842c0 100644 --- a/backend/src/main/java/io/metersphere/excel/listener/TestCaseDataListener.java +++ b/backend/src/main/java/io/metersphere/excel/listener/TestCaseDataListener.java @@ -142,7 +142,7 @@ public class TestCaseDataListener extends EasyExcelListener { public void saveData() { //excel中用例都有错误时就返回,只要有用例可用于更新或者插入就不返回 - if (!errList.isEmpty() && list.size() == 0 && updateList.size() == 0) { + if (!errList.isEmpty()) { return; } @@ -231,15 +231,23 @@ public class TestCaseDataListener extends EasyExcelListener { */ public String modifyTagPattern(TestCaseExcelData data){ String tags = data.getTags(); - if (tags != null) { - Stream stringStream = Arrays.stream(tags.split("[,;,;]")); //当标签值以中英文的逗号和分号分隔时才能正确解析 - List tagList = stringStream.map(tag -> tag = "\"" + tag + "\"") - .collect(Collectors.toList()); - String modifiedTags = StringUtils.join(tagList, ","); - modifiedTags = "[" + modifiedTags + "]"; - return modifiedTags; - }else { - return null; + try { + if (StringUtils.isNotBlank(tags)) { + JSONArray.parse(tags); + return tags; + } + return "[]"; + } catch (Exception e) { + if (tags != null) { + Stream stringStream = Arrays.stream(tags.split("[,;,;]")); //当标签值以中英文的逗号和分号分隔时才能正确解析 + List tagList = stringStream.map(tag -> tag = "\"" + tag + "\"") + .collect(Collectors.toList()); + String modifiedTags = StringUtils.join(tagList, ","); + modifiedTags = "[" + modifiedTags + "]"; + return modifiedTags; + } else { + return "[]"; + } } } From 2279c17d73f50eaf18d82d23a308cfc4ec486b9f Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Wed, 31 Mar 2021 14:33:04 +0800 Subject: [PATCH 5/7] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E4=BF=AE=E6=94=B9=E8=BD=AC=E5=9C=BA=E6=99=AF?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/api/definition/components/case/ApiCaseList.vue | 1 + frontend/src/business/components/api/test/Upgrade.vue | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/business/components/api/definition/components/case/ApiCaseList.vue b/frontend/src/business/components/api/definition/components/case/ApiCaseList.vue index f63c1e8f92..d1e3834198 100644 --- a/frontend/src/business/components/api/definition/components/case/ApiCaseList.vue +++ b/frontend/src/business/components/api/definition/components/case/ApiCaseList.vue @@ -152,6 +152,7 @@ saveApiAndCase(api) { this.visible = true; this.api = api; + this.currentApi = api; this.addCase(); }, setEnvironment(environment) { diff --git a/frontend/src/business/components/api/test/Upgrade.vue b/frontend/src/business/components/api/test/Upgrade.vue index 0c3b568be8..40f70cbd05 100644 --- a/frontend/src/business/components/api/test/Upgrade.vue +++ b/frontend/src/business/components/api/test/Upgrade.vue @@ -11,7 +11,6 @@ Date: Wed, 31 Mar 2021 14:43:59 +0800 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E9=A6=96=E9=A1=B5=E5=A2=9E=E5=8A=A0"=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E8=A6=86=E7=9B=96=E7=8E=87=E7=BB=9F=E8=AE=A1"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 接口测试首页增加"接口覆盖率统计" --- .../api/controller/APITestController.java | 54 +++++-- .../datacount/response/ApiDataCountDTO.java | 5 + .../api/service/ApiAutomationService.java | 132 ++++++++++++++++++ .../api/service/ApiDefinitionService.java | 4 + .../api/service/ApiTestCaseService.java | 4 + .../mapper/ext/ExtApiDefinitionMapper.java | 2 + .../mapper/ext/ExtApiDefinitionMapper.xml | 5 + .../base/mapper/ext/ExtApiScenarioMapper.java | 3 +- .../base/mapper/ext/ExtApiScenarioMapper.xml | 3 + .../base/mapper/ext/ExtApiTestCaseMapper.java | 2 + .../base/mapper/ext/ExtApiTestCaseMapper.xml | 3 + .../api/homepage/ApiTestHomePage.vue | 7 +- .../api/homepage/components/SceneInfoCard.vue | 29 +++- frontend/src/i18n/en-US.js | 1 + frontend/src/i18n/zh-CN.js | 1 + frontend/src/i18n/zh-TW.js | 1 + 16 files changed, 237 insertions(+), 19 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/controller/APITestController.java b/backend/src/main/java/io/metersphere/api/controller/APITestController.java index d43ea2acb9..185abbd176 100644 --- a/backend/src/main/java/io/metersphere/api/controller/APITestController.java +++ b/backend/src/main/java/io/metersphere/api/controller/APITestController.java @@ -12,8 +12,7 @@ import io.metersphere.api.dto.datacount.response.TaskInfoResult; import io.metersphere.api.dto.definition.RunDefinitionRequest; import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter; import io.metersphere.api.service.*; -import io.metersphere.base.domain.ApiTest; -import io.metersphere.base.domain.Schedule; +import io.metersphere.base.domain.*; import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.constants.ScheduleGroup; import io.metersphere.commons.utils.CronUtils; @@ -30,13 +29,15 @@ import org.apache.commons.lang3.StringUtils; import org.apache.jorphan.collections.HashTree; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; -import org.python.core.AstList; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.text.DecimalFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; import static io.metersphere.commons.utils.JsonPathUtils.getListJson; @@ -251,9 +252,7 @@ public class APITestController { @GetMapping("/testSceneInfoCount/{projectId}") public ApiDataCountDTO testSceneInfoCount(@PathVariable String projectId) { - ApiDataCountDTO apiCountResult = new ApiDataCountDTO(); - long scenarioCountNumber = apiAutomationService.countScenarioByProjectID(projectId); apiCountResult.setAllApiDataCountNumber(scenarioCountNumber); @@ -272,17 +271,46 @@ public class APITestController { //未执行、未通过、已通过 List countResultByRunResult = apiAutomationService.countRunResultByProjectID(projectId); apiCountResult.countRunResult(countResultByRunResult); - long allCount = apiCountResult.getUnexecuteCount() + apiCountResult.getExecutionPassCount() + apiCountResult.getExecutionFailedCount(); - + DecimalFormat df = new DecimalFormat("0.0"); if (allCount != 0) { + //通过率 float coverageRageNumber = (float) apiCountResult.getExecutionPassCount() * 100 / allCount; - DecimalFormat df = new DecimalFormat("0.0"); apiCountResult.setPassRage(df.format(coverageRageNumber) + "%"); } - return apiCountResult; + } + @GetMapping("/countInterfaceCoverage/{projectId}") + public String countInterfaceCoverage(@PathVariable String projectId) { + String returnStr = "100%"; + /** + * 接口覆盖率 + * 复制的接口定义/复制或引用的单接口用例/ 添加的自定义请求 url 路径与现有的接口定义一致的请求 + */ + long startTime1 = System.currentTimeMillis(); + List allScenarioInfoList = apiAutomationService.selectIdAndScenarioByProjectId(projectId); + long startTime2 = System.currentTimeMillis(); + System.out.println("Search data time : " + (startTime2 - startTime1)); + startTime1 = System.currentTimeMillis(); + List allEffectiveApiIdList = apiDefinitionService.selectEffectiveIdByProjectId(projectId); + startTime2 = System.currentTimeMillis(); + System.out.println("Search data time (api info) : " + (startTime2 - startTime1)); + List allEffectiveApiCaseList = apiTestCaseService.selectEffectiveTestCaseByProjectId(projectId); + long startTime3 = System.currentTimeMillis(); + System.out.println("Search data time (case info): " + (startTime3 - startTime2)); + + try { + startTime1 = System.currentTimeMillis(); + float intetfaceCoverageRageNumber = apiAutomationService.countInterfaceCoverage(allScenarioInfoList, allEffectiveApiIdList, allEffectiveApiCaseList); + startTime2 = System.currentTimeMillis(); + System.out.println("Count data time : " + (startTime2 - startTime1)); + DecimalFormat df = new DecimalFormat("0.0"); + returnStr = df.format(intetfaceCoverageRageNumber) + "%"; + }catch (Exception e){ + e.printStackTrace(); + } + return returnStr; } @GetMapping("/scheduleTaskInfoCount/{projectId}") @@ -346,11 +374,11 @@ public class APITestController { @GetMapping("/runningTask/{projectID}/{callFrom}") public List runningTask(@PathVariable String projectID, @PathVariable String callFrom) { List typeFilter = new ArrayList<>(); - if(StringUtils.equals(callFrom, "api_test")) { // 接口测试首页显示的运行中定时任务,只要这3种,不需要 性能测试、api_test(旧版) + if (StringUtils.equals(callFrom, "api_test")) { // 接口测试首页显示的运行中定时任务,只要这3种,不需要 性能测试、api_test(旧版) typeFilter.add(ScheduleGroup.API_SCENARIO_TEST.name()); typeFilter.add(ScheduleGroup.SWAGGER_IMPORT.name()); typeFilter.add(ScheduleGroup.TEST_PLAN_TEST.name()); - } else if(StringUtils.equals(callFrom, "track_home")) { // 测试跟踪首页只显示测试计划的定时任务 + } else if (StringUtils.equals(callFrom, "track_home")) { // 测试跟踪首页只显示测试计划的定时任务 typeFilter.add(ScheduleGroup.TEST_PLAN_TEST.name()); } List resultList = scheduleService.findRunningTaskInfoByProjectID(projectID, typeFilter); @@ -386,7 +414,7 @@ public class APITestController { String testName = runRequest.getName(); //将jmx处理封装为通用方法 - JmxInfoDTO dto = apiTestService.updateJmxString(jmxString,testName,false); + JmxInfoDTO dto = apiTestService.updateJmxString(jmxString, testName, false); dto.setName(runRequest.getName() + ".jmx"); return dto; } diff --git a/backend/src/main/java/io/metersphere/api/dto/datacount/response/ApiDataCountDTO.java b/backend/src/main/java/io/metersphere/api/dto/datacount/response/ApiDataCountDTO.java index 1ed49369c7..088cb896f5 100644 --- a/backend/src/main/java/io/metersphere/api/dto/datacount/response/ApiDataCountDTO.java +++ b/backend/src/main/java/io/metersphere/api/dto/datacount/response/ApiDataCountDTO.java @@ -111,6 +111,11 @@ public class ApiDataCountDTO { */ private String successRage = " 0%"; + /** + * 接口覆盖率 + */ + private String interfaceCoverage = " 0%"; + public ApiDataCountDTO(){} /** diff --git a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java index 33626513da..1694d72efe 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -1,6 +1,7 @@ package io.metersphere.api.service; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONPath; import com.fasterxml.jackson.core.type.TypeReference; @@ -710,6 +711,10 @@ public class ApiAutomationService { return extApiScenarioMapper.countByProjectID(projectId); } + public List selectIdAndScenarioByProjectId(String projectId) { + return extApiScenarioMapper.selectIdAndScenarioByProjectId(projectId); + } + public long countScenarioByProjectIDAndCreatInThisWeek(String projectId) { Map startAndEndDateInWeek = DateUtils.getWeedFirstTimeAndLastTime(new Date()); Date firstTime = startAndEndDateInWeek.get("firstTime"); @@ -1031,4 +1036,131 @@ public class ApiAutomationService { this.deleteBatch(request.getIds()); } + + /** + * 统计接口覆盖率 + * 1.场景中复制的接口 + * 2.场景中引用/复制的案例 + * 3.场景中的自定义路径与接口定义中的匹配 + * + * @param allScenarioInfoList 场景集合(id / scenario大字段 必须有数据) + * @param allEffectiveApiList 接口集合(id / path 必须有数据) + * @param allEffectiveApiCaseList 案例集合(id /api_definition_id 必须有数据) + * @return + */ + public float countInterfaceCoverage(List allScenarioInfoList, List allEffectiveApiList, List allEffectiveApiCaseList) { +// float coverageRageNumber = (float) apiCountResult.getExecutionPassCount() * 100 / allCount; + float intetfaceCoverage = 0; + if (allEffectiveApiList == null || allEffectiveApiList.isEmpty()) { + return 100; + } + + /** + * 前置工作: + * 1。将接口集合转化数据结构: map> urlMap 用来做3的筛选 + * 2。将案例集合转化数据结构:map> caseIdMap 用来做2的筛选 + * 3。将接口集合转化数据结构: List allApiIdList 用来做1的筛选 + * 4。自定义List coveragedIdList 已覆盖的id集合。 最终计算公式是 coveragedIdList/allApiIdList + * + * 解析allScenarioList的scenarioDefinition字段。 + * 1。提取每个步骤的url。 在 urlMap筛选 + * 2。提取每个步骤的id. 在caseIdMap 和 allApiIdList。 + */ + Map> urlMap = new HashMap<>(); + List allApiIdList = new ArrayList<>(); + Map> caseIdMap = new HashMap<>(); + for (ApiDefinition model : allEffectiveApiList) { + String url = model.getPath(); + String id = model.getId(); + allApiIdList.add(id); + if (urlMap.containsKey(url)) { + urlMap.get(url).add(id); + } else { + List list = new ArrayList<>(); + list.add(id); + urlMap.put(url, list); + } + } + for (ApiTestCase model : allEffectiveApiCaseList){ + String caseId = model.getId(); + String apiId = model.getApiDefinitionId(); + if (urlMap.containsKey(caseId)) { + urlMap.get(caseId).add(apiId); + } else { + List list = new ArrayList<>(); + list.add(apiId); + urlMap.put(caseId, list); + } + } + + if (allApiIdList.isEmpty()) { + return 100; + } + + List urlList = new ArrayList<>(); + List idList= new ArrayList<>(); + + for (ApiScenarioWithBLOBs model : allScenarioInfoList) { + String scenarioDefiniton = model.getScenarioDefinition(); + this.addUrlAndIdToList(scenarioDefiniton,urlList,idList); + } + + List containsApiIdList = new ArrayList<>(); + + for (String url : urlList) { + List apiIdList = urlMap.get(url); + if(apiIdList!=null ){ + for (String api : apiIdList) { + if(!containsApiIdList.contains(api)){ + containsApiIdList.add(api); + } + } + } + } + + for (String id : idList) { + List apiIdList = caseIdMap.get(id); + if(apiIdList!=null ){ + for (String api : apiIdList) { + if(!containsApiIdList.contains(api)){ + containsApiIdList.add(api); + } + } + } + + if(allApiIdList.contains(id)){ + if(!containsApiIdList.contains(id)){ + containsApiIdList.add(id); + } + } + } + + float coverageRageNumber = (float) containsApiIdList.size() * 100 / allApiIdList.size(); + return coverageRageNumber; + } + + private void addUrlAndIdToList(String scenarioDefiniton, List urlList, List idList) { + try { + JSONObject scenarioObj = JSONObject.parseObject(scenarioDefiniton); + if(scenarioObj.containsKey("hashTree")){ + JSONArray hashArr = scenarioObj.getJSONArray("hashTree"); + for (int i = 0; i < hashArr.size(); i++) { + JSONObject elementObj = hashArr.getJSONObject(i); + if(elementObj.containsKey("id")){ + String id = elementObj.getString("id"); + idList.add(id); + } + if(elementObj.containsKey("url")){ + String url = elementObj.getString("url"); + urlList.add(url); + } + if(elementObj.containsKey("path")){ + String path = elementObj.getString("path"); + urlList.add(path); + } + } + } + }catch (Exception e){ + } + } } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java index 7884538fcc..eb3847aaf5 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -912,4 +912,8 @@ public class ApiDefinitionService { } return apiExportResult; } + + public List selectEffectiveIdByProjectId(String projectId) { + return extApiDefinitionMapper.selectEffectiveIdByProjectId(projectId); + } } diff --git a/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java b/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java index aa7f0724a4..341c68747e 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java @@ -648,4 +648,8 @@ public class ApiTestCaseService { public ApiDefinitionExecResult getInfo(String id){ return apiDefinitionExecResultMapper.selectByPrimaryKey(id); } + + public List selectEffectiveTestCaseByProjectId(String projectId) { + return extApiTestCaseMapper.selectEffectiveTestCaseByProjectId(projectId); + } } diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiDefinitionMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiDefinitionMapper.java index 44cf4c6abe..3230662b65 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiDefinitionMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiDefinitionMapper.java @@ -38,4 +38,6 @@ public interface ExtApiDefinitionMapper { List listRelevance(@Param("request")ApiDefinitionRequest request); List listRelevanceReview(@Param("request")ApiDefinitionRequest request); List selectIds(@Param("request") BaseQueryRequest query); + + List selectEffectiveIdByProjectId(String projectId); } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiDefinitionMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiDefinitionMapper.xml index bfaa0afcd0..7067ce9a49 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiDefinitionMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiDefinitionMapper.xml @@ -465,6 +465,11 @@ + diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.java index 6bd9153db2..d7d397f6bb 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.java @@ -6,7 +6,6 @@ import io.metersphere.api.dto.datacount.ApiDataCountResult; import io.metersphere.base.domain.ApiScenario; import io.metersphere.base.domain.ApiScenarioExample; import io.metersphere.base.domain.ApiScenarioWithBLOBs; -import io.metersphere.controller.request.BaseQueryRequest; import org.apache.ibatis.annotations.Param; import java.util.List; @@ -28,6 +27,8 @@ public interface ExtApiScenarioMapper { long countByProjectID(String projectId); + List selectIdAndScenarioByProjectId(String projectId); + long countByProjectIDAndCreatInThisWeek(@Param("projectId") String projectId, @Param("firstDayTimestamp") long firstDayTimestamp, @Param("lastDayTimestamp") long lastDayTimestamp); List countRunResultByProjectID(String projectId); diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml index c7db6225fe..db83f076af 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiScenarioMapper.xml @@ -304,6 +304,9 @@ + select name from api_test_case where project_id = #{projectId} + \ No newline at end of file diff --git a/frontend/src/business/components/api/homepage/ApiTestHomePage.vue b/frontend/src/business/components/api/homepage/ApiTestHomePage.vue index dd5236a8e8..1bd4373d58 100644 --- a/frontend/src/business/components/api/homepage/ApiTestHomePage.vue +++ b/frontend/src/business/components/api/homepage/ApiTestHomePage.vue @@ -34,7 +34,7 @@ - + @@ -82,6 +82,7 @@ export default { sceneCountData: {}, testCaseCountData: {}, scheduleTaskCountData: {}, + interfaceCoverage: "waitting...", tipsType: "1", result: {}, } @@ -109,6 +110,10 @@ export default { this.sceneCountData = response.data; }); + this.$get("/api/countInterfaceCoverage/" + selectProjectId, response => { + this.interfaceCoverage = response.data; + }); + this.$get("/api/testCaseInfoCount/" + selectProjectId, response => { this.testCaseCountData = response.data; }); diff --git a/frontend/src/business/components/api/homepage/components/SceneInfoCard.vue b/frontend/src/business/components/api/homepage/components/SceneInfoCard.vue index e048e5c050..19f64837d2 100644 --- a/frontend/src/business/components/api/homepage/components/SceneInfoCard.vue +++ b/frontend/src/business/components/api/homepage/components/SceneInfoCard.vue @@ -52,16 +52,29 @@ - - + + {{$t('api_test.home_page.detail_card.rate.pass')+":"}} - - + + {{sceneCountData.passRage}} + + + {{$t('api_test.home_page.detail_card.rate.interface_coverage')+":"}} + + + + {{interfaceCoverage}} + + + {{interfaceCoverage}} + + + @@ -120,6 +133,7 @@ export default { props:{ sceneCountData:{}, + interfaceCoverage:String, }, methods: { @@ -141,6 +155,13 @@ export default { margin:20px auto; } +.rows-count-number{ + font-family:'ArialMT', 'Arial', sans-serif; + font-size:30px; + color: var(--count_number); + margin:20px auto; +} + .main-number-show { width: 100px; height: 100px; diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index 94837b728c..3ffb614514 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -1001,6 +1001,7 @@ export default { coverage: "Coverage rate", pass: "Pass rate", success: "Success rate", + interface_coverage: "Interface coverage", }, }, api_details_card: { diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index 251d71ac48..5039195966 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -1005,6 +1005,7 @@ export default { coverage: "覆盖率", pass: "通过率", success: "成功率", + interface_coverage: "接口覆盖率", }, }, api_details_card: { diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index e9f8dddcd4..2a6ca86ab7 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -1003,6 +1003,7 @@ export default { coverage: "覆蓋率", pass: "通過率", success: "成功率", + interface_coverage: "接口覆蓋率", }, }, api_details_card: { From bbfa3d0cb4418f8a42f3ad5c330f0e563a7c665b Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Wed, 31 Mar 2021 14:55:19 +0800 Subject: [PATCH 7/7] =?UTF-8?q?refactor:=20=E5=8D=87=E7=BA=A7=20openapi=20?= =?UTF-8?q?swagger=20=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/pom.xml b/backend/pom.xml index c54fc88b7c..7c5cb8a95b 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -139,7 +139,7 @@ org.springdoc springdoc-openapi-ui - 1.2.32 + 1.5.6 @@ -280,7 +280,7 @@ io.swagger.parser.v3 swagger-parser - 2.0.22 + 2.0.24