This commit is contained in:
chenjianxing 2020-12-24 11:37:28 +08:00
commit 0de9d0a073
14 changed files with 97 additions and 70 deletions

View File

@ -268,7 +268,7 @@ public class APITestController {
if(allCount!=0){
float coverageRageNumber =(float)apiCountResult.getExecutionPassCount()*100/allCount;
DecimalFormat df = new DecimalFormat("0.0");
apiCountResult.setCoverageRage(df.format(coverageRageNumber)+"%");
apiCountResult.setPassRage(df.format(coverageRageNumber)+"%");
}
return apiCountResult;
@ -302,7 +302,7 @@ public class APITestController {
if(allCount!=0){
float coverageRageNumber =(float)apiCountResult.getSuccessCount()*100/allCount;
DecimalFormat df = new DecimalFormat("0.0");
apiCountResult.setCoverageRage(df.format(coverageRageNumber)+"%");
apiCountResult.setSuccessRage(df.format(coverageRageNumber)+"%");
}
return apiCountResult;
@ -354,6 +354,6 @@ public class APITestController {
public void updateScheduleEnableByPrimyKey(@RequestBody ScheduleInfoRequest request) {
Schedule schedule = scheduleService.getSchedule(request.getTaskID());
schedule.setEnable(request.isEnable());
apiTestService.updateSchedule(schedule);
apiAutomationService.updateSchedule(schedule);
}
}

View File

@ -44,21 +44,20 @@ public class ApiDefinitionController {
@PostMapping(value = "/create", consumes = {"multipart/form-data"})
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
public void create(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
checkPermissionService.checkReadOnlyUser();
checkPermissionService.checkProjectOwner(request.getProjectId());
apiDefinitionService.create(request, bodyFiles);
}
@PostMapping(value = "/update", consumes = {"multipart/form-data"})
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
public void update(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
checkPermissionService.checkReadOnlyUser();
checkPermissionService.checkProjectOwner(request.getProjectId());
apiDefinitionService.update(request, bodyFiles);
}
@GetMapping("/delete/{id}")
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER}, logical = Logical.OR)
public void delete(@PathVariable String id) {
checkPermissionService.checkReadOnlyUser();
apiDefinitionService.delete(id);
}

View File

@ -206,35 +206,17 @@ public class MsHTTPSamplerProxy extends MsTestElement {
this.getRest().stream().filter(KeyValue::isEnable).filter(KeyValue::isValid).forEach(keyValue ->
keyValueMap.put(keyValue.getName(), keyValue.getValue())
);
// 这块是否使用jmeter自身机制
Map<String, String> pubKeyValueMap = new HashMap<>();
if (config != null && config.getVariables() != null) {
config.getVariables().stream().forEach(keyValue -> {
pubKeyValueMap.put(keyValue.getName(), keyValue.getValue());
});
}
for (String key : keyValueMap.keySet()) {
if (keyValueMap.get(key) != null && keyValueMap.get(key).startsWith("$")) {
String pubKey = keyValueMap.get(key).substring(2, keyValueMap.get(key).length() - 1);
keyValueMap.put(key, pubKeyValueMap.get(pubKey));
}
}
Pattern p = Pattern.compile("(\\{)([\\w]+)(\\})");
Matcher m = p.matcher(path);
StringBuffer sb = new StringBuffer();
try {
Pattern p = Pattern.compile("(\\{)([\\w]+)(\\})");
Matcher m = p.matcher(path);
while (m.find()) {
String group = m.group(2);
//替换并且把替换好的值放到sb中
m.appendReplacement(sb, keyValueMap.get(group));
path = path.replace("{" + group + "}", keyValueMap.get(group));
}
} catch (Exception ex) {
ex.printStackTrace();
}
//把符合的数据追加到sb尾
m.appendTail(sb);
return sb.toString();
return path;
}
private String getPostQueryParameters(String path) {

View File

@ -1,6 +1,7 @@
package io.metersphere.api.jmeter;
import io.metersphere.api.service.*;
import io.metersphere.base.domain.ApiScenarioReport;
import io.metersphere.base.domain.ApiTestReport;
import io.metersphere.commons.constants.APITestStatus;
import io.metersphere.commons.constants.ApiRunMode;
@ -20,6 +21,7 @@ import org.apache.jmeter.protocol.http.sampler.HTTPSampleResult;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.visualizers.backend.AbstractBackendListenerClient;
import org.apache.jmeter.visualizers.backend.BackendListenerContext;
import org.python.antlr.ast.Str;
import org.springframework.http.HttpMethod;
import java.io.ByteArrayOutputStream;
@ -50,6 +52,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
private ApiScenarioReportService apiScenarioReportService;
public String runMode = ApiRunMode.RUN.name();
// 测试ID
@ -155,6 +158,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
testResult.getScenarios().addAll(scenarios.values());
testResult.getScenarios().sort(Comparator.comparing(ScenarioResult::getId));
ApiTestReport report = null;
String reportUrl = null;
// 这部分后续优化只留 DELIMIT SCENARIO 两部分
if (StringUtils.equals(this.runMode, ApiRunMode.DEBUG.name())) {
report = apiReportService.get(debugReportId);
@ -173,7 +177,31 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
} else if (StringUtils.equalsAny(this.runMode, ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name())) {
// 执行报告不需要存储由用户确认后在存储
testResult.setTestId(testId);
apiScenarioReportService.complete(testResult, this.runMode);
ApiScenarioReport scenarioReport = apiScenarioReportService.complete(testResult, this.runMode);
report = new ApiTestReport();
report.setStatus(scenarioReport.getStatus());
report.setId(scenarioReport.getId());
report.setTriggerMode(scenarioReport.getTriggerMode());
report.setName(scenarioReport.getName());
SystemParameterService systemParameterService = CommonBeanFactory.getBean(SystemParameterService.class);
assert systemParameterService != null;
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
reportUrl = baseSystemConfigDTO.getUrl() + "/#/api/automation/report";
String scenaName = scenarioReport.getName();
if(scenaName==null){
scenaName = "";
}else {
scenaName = scenaName.split("-")[0];
}
String scenarioID = apiScenarioReportService.getApiScenarioId(scenaName,scenarioReport.getProjectId());
testResult.setTestId(scenarioID);
} else {
apiTestService.changeStatus(testId, APITestStatus.Completed);
report = apiReportService.getRunningReport(testResult.getTestId());
@ -196,22 +224,24 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
}
}
try {
sendTask(report, testResult);
sendTask(report,reportUrl, testResult);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
}
}
private static void sendTask(ApiTestReport report, TestResult testResult) {
private static void sendTask(ApiTestReport report,String reportUrl, TestResult testResult) {
SystemParameterService systemParameterService = CommonBeanFactory.getBean(SystemParameterService.class);
NoticeSendService noticeSendService = CommonBeanFactory.getBean(NoticeSendService.class);
assert systemParameterService != null;
assert noticeSendService != null;
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
String url = baseSystemConfigDTO.getUrl() + "/#/api/report/view/" + report.getId();
String url = reportUrl;
if(StringUtils.isEmpty(url)){
url = baseSystemConfigDTO.getUrl() + "/#/api/report/view/" + report.getId();
}
String successContext = "";
String failedContext = "";
String subject = "";

View File

@ -30,9 +30,6 @@ import io.metersphere.service.ScheduleService;
import io.metersphere.track.dto.TestPlanDTO;
import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.request.testcase.TestPlanApiCaseBatchRequest;
import io.metersphere.track.service.TestPlanApiCaseService;
import io.metersphere.track.service.TestPlanScenarioCaseService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
@ -40,14 +37,13 @@ import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.collections.ListedHashTree;
import org.python.antlr.ast.Str;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
@Transactional(rollbackFor = Exception.class)
@ -160,7 +156,7 @@ public class ApiAutomationService {
apiScenarioMapper.deleteByPrimaryKey(id);
}
public void preDelete(String scenarioID){
public void preDelete(String scenarioID) {
scheduleService.deleteByResourceId(scenarioID);
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
@ -174,37 +170,40 @@ public class ApiAutomationService {
}
example = new TestPlanApiScenarioExample();
if(!idList.isEmpty()){
if (!idList.isEmpty()) {
example.createCriteria().andIdIn(idList);
testPlanApiScenarioMapper.deleteByExample(example);
}
}
public void preDelete(List<String> scenarioIDList){
public void preDelete(List<String> scenarioIDList) {
List<String> testPlanApiScenarioIdList = new ArrayList<>();
List<String> scheduleIdList = new ArrayList<>();
for (String id :scenarioIDList) {
for (String id : scenarioIDList) {
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
example.createCriteria().andApiScenarioIdEqualTo(id);
List<TestPlanApiScenario> testPlanApiScenarioList = testPlanApiScenarioMapper.selectByExample(example);
for (TestPlanApiScenario api :testPlanApiScenarioList) {
if(!testPlanApiScenarioIdList.contains(api.getId())){
for (TestPlanApiScenario api : testPlanApiScenarioList) {
if (!testPlanApiScenarioIdList.contains(api.getId())) {
testPlanApiScenarioIdList.add(api.getId());
}
}
scheduleService.deleteByResourceId(id);
}
if(!testPlanApiScenarioIdList.isEmpty()){
if (!testPlanApiScenarioIdList.isEmpty()) {
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
example.createCriteria().andIdIn(testPlanApiScenarioIdList);
testPlanApiScenarioMapper.deleteByExample(example);
}
}
public void deleteBatch(List<String> ids) {
//及连删除外键表
preDelete(ids);;
preDelete(ids);
;
ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andIdIn(ids);
apiScenarioMapper.deleteByExample(example);
@ -242,16 +241,16 @@ public class ApiAutomationService {
return new ArrayList<>();
}
private void createAPIScenarioReportResult(String id, String triggerMode, String execType, String projectId,String userID) {
private void createAPIScenarioReportResult(String id, String triggerMode, String execType, String projectId, String userID) {
APIScenarioReportResult report = new APIScenarioReportResult();
report.setId(id);
report.setName("测试执行结果");
report.setCreateTime(System.currentTimeMillis());
report.setUpdateTime(System.currentTimeMillis());
report.setStatus(APITestStatus.Running.name());
if(StringUtils.isNotEmpty(userID)){
if (StringUtils.isNotEmpty(userID)) {
report.setUserId(userID);
}else {
} else {
report.setUserId(SessionUtils.getUserId());
}
@ -316,7 +315,7 @@ public class ApiAutomationService {
jMeterService.runDefinition(request.getId(), jmeterTestPlanHashTree, request.getReportId(), runMode);
createAPIScenarioReportResult(request.getId(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
request.getExecuteType(), projectID,request.getReportUserID());
request.getExecuteType(), projectID, request.getReportUserID());
return request.getId();
}
@ -339,7 +338,6 @@ public class ApiAutomationService {
ParameterConfig config = new ParameterConfig();
config.setConfig(envConfig);
HashTree hashTree = request.getTestElement().generateHashTree(config);
request.getTestElement().getJmx(hashTree);
// 调用执行方法
jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), ApiRunMode.SCENARIO.name());
createAPIScenarioReportResult(request.getId(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(),
@ -367,8 +365,8 @@ public class ApiAutomationService {
ExtTestPlanScenarioCaseMapper scenarioBatchMapper = sqlSession.getMapper(ExtTestPlanScenarioCaseMapper.class);
ExtTestPlanApiCaseMapper apiCaseBatchMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class);
for (TestPlanDTO testPlan:list) {
if(request.getScenarioIds()!=null){
for (TestPlanDTO testPlan : list) {
if (request.getScenarioIds() != null) {
for (String scenarioId : request.getScenarioIds()) {
TestPlanApiScenario testPlanApiScenario = new TestPlanApiScenario();
testPlanApiScenario.setId(UUID.randomUUID().toString());
@ -379,7 +377,7 @@ public class ApiAutomationService {
scenarioBatchMapper.insertIfNotExists(testPlanApiScenario);
}
}
if(request.getApiIds()!=null){
if (request.getApiIds() != null) {
for (String caseId : request.getApiIds()) {
TestPlanApiCase testPlanApiCase = new TestPlanApiCase();
testPlanApiCase.setId(UUID.randomUUID().toString());

View File

@ -50,7 +50,18 @@ public class ApiScenarioReportService {
@Resource
private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
public void complete(TestResult result, String runMode) {
public String getApiScenarioId(String name, String projectID) {
ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andNameEqualTo(name).andProjectIdEqualTo(projectID).andStatusNotEqualTo("Trash");
List<ApiScenario> list = apiScenarioMapper.selectByExample(example);
if (list.isEmpty()) {
return null;
} else {
return list.get(0).getId();
}
}
public ApiScenarioReport complete(TestResult result, String runMode) {
Object obj = cache.get(result.getTestId());
if (obj == null) {
MSException.throwException(Translator.get("api_report_is_null"));
@ -83,6 +94,7 @@ public class ApiScenarioReportService {
if (!report.getTriggerMode().equals(ReportTriggerMode.SCHEDULE.name())) {
cache.put(report.getId(), report);
}
return report;
}
/**

View File

@ -50,12 +50,20 @@
) caseErrorCountData ON caseErrorCountData.testCaseID =testCase.testCaseID
WHERE caseErrorCountData.executeTime >= #{startTimestamp}
UNION
SELECT scene.`name` AS caseName,testPlan.`name` AS testPlan,count(report.id) AS failureTimes,'scenario' AS caseType
SELECT scene.`name` AS caseName,apiScene.testPlanName AS testPlan,count(report.id) AS failureTimes,'scenario' AS caseType
FROM api_scenario_report report
INNER JOIN api_scenario_report_detail reportDetail ON report.id = reportDetail.report_id
INNER JOIN api_scenario scene ON reportDetail.content like concat('%"',scene.`name`,'"%')
LEFT JOIN test_plan_api_scenario apiScene ON apiScene.api_scenario_id = scene.id
LEFT JOIN test_plan testPlan ON testPlan.id = apiScene.test_plan_id
INNER JOIN api_scenario scene ON reportDetail.content like concat('%"', scene.`name`,'"%')
LEFT JOIN
(
SELECT
apiScene.api_scenario_id,
group_concat(testPlan.`name`) AS testPlanName
FROM
test_plan_api_scenario apiScene
INNER JOIN test_plan testPlan ON testPlan.id = apiScene.test_plan_id
GROUP BY apiScene.api_scenario_id
)apiScene ON apiScene.api_scenario_id = scene.id
WHERE report.project_id = #{projectId}
AND report.status = 'Error' AND report.create_time >= #{startTimestamp}
GROUP BY scene.id

View File

@ -179,8 +179,8 @@
SELECT count(acr.report_id) AS countNumber FROM api_scenario_report_detail acr
INNER JOIN api_scenario_report ar ON ar.id = acr.report_id
INNER JOIN (
SELECT acitem.id FROM api_scenario acitem INNER JOIN `schedule` sc ON acitem.id = sc.resource_id
) ac on acr.content like CONCAT('%', ac.id,'%')
SELECT acitem.`name` FROM api_scenario acitem INNER JOIN `schedule` sc ON acitem.id = sc.resource_id
) ac on acr.content like CONCAT('%"', ac.`name`,'"%')
WHERE acr.project_id = #{projectId} AND ar.create_time BETWEEN #{firstDayTimestamp} AND #{lastDayTimestamp}
</select>
@ -189,8 +189,8 @@
FROM api_scenario_report_detail acr
INNER JOIN api_scenario_report ar ON ar.id = acr.report_id
INNER JOIN (
SELECT acitem.id FROM api_scenario acitem INNER JOIN `schedule` sc ON acitem.id = sc.resource_id
) ac on acr.content like CONCAT('%', ac.id,'%')
SELECT acitem.`name` FROM api_scenario acitem INNER JOIN `schedule` sc ON acitem.id = sc.resource_id
) ac on acr.content like CONCAT('%"', ac.`name`,'"%')
WHERE acr.project_id = #{projectId}
</select>
</mapper>

View File

@ -160,7 +160,6 @@
WHERE sch.resource_id IN (
SELECT id FROM api_test WHERE project_id = #{projectId,jdbcType=VARCHAR}
)
AND `group` = #{group}
</select>
<select id="countByProjectIDAndCreateInThisWeek" resultType="java.lang.Long">

View File

@ -231,6 +231,7 @@
<select id="selectTestPlanByRelevancy" resultMap="BaseResultMap" parameterType="io.metersphere.track.request.testcase.QueryTestPlanRequest">
SELECT * FROM TEST_PLAN p LEFT JOIN test_plan_project t ON t.test_plan_id=p.id
<where>
AND t.project_id = #{request.projectId}
<if test="request.scenarioId != null">
AND p.id IN (SELECT test_plan_id FROM test_plan_api_scenario WHERE api_scenario_id = #{request.scenarioId} )
</if>

View File

@ -75,7 +75,7 @@ public class PerformanceTestController {
@RequestPart("request") SaveTestPlanRequest request,
@RequestPart(value = "file") List<MultipartFile> files
) {
checkPermissionService.checkReadOnlyUser();
checkPermissionService.checkProjectOwner(request.getProjectId());
return performanceTestService.save(request, files);
}
@ -84,7 +84,6 @@ public class PerformanceTestController {
@RequestPart("request") EditTestPlanRequest request,
@RequestPart(value = "file", required = false) List<MultipartFile> files
) {
checkPermissionService.checkReadOnlyUser();
checkPermissionService.checkPerformanceTestOwner(request.getId());
return performanceTestService.edit(request, files);
}
@ -115,7 +114,6 @@ public class PerformanceTestController {
@PostMapping("/delete")
public void delete(@RequestBody DeleteTestPlanRequest request) {
checkPermissionService.checkReadOnlyUser();
checkPermissionService.checkPerformanceTestOwner(request.getId());
performanceTestService.delete(request);
}

View File

@ -212,6 +212,8 @@ public class SystemParameterService {
public void saveBaseInfo(List<SystemParameter> parameters) {
SystemParameterExample example = new SystemParameterExample();
parameters.forEach(param -> {
// 去掉路径最后的 /
param.setParamValue(StringUtils.removeEnd(param.getParamValue(), "/"));
example.createCriteria().andParamKeyEqualTo(param.getParamKey());
if (systemParameterMapper.countByExample(example) > 0) {
systemParameterMapper.updateByPrimaryKey(param);

@ -1 +1 @@
Subproject commit 9f4a9bbf46fc1333dbcccea21f83e27e3ec10b1f
Subproject commit 79343a2763b014355f91fc21b2356a95ae437973

View File

@ -48,7 +48,6 @@
<ms-code-edit :read-only="isReadOnly" :data.sync="body.raw" :modes="modes" :mode="'xml'" ref="codeEdit"/>
</div>
<div class="ms-body" v-if="body.type == 'Raw'">
<ms-code-edit :read-only="isReadOnly" :data.sync="body.raw" :modes="modes" ref="codeEdit"/>
</div>
@ -69,7 +68,6 @@
import {BODY_TYPE, KeyValue} from "../../model/ApiTestModel";
import MsCodeEdit from "../../../../common/components/MsCodeEdit";
import MsJsonCodeEdit from "../../../../common/components/MsJsonCodeEdit";
import MsDropdown from "../../../../common/components/MsDropdown";
import MsApiVariable from "../ApiVariable";
import MsApiBinaryVariable from "./ApiBinaryVariable";