From be21158f606a27dcebb4af53ffd3d6c7e95f6511 Mon Sep 17 00:00:00 2001 From: q4speed Date: Wed, 22 Jul 2020 11:02:26 +0800 Subject: [PATCH 1/9] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8D=E5=9C=BA=E6=99=AF=E7=9A=84Dubbo=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=9C=89=E9=BB=98=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/api/test/model/ScenarioModel.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/frontend/src/business/components/api/test/model/ScenarioModel.js b/frontend/src/business/components/api/test/model/ScenarioModel.js index 52c262b027..965b35b0e1 100644 --- a/frontend/src/business/components/api/test/model/ScenarioModel.js +++ b/frontend/src/business/components/api/test/model/ScenarioModel.js @@ -194,6 +194,18 @@ class DubboConfig extends BaseConfig { super(); this.configCenter = new ConfigCenter(options.configCenter) this.registryCenter = new RegistryCenter(options.registryCenter) + if (options.consumerAndService === undefined) { + options.consumerAndService = { + timeout: undefined, + version: undefined, + retries: undefined, + cluster: undefined, + group: undefined, + connections: undefined, + async: undefined, + loadBalance: undefined + } + } this.consumerAndService = new ConsumerAndService(options.consumerAndService) } } @@ -259,7 +271,7 @@ export class HttpRequest extends Request { } isValid(environmentId) { - if (this.useEnvironment){ + if (this.useEnvironment) { if (!environmentId) { return { isValid: false, From 7365355d8e174ac7a3bc6fe08c4e77af92bf1850 Mon Sep 17 00:00:00 2001 From: q4speed Date: Wed, 22 Jul 2020 12:22:29 +0800 Subject: [PATCH 2/9] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8Dinterface=E9=87=8D=E5=A4=8Dbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/service/APITestService.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/backend/src/main/java/io/metersphere/api/service/APITestService.java b/backend/src/main/java/io/metersphere/api/service/APITestService.java index d0a9704d40..9dcffef0fe 100644 --- a/backend/src/main/java/io/metersphere/api/service/APITestService.java +++ b/backend/src/main/java/io/metersphere/api/service/APITestService.java @@ -263,7 +263,7 @@ public class APITestService { ApiImportParser apiImportParser = ApiImportParserFactory.getApiImportParser(request.getPlatform()); ApiImport apiImport = null; try { - apiImport = apiImportParser.parse(file.getInputStream(), request); + apiImport = Objects.requireNonNull(apiImportParser).parse(file.getInputStream(), request); } catch (Exception e) { LogUtil.error(e.getMessage(), e); MSException.throwException(Translator.get("parse_data_error")); @@ -290,21 +290,26 @@ public class APITestService { } public List getProviders(RegistryCenter registry) { - ProviderService providerService = ProviderService.get("provider"); + ProviderService providerService = ProviderService.get(registry.getAddress()); List providers = providerService.getProviders(registry.getProtocol(), registry.getAddress(), registry.getGroup()); - List providerList = new ArrayList<>(); + List list = new ArrayList<>(); providers.forEach(p -> { + DubboProvider provider = new DubboProvider(); + String[] info = p.split(":"); + if (info.length > 1) { + provider.setVersion(info[1]); + } + provider.setService(info[0]); + provider.setServiceInterface(p); Map services = providerService.findByService(p); - services.forEach((k, v) -> { - DubboProvider provider = new DubboProvider(); - provider.setVersion(v.getParameter("version")); - provider.setService(v.getServiceKey()); - provider.setServiceInterface(v.getServiceInterface()); - String[] methods = v.getParameter("methods").split(","); + if (services != null && !services.isEmpty()) { + String[] methods = services.values().stream().findFirst().get().getParameter("methods").split(","); provider.setMethods(Arrays.asList(methods)); - providerList.add(provider); - }); + } else { + provider.setMethods(new ArrayList<>()); + } + list.add(provider); }); - return providerList; + return list; } } From 621b1380c33ed674ad14a691d829d4c0b89fb251 Mon Sep 17 00:00:00 2001 From: noonkho Date: Wed, 22 Jul 2020 12:26:06 +0800 Subject: [PATCH 3/9] Add README_EN.md --- README.md | 4 +- README_EN.md | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 1 deletion(-) mode change 100644 => 100755 README.md create mode 100755 README_EN.md diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 3992f40dee..a8b8634fad --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/metersphere/metersphere)](https://github.com/metersphere/metersphere/releases/latest) [![GitHub All Releases](https://img.shields.io/github/downloads/metersphere/metersphere/total)](https://github.com/metersphere/metersphere/releases) +> [English](README_EN.md) | 中文 + MeterSphere 是一站式的开源企业级持续测试平台,涵盖测试跟踪、接口测试、性能测试、团队协作等功能,兼容JMeter 等开源标准,有效助力开发和测试团队充分利用云弹性进行高度可扩展的自动化测试,加速高质量软件的交付。 - 测试跟踪: 远超 TestLink 的使用体验; @@ -172,7 +174,7 @@ v1.1.0 是 v1.0.0 之后的功能版本。 -详细版本规划请参考 [版本路线图](https://github.com/metersphere/metersphere/blob/master/ROADMAP.md) +详细的版本规划请参考 [版本路线图](https://github.com/metersphere/metersphere/blob/master/ROADMAP.md) ## 技术栈 diff --git a/README_EN.md b/README_EN.md new file mode 100755 index 0000000000..e94f9ec3d1 --- /dev/null +++ b/README_EN.md @@ -0,0 +1,170 @@ +# MeterSphere : Open-source Continuous Testing Platform + +[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/metersphere/metersphere)](https://github.com/metersphere/metersphere/releases/latest) +[![GitHub All Releases](https://img.shields.io/github/downloads/metersphere/metersphere/total)](https://github.com/metersphere/metersphere/releases) + +> [中文](README.md) | English + +MeterSphere is a one-stop open-source enterprise-class continuous testing platform. It covers functions such as tests tracking, interface testing, performance testing, team collaboration and is compatible with open-source standards such as JMeter. It helps development and testing teams to conduct highly scalable automated testing, making full use of elasticity of the cloud, and accelerating the delivery process of high-quality software. + +- Test Tracking: Far beyond the user experience of TestLink. +- API Testing: Similar to Postman's experience. +- Performance Testing: Compatible with JMeter. Support Kubernetes and Cloud Environment. High concurrency, distributed performance testing with ease. +- Team Collaboration: duo-levels tenants system, naturally support team co-op. + + +## Quick Start + +Only need two steps to install MeterSphere: + +What you need: + 1. Prepare a 64-bit Linux host with no less than 8 G RAM + 2. Log into root user and execute the command down below to install MeterSphere + +```sh +curl -sSL https://github.com/metersphere/metersphere/releases/latest/download/quick_start.sh | sh +``` + +## Technical advantages + +- Full Life Cycle: Full coverage over all STLC phases. Starting from the Test Plan to the Report Creation phase. +- Automation & Scalable: Automation for interface and performance testings. Fully adopt the elasticity of Cloud to produce a large scale of performance testing. +- Continuous Testing: Seamlessly integrated with the CI tools. Supporting enterprises for "Shift left" testing. +- Team Collaboration: Support different proportions of teams. Capable from a group of five to a testing center of several hundred people. + +## Features List + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test TrackingProject managementMulti-project support, test cases, test plan, and project association
Test Cases ManagementOnline editing test case
tree structure display project module and its test cases
Custom test case attributes
Quickly import test cases into the system
Test Plan TrackingInitiate a test plan based on existing test cases
Online update of test case execution results
Flexible test case allocation
Generate test reports online, support custom test report templates
Combine with the interface test and performance test functions in the platform to automatically update the results of associated test cases
Interface TestingTest ScriptOnline editing interface testing content
Support parameterized testing
Pliable assertion support
Support multi-interface scenario testing
Quickly record test script via brower plug-in
Test ReportAutomatically generate test report after test execution
Exportable Test report
Performance TestingTest ScriptFully compatible with JMeter script
Adjust pressure parameter online
Distributed pressure testing
Support parameterized testing
Quickly record test script via brower plug-in
Test ReportAutomatically generate test report after test execution
Rich test report display form
Exportable test report
View test log details
System ManagementTenant managementSupport multi-level tenant system
Support multiple tenant roles
Test resource managementPerformance test resource pool management
Email notification configuration
Integration and expansionComplete API list
Supports continuous integration tools such as Jenkins 
+ + +## Technology stack + +- Backend: [Spring Boot](https://www.tutorialspoint.com/spring_boot/spring_boot_introduction.htm) +- Frontend: [Vue.js](https://vuejs.org/) +- Middleware: [MySQL](https://www.mysql.com/), [Kafka](https://kafka.apache.org/) +- Basic infrastructure: [Docker](https://www.docker.com/), [Kubernetes](https://kubernetes.io/) +- Test engine: [JMeter](https://jmeter.apache.org/) + + +## License & Copyright + +Copyright (c) 2014-2020 飞致云 FIT2CLOUD, All rights reserved. + +Licensed under The GNU General Public License version 2 (GPLv2) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +https://www.gnu.org/licenses/gpl-2.0.html + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. From fc278e6bf788b25a2bcc104ed351011a6d7f38be Mon Sep 17 00:00:00 2001 From: q4speed Date: Wed, 22 Jul 2020 12:26:49 +0800 Subject: [PATCH 4/9] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):?= =?UTF-8?q?=20=E4=BD=BF=E7=94=A8Dubbo=E5=B8=B8=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/metersphere/api/service/APITestService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/io/metersphere/api/service/APITestService.java b/backend/src/main/java/io/metersphere/api/service/APITestService.java index 9dcffef0fe..2d26e31555 100644 --- a/backend/src/main/java/io/metersphere/api/service/APITestService.java +++ b/backend/src/main/java/io/metersphere/api/service/APITestService.java @@ -27,6 +27,7 @@ import io.metersphere.service.FileService; import io.metersphere.service.ScheduleService; import io.metersphere.track.service.TestCaseService; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.constants.CommonConstants; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -303,7 +304,7 @@ public class APITestService { provider.setServiceInterface(p); Map services = providerService.findByService(p); if (services != null && !services.isEmpty()) { - String[] methods = services.values().stream().findFirst().get().getParameter("methods").split(","); + String[] methods = services.values().stream().findFirst().get().getParameter(CommonConstants.METHODS_KEY).split(","); provider.setMethods(Arrays.asList(methods)); } else { provider.setMethods(new ArrayList<>()); From f4100f43e634763f100373630b6597eb1b979552 Mon Sep 17 00:00:00 2001 From: q4speed Date: Wed, 22 Jul 2020 13:19:39 +0800 Subject: [PATCH 5/9] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8Dget=20provider=E6=88=90=E5=8A=9F=E5=90=8E?= =?UTF-8?q?=E7=9A=84=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/api/test/components/request/dubbo/Interface.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/business/components/api/test/components/request/dubbo/Interface.vue b/frontend/src/business/components/api/test/components/request/dubbo/Interface.vue index 776d5530fc..62cab5c43b 100644 --- a/frontend/src/business/components/api/test/components/request/dubbo/Interface.vue +++ b/frontend/src/business/components/api/test/components/request/dubbo/Interface.vue @@ -96,6 +96,7 @@ this.methods = this.methodMap[this.request.interface].methods; } this.loading = false; + this.$success(this.$t('api_test.request.dubbo.get_provider_success')); }).catch(() => { this.loading = false; this.$warning(this.$t('api_test.request.dubbo.check_registry_center')); From c247110668ee3d3f368caaefe0e0806d0f4c8f55 Mon Sep 17 00:00:00 2001 From: q4speed Date: Wed, 22 Jul 2020 13:20:37 +0800 Subject: [PATCH 6/9] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8Dget=20provider=E6=88=90=E5=8A=9F=E5=90=8E?= =?UTF-8?q?=E7=9A=84=E6=8F=90=E7=A4=BA=EF=BC=8Ci18n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/i18n/en-US.js | 1 + frontend/src/i18n/zh-CN.js | 1 + frontend/src/i18n/zh-TW.js | 1 + 3 files changed, 3 insertions(+) diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index ca9385488b..17752dbd7f 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -416,6 +416,7 @@ export default { input_interface: "Please enter the interface", input_method: "Please enter the method", input_config_center: "Please enter the config center", + get_provider_success: "get provider list to finish", input_registry_center: "Please enter the registry center", input_consumer_service: "Please enter the consumer & service", check_registry_center: "Can't get interface list, please check the registry center", diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index e0356c666b..662ed2feba 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -417,6 +417,7 @@ export default { input_config_center: "请输入Config Center", input_registry_center: "请输入Registry Center", input_consumer_service: "请输入Consumer & Service", + get_provider_success: "获取成功", check_registry_center: "获取失败,请检查Registry Center", form_description: "如果当前配置项无值,则取场景配置项的值", } diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index 4db3545c88..f2b13b4ea3 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -415,6 +415,7 @@ export default { input_interface: "請輸入Interface", input_method: "請輸入Method", input_config_center: "請輸入Config Center", + get_provider_success: "獲取成功", input_registry_center: "請輸入Registry Center", input_consumer_service: "請輸入Consumer & Service", check_registry_center: "獲取失敗,請檢查Registry Center", From 0fa304a4097b2f10a8831c19dbdc66b8707210ec Mon Sep 17 00:00:00 2001 From: q4speed Date: Wed, 22 Jul 2020 13:45:54 +0800 Subject: [PATCH 7/9] =?UTF-8?q?style(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95)?= =?UTF-8?q?:=20=E9=81=BF=E5=85=8D=E6=B5=8B=E8=AF=95=E6=8A=A5=E5=91=8Amessa?= =?UTF-8?q?ge=E5=86=85=E5=AE=B9=E6=BA=A2=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/api/report/components/RequestMetric.vue | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/business/components/api/report/components/RequestMetric.vue b/frontend/src/business/components/api/report/components/RequestMetric.vue index 1ebfa0e203..cdffc5d23d 100644 --- a/frontend/src/business/components/api/report/components/RequestMetric.vue +++ b/frontend/src/business/components/api/report/components/RequestMetric.vue @@ -82,7 +82,7 @@ } .metric .code { - width: 120px; + min-width: 120px; } .metric .code .value { @@ -98,4 +98,9 @@ border-left: 1px solid #EBEEF5; margin-right: 20px; } + + .metric .message { + max-height: 114px; + overflow-y: auto; + } From d5562998e8c4a20024ec14c021c23a4122e5ebb7 Mon Sep 17 00:00:00 2001 From: wenyann <64353056+wenyann@users.noreply.github.com> Date: Wed, 22 Jul 2020 15:23:25 +0800 Subject: [PATCH 8/9] =?UTF-8?q?fix:=20=E5=9B=BD=E9=99=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business/components/track/case/components/TestCaseList.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/business/components/track/case/components/TestCaseList.vue b/frontend/src/business/components/track/case/components/TestCaseList.vue index 5a29f6c351..2bcc6ed782 100644 --- a/frontend/src/business/components/track/case/components/TestCaseList.vue +++ b/frontend/src/business/components/track/case/components/TestCaseList.vue @@ -297,7 +297,7 @@ responseType: 'blob' }; this.result = this.$request(config).then(response => { - const filename = '测试用例.xlsx' + const filename = this.$t('test_track.case.test_case') + ".xlsx"; const blob = new Blob([response.data]); if ("download" in document.createElement("a")) { let aTag = document.createElement('a'); From 90489ae2a383b438d436c6b01c5bef443966460c Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Wed, 22 Jul 2020 16:16:59 +0800 Subject: [PATCH 9/9] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E6=80=A7=E8=83=BD=E6=B5=8B=E8=AF=95=E6=97=A5=E5=BF=97=E7=9A=84?= =?UTF-8?q?=E6=8E=92=E5=BA=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/metersphere/performance/service/ReportService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/main/java/io/metersphere/performance/service/ReportService.java b/backend/src/main/java/io/metersphere/performance/service/ReportService.java index 50bcc908fc..96bde66a53 100644 --- a/backend/src/main/java/io/metersphere/performance/service/ReportService.java +++ b/backend/src/main/java/io/metersphere/performance/service/ReportService.java @@ -213,6 +213,7 @@ public class ReportService { public byte[] downloadLog(String reportId, String resourceId) { LoadTestReportLogExample example = new LoadTestReportLogExample(); example.createCriteria().andReportIdEqualTo(reportId).andResourceIdEqualTo(resourceId); + example.setOrderByClause("part desc"); List loadTestReportLogs = loadTestReportLogMapper.selectByExampleWithBLOBs(example); String content = loadTestReportLogs.stream().map(LoadTestReportLog::getContent).reduce("", (a, b) -> a + b);