Commit 0b1a0964 authored by shiziyuan9527's avatar shiziyuan9527
Browse files

Merge branch 'v1.1' of https://github.com/metersphere/metersphere into v1.1

parents ffd4ae42 67503e6d
Showing with 283 additions and 51 deletions
+283 -51
......@@ -172,7 +172,7 @@ v1.1.0 是 v1.0.0 之后的功能版本。
</tbody>
</table>
详细版本规划请参考 [版本路线图](https://github.com/metersphere/metersphere/blob/master/ROADMAP.md)
详细版本规划请参考 [版本路线图](https://github.com/metersphere/metersphere/blob/master/ROADMAP.md)
## 技术栈
......
......@@ -123,7 +123,7 @@
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.45</version>
<version>1.2.72</version>
</dependency>
<dependency>
......@@ -201,17 +201,6 @@
<version>2.1.7</version>
</dependency>
<!--
该依赖是私有仓库的依赖,现已经发布到 Github Packages,下载请在 settings 文件中配置自己的 GITHUB_TOKEN
示例:
<servers>
<server>
<id>github</id>
<username>USERNAME</username>
<password>TOKEN</password>
</server>
</servers>
-->
<dependency>
<groupId>com.fit2cloud</groupId>
<artifactId>quartz-spring-boot-starter</artifactId>
......@@ -358,18 +347,33 @@
</plugins>
</build>
<!--
项目中依赖了某些私有仓库的包,现已经发布到 Github Packages,
开发者下载依赖可按照 Github Maven 仓库的使用指导添加 Maven 仓库地址:https://docs.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-apache-maven-for-use-with-github-packages
示例:下载请在 settings 文件中配置自己 Github 账号和 GITHUB_TOKEN
<servers>
<server>
<id>fit2cloud</id>
<username>USERNAME</username>
<password>TOKEN</password>
</server>
<server>
<id>metersphere</id>
<username>USERNAME</username>
<password>TOKEN</password>
</server>
</servers>
-->
<repositories>
<repository>
<id>github</id>
<id>fit2cloud</id>
<name>fit2cloud</name>
<url>https://maven.pkg.github.com/fit2cloud/quartz-spring-boot-starter</url>
</repository>
<repository>
<id>github</id>
<id>metersphere</id>
<name>metersphere</name>
<url>https://maven.pkg.github.com/metersphere/jmeter-plugins-for-apache-dubbo</url>
</repository>
</repositories>
</project>
\ No newline at end of file
......@@ -3,6 +3,7 @@ package io.metersphere.api.controller;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.api.dto.*;
import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter;
import io.metersphere.api.service.APITestService;
import io.metersphere.base.domain.ApiTest;
import io.metersphere.base.domain.Schedule;
......@@ -94,8 +95,12 @@ public class APITestController {
@PostMapping(value = "/import", consumes = {"multipart/form-data"})
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public ApiTest testCaseImport(@RequestPart(value = "file") MultipartFile file, @RequestPart("request") ApiTestImportRequest request) {
public ApiTest testCaseImport(@RequestPart(value = "file") MultipartFile file, @RequestPart("request") ApiTestImportRequest request) {
return apiTestService.apiTestImport(file, request);
}
@PostMapping("/dubbo/providers")
public List<DubboProvider> getProviders(@RequestBody RegistryCenter registry) {
return apiTestService.getProviders(registry);
}
}
package io.metersphere.api.dto;
import lombok.Data;
import java.util.List;
@Data
public class DubboProvider {
private String version;
private String service;
private String serviceInterface;
private List<String> methods;
}
package io.metersphere.api.dto.scenario;
import io.metersphere.api.dto.scenario.request.dubbo.ConfigCenter;
import io.metersphere.api.dto.scenario.request.dubbo.ConsumerAndService;
import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter;
import lombok.Data;
@Data
public class DubboConfig {
private ConfigCenter configCenter;
private RegistryCenter registryCenter;
private ConsumerAndService consumerAndService;
}
package io.metersphere.api.dto.scenario;
import io.metersphere.api.dto.scenario.request.Request;
import lombok.Data;
import java.util.List;
......@@ -12,4 +13,5 @@ public class Scenario {
private List<KeyValue> variables;
private List<KeyValue> headers;
private List<Request> requests;
private DubboConfig dubboConfig;
}
package io.metersphere.api.dto.scenario.request;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.annotation.JSONType;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.assertions.Assertions;
import io.metersphere.api.dto.scenario.extract.Extract;
import io.metersphere.api.dto.scenario.request.dubbo.ConfigCenter;
import io.metersphere.api.dto.scenario.request.dubbo.ConsumerAndService;
import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter;
import lombok.Data;
import java.util.List;
@Data
@JSONType(typeName = RequestType.DUBBO)
public class DubboRequest implements Request {
// type 必须放最前面,以便能够转换正确的类
private String type = RequestType.DUBBO;
@JSONField(ordinal = 1)
private String name;
@JSONField(ordinal = 2)
private String protocol;
@JsonProperty(value = "interface")
@JSONField(ordinal = 3, name = "interface")
private String _interface;
@JSONField(ordinal = 4)
private String method;
@JSONField(ordinal = 5)
private ConfigCenter configCenter;
@JSONField(ordinal = 6)
private RegistryCenter registryCenter;
@JSONField(ordinal = 7)
private ConsumerAndService consumerAndService;
@JSONField(ordinal = 8)
private List<KeyValue> args;
@JSONField(ordinal = 9)
private List<KeyValue> attachmentArgs;
@JSONField(ordinal = 10)
private Assertions assertions;
@JSONField(ordinal = 11)
private Extract extract;
}
package io.metersphere.api.dto.scenario;
package io.metersphere.api.dto.scenario.request;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.annotation.JSONType;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.assertions.Assertions;
import io.metersphere.api.dto.scenario.extract.Extract;
import lombok.Data;
......@@ -7,15 +11,28 @@ import lombok.Data;
import java.util.List;
@Data
public class Request {
@JSONType(typeName = RequestType.HTTP)
public class HttpRequest implements Request {
// type 必须放最前面,以便能够转换正确的类
private String type = RequestType.HTTP;
@JSONField(ordinal = 1)
private String name;
@JSONField(ordinal = 2)
private String url;
@JSONField(ordinal = 3)
private String method;
private Boolean useEnvironment;
@JSONField(ordinal = 4)
private String path;
@JSONField(ordinal = 5)
private Boolean useEnvironment;
@JSONField(ordinal = 6)
private List<KeyValue> parameters;
@JSONField(ordinal = 7)
private List<KeyValue> headers;
@JSONField(ordinal = 8)
private Body body;
@JSONField(ordinal = 9)
private Assertions assertions;
@JSONField(ordinal = 10)
private Extract extract;
}
package io.metersphere.api.dto.scenario.request;
import com.alibaba.fastjson.annotation.JSONType;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = HttpRequest.class, name = RequestType.HTTP),
@JsonSubTypes.Type(value = DubboRequest.class, name = RequestType.DUBBO)
})
@JSONType(seeAlso = {HttpRequest.class, DubboRequest.class}, typeKey = "type")
public interface Request {
}
package io.metersphere.api.dto.scenario.request;
public class RequestType {
public static final String HTTP = "HTTP";
public static final String DUBBO = "DUBBO";
}
package io.metersphere.api.dto.scenario.request.dubbo;
import lombok.Data;
@Data
public class ConfigCenter {
private String protocol;
private String group;
private String namespace;
private String username;
private String address;
private String password;
private String timeout;
}
package io.metersphere.api.dto.scenario.request.dubbo;
import lombok.Data;
@Data
public class ConsumerAndService {
private String timeout;
private String version;
private String retries;
private String cluster;
private String group;
private String connections;
private String async;
private String loadBalance;
}
package io.metersphere.api.dto.scenario.request.dubbo;
import lombok.Data;
@Data
public class RegistryCenter {
private String protocol;
private String group;
private String username;
private String address;
private String password;
private String timeout;
}
package io.metersphere.api.jmeter;
import io.github.ningyu.jmeter.plugin.dubbo.sample.ProviderService;
import io.metersphere.api.service.APIReportService;
import io.metersphere.api.service.APITestService;
import io.metersphere.commons.constants.APITestStatus;
......@@ -107,14 +108,11 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
}
private RequestResult getRequestResult(SampleResult result) {
String body = result.getSamplerData();
String method = StringUtils.substringBefore(body, " ");
RequestResult requestResult = new RequestResult();
requestResult.setName(result.getSampleLabel());
requestResult.setUrl(result.getUrlAsString());
requestResult.setMethod(method);
requestResult.setBody(body);
requestResult.setMethod(getMethod(result));
requestResult.setBody(result.getSamplerData());
requestResult.setHeaders(result.getRequestHeaders());
requestResult.setRequestSize(result.getSentBytes());
requestResult.setTotalAssertions(result.getAssertionResults().length);
......@@ -143,6 +141,19 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
return requestResult;
}
private String getMethod(SampleResult result) {
String body = result.getSamplerData();
// Dubbo Protocol
String start = "RPC Protocol: ";
String end = "://";
if (StringUtils.contains(body, start)) {
return StringUtils.substringBetween(body, start, end).toUpperCase();
} else {
// Http Method
return StringUtils.substringBefore(body, " ");
}
}
private ResponseAssertionResult getResponseAssertionResult(AssertionResult assertionResult) {
ResponseAssertionResult responseAssertionResult = new ResponseAssertionResult();
responseAssertionResult.setMessage(assertionResult.getFailureMessage());
......
......@@ -2,8 +2,8 @@ package io.metersphere.api.parse;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.Request;
import io.metersphere.api.dto.scenario.Scenario;
import io.metersphere.api.dto.scenario.request.HttpRequest;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.lang3.StringUtils;
......@@ -50,11 +50,11 @@ public abstract class ApiImportAbstractParser implements ApiImportParser {
}
}
protected void addContentType(Request request, String contentType) {
protected void addContentType(HttpRequest request, String contentType) {
addHeader(request, HttpHeader.CONTENT_TYPE.toString(), contentType);
}
protected void addCookie(Request request, String key, String value) {
protected void addCookie(HttpRequest request, String key, String value) {
List<KeyValue> headers = Optional.ofNullable(request.getHeaders()).orElse(new ArrayList<>());
boolean hasCookie = false;
for (KeyValue header : headers) {
......@@ -69,7 +69,7 @@ public abstract class ApiImportAbstractParser implements ApiImportParser {
}
}
protected void addHeader(Request request, String key, String value) {
protected void addHeader(HttpRequest request, String key, String value) {
List<KeyValue> headers = Optional.ofNullable(request.getHeaders()).orElse(new ArrayList<>());
boolean hasContentType = false;
for (KeyValue header : headers) {
......
......@@ -7,8 +7,9 @@ import io.metersphere.api.dto.parse.ApiImport;
import io.metersphere.api.dto.parse.postman.*;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.Request;
import io.metersphere.api.dto.scenario.request.HttpRequest;
import io.metersphere.api.dto.scenario.Scenario;
import io.metersphere.api.dto.scenario.request.Request;
import io.metersphere.commons.constants.MsRequestBodyType;
import io.metersphere.commons.constants.PostmanRequestBodyMode;
import org.apache.commons.lang3.StringUtils;
......@@ -62,7 +63,7 @@ public class PostmanParser extends ApiImportAbstractParser {
List<PostmanItem> item = postmanCollection.getItem();
List<Request> requests = new ArrayList<>();
for (PostmanItem requestItem : item) {
Request request = new Request();
HttpRequest request = new HttpRequest();
PostmanRequest requestDesc = requestItem.getRequest();
PostmanUrl url = requestDesc.getUrl();
request.setName(requestItem.getName());
......@@ -77,7 +78,7 @@ public class PostmanParser extends ApiImportAbstractParser {
return requests;
}
private Body parseBody(PostmanRequest requestDesc, Request request) {
private Body parseBody(PostmanRequest requestDesc, HttpRequest request) {
Body body = new Body();
JSONObject postmanBody = requestDesc.getBody();
if (postmanBody == null) {
......
......@@ -6,8 +6,9 @@ import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.parse.ApiImport;
import io.metersphere.api.dto.scenario.Body;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.Request;
import io.metersphere.api.dto.scenario.request.HttpRequest;
import io.metersphere.api.dto.scenario.Scenario;
import io.metersphere.api.dto.scenario.request.Request;
import io.metersphere.commons.constants.MsRequestBodyType;
import io.metersphere.commons.constants.SwaggerParameterType;
import io.swagger.models.*;
......@@ -51,7 +52,7 @@ public class Swagger2Parser extends ApiImportAbstractParser {
Set<HttpMethod> httpMethods = operationMap.keySet();
for (HttpMethod method : httpMethods) {
Operation operation = operationMap.get(method);
Request request = new Request();
HttpRequest request = new HttpRequest();
request.setName(operation.getOperationId());
request.setPath(pathName);
request.setUseEnvironment(true);
......@@ -76,13 +77,11 @@ public class Swagger2Parser extends ApiImportAbstractParser {
}
}
scenarioMap.values().forEach(scenario -> {
scenarios.add(scenario);
});
scenarios.addAll(scenarioMap.values());
return scenarios;
}
private void parseParameters(Operation operation, Map<String, Model> definitions, Request request) {
private void parseParameters(Operation operation, Map<String, Model> definitions, HttpRequest request) {
List<Parameter> parameters = operation.getParameters();
......@@ -113,17 +112,17 @@ public class Swagger2Parser extends ApiImportAbstractParser {
}
}
private void parseCookieParameters(Parameter parameter, Request request) {
private void parseCookieParameters(Parameter parameter, HttpRequest request) {
CookieParameter cookieParameter = (CookieParameter) parameter;
addCookie(request, cookieParameter.getName(), cookieParameter.getDescription());
}
private void parseHeaderParameters(Parameter parameter, Request request) {
private void parseHeaderParameters(Parameter parameter, HttpRequest request) {
HeaderParameter headerParameter = (HeaderParameter) parameter;
addHeader(request, headerParameter.getName(), headerParameter.getDescription());
}
private void parseBodyParameters(Parameter parameter, Request request, Map<String, Model> definitions) {
private void parseBodyParameters(Parameter parameter, HttpRequest request, Map<String, Model> definitions) {
BodyParameter bodyParameter = (BodyParameter) parameter;
Body body = Optional.ofNullable(request.getBody()).orElse(new Body());
body.setType(MsRequestBodyType.RAW.value());
......@@ -175,7 +174,7 @@ public class Swagger2Parser extends ApiImportAbstractParser {
return jsonObject;
}
private void parseFormDataParameters(Parameter parameter, Request request) {
private void parseFormDataParameters(Parameter parameter, HttpRequest request) {
Body body = Optional.ofNullable(request.getBody()).orElse(new Body());
body.setType(MsRequestBodyType.FORM_DATA.value());
List<KeyValue> keyValues = Optional.ofNullable(body.getKvs()).orElse(new ArrayList<>());
......@@ -184,7 +183,7 @@ public class Swagger2Parser extends ApiImportAbstractParser {
request.setBody(body);
}
private void parseQueryParameters(Parameter parameter, Request request) {
private void parseQueryParameters(Parameter parameter, HttpRequest request) {
QueryParameter queryParameter = (QueryParameter) parameter;
List<KeyValue> parameters = Optional.ofNullable(request.getParameters()).orElse(new ArrayList<>());
parameters.add(new KeyValue(queryParameter.getName(), "", queryParameter.getDescription()));
......
package io.metersphere.api.service;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.APITestResult;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.QueryAPITestRequest;
import io.metersphere.api.dto.SaveAPITestRequest;
import io.github.ningyu.jmeter.plugin.dubbo.sample.ProviderService;
import io.metersphere.api.dto.*;
import io.metersphere.api.dto.parse.ApiImport;
import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter;
import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.parse.ApiImportParser;
import io.metersphere.api.parse.ApiImportParserFactory;
......@@ -27,18 +26,17 @@ import io.metersphere.job.sechedule.ApiTestJob;
import io.metersphere.service.FileService;
import io.metersphere.service.ScheduleService;
import io.metersphere.track.service.TestCaseService;
import org.apache.dubbo.common.URL;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
@Service
......@@ -290,4 +288,23 @@ public class APITestService {
}
return request;
}
public List<DubboProvider> getProviders(RegistryCenter registry) {
ProviderService providerService = ProviderService.get("provider");
List<String> providers = providerService.getProviders(registry.getProtocol(), registry.getAddress(), registry.getGroup());
List<DubboProvider> providerList = new ArrayList<>();
providers.forEach(p -> {
Map<String, URL> 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(",");
provider.setMethods(Arrays.asList(methods));
providerList.add(provider);
});
});
return providerList;
}
}
......@@ -101,7 +101,7 @@
<select id="getLoadTestByProjectId" resultType="io.metersphere.base.domain.LoadTest">
select id,name
from load_test
where project_id = #{projectId};
where project_id = #{projectId}
</select>
</mapper>
\ No newline at end of file
package io.metersphere.track.domain;
import io.metersphere.commons.constants.TestPlanTestCaseStatus;
import io.metersphere.track.dto.TestCaseReportMetricDTO;
import io.metersphere.track.dto.TestCaseReportStatusResultDTO;
import io.metersphere.track.dto.TestPlanCaseDTO;
......@@ -7,6 +8,7 @@ import io.metersphere.track.dto.TestPlanDTO;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ReportResultChartComponent extends ReportComponent {
......@@ -25,7 +27,24 @@ public class ReportResultChartComponent extends ReportComponent {
@Override
public void afterBuild(TestCaseReportMetricDTO testCaseReportMetric) {
testCaseReportMetric.setExecuteResult(new ArrayList<>(reportStatusResultMap.values()));
testCaseReportMetric.setExecuteResult(getReportStatusResult());
}
private List<TestCaseReportStatusResultDTO> getReportStatusResult() {
List<TestCaseReportStatusResultDTO> reportStatusResult = new ArrayList<>();
addToReportStatusResultList(reportStatusResult, TestPlanTestCaseStatus.Pass.name());
addToReportStatusResultList(reportStatusResult, TestPlanTestCaseStatus.Failure.name());
addToReportStatusResultList(reportStatusResult, TestPlanTestCaseStatus.Blocking.name());
addToReportStatusResultList(reportStatusResult, TestPlanTestCaseStatus.Skip.name());
addToReportStatusResultList(reportStatusResult, TestPlanTestCaseStatus.Underway.name());
addToReportStatusResultList(reportStatusResult, TestPlanTestCaseStatus.Prepare.name());
return reportStatusResult;
}
private void addToReportStatusResultList(List<TestCaseReportStatusResultDTO> reportStatusResultList, String status) {
if (reportStatusResultMap.get(status) != null) {
reportStatusResultList.add(reportStatusResultMap.get(status));
}
}
private void getStatusResultMap(Map<String, TestCaseReportStatusResultDTO> reportStatusResultMap, TestPlanCaseDTO testCase) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment