fix(接口自动化): 部分缺陷修复
This commit is contained in:
parent
4318d56a83
commit
14810d24f7
|
@ -206,6 +206,7 @@ public abstract class MsTestElement {
|
|||
}
|
||||
csvDataSet.setIgnoreFirstLine(false);
|
||||
csvDataSet.setRecycle(true);
|
||||
csvDataSet.setProperty("shareMode","shareMode.thread");
|
||||
csvDataSet.setProperty("recycle", true);
|
||||
csvDataSet.setProperty("delimiter", item.getDelimiter());
|
||||
csvDataSet.setComment(StringUtils.isEmpty(item.getDescription()) ? "" : item.getDescription());
|
||||
|
|
|
@ -111,8 +111,16 @@ public class MsJDBCSampler extends MsTestElement {
|
|||
this.dataSource = config.getConfig().get(this.getProjectId()).getDatabaseConfigs().get(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.dataSource == null) {
|
||||
MSException.throwException("数据源为空无法执行");
|
||||
// 用自身的数据
|
||||
if (StringUtils.isNotEmpty(dataSourceId)) {
|
||||
this.dataSource = null;
|
||||
this.initDataSource();
|
||||
}
|
||||
if (this.dataSource == null) {
|
||||
MSException.throwException("数据源为空无法执行");
|
||||
}
|
||||
}
|
||||
final HashTree samplerHashTree = tree.add(jdbcSampler(config));
|
||||
tree.add(jdbcDataSource());
|
||||
|
|
|
@ -21,6 +21,7 @@ import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
|
|||
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.api.parse.ApiImportParser;
|
||||
import io.metersphere.api.service.task.ParallelExecTask;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.*;
|
||||
|
@ -57,6 +58,8 @@ import java.io.ByteArrayOutputStream;
|
|||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
|
@ -743,6 +746,8 @@ public class ApiAutomationService {
|
|||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
ApiScenarioReportMapper batchMapper = sqlSession.getMapper(ApiScenarioReportMapper.class);
|
||||
String reportId = request.getId();
|
||||
|
||||
Map<String, HashTree> map = new LinkedHashMap<>();
|
||||
// 按照场景执行
|
||||
for (ApiScenarioWithBLOBs item : apiScenarios) {
|
||||
if (item.getStepTotal() == null || item.getStepTotal() == 0) {
|
||||
|
@ -780,11 +785,18 @@ public class ApiAutomationService {
|
|||
batchMapper.insert(report);
|
||||
|
||||
// 调用执行方法
|
||||
jMeterService.runDefinition(report.getId(), hashTree, request.getReportId(), request.getRunMode());
|
||||
// jMeterService.runDefinition(report.getId(), hashTree, request.getReportId(), request.getRunMode());
|
||||
map.put(report.getId(), hashTree);
|
||||
// 重置报告ID
|
||||
reportId = UUID.randomUUID().toString();
|
||||
}
|
||||
sqlSession.flushStatements();
|
||||
// 开始执行
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(map.size());
|
||||
for (String key : map.keySet()) {
|
||||
executorService.submit(new ParallelExecTask(jMeterService, key, map.get(key), request));
|
||||
}
|
||||
|
||||
return request.getId();
|
||||
}
|
||||
|
||||
|
@ -884,7 +896,7 @@ public class ApiAutomationService {
|
|||
// 生成集成报告
|
||||
if (request.getConfig() != null && request.getConfig().getMode().equals("serial") && StringUtils.isNotEmpty(request.getConfig().getReportName())) {
|
||||
request.getConfig().setReportId(UUID.randomUUID().toString());
|
||||
APIScenarioReportResult report = createScenarioReport(request.getConfig().getReportId(), JSON.toJSONString(reportList), request.getConfig().getReportName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
|
||||
APIScenarioReportResult report = createScenarioReport(request.getConfig().getReportId(), JSON.toJSONString(reportList), request.getConfig().getReportName(), ReportTriggerMode.MANUAL.name(),
|
||||
ExecuteType.Saved.name(), request.getProjectId(), request.getReportUserID(), request.getConfig());
|
||||
batchMapper.insert(report);
|
||||
}
|
||||
|
|
|
@ -361,7 +361,6 @@ public class ApiScenarioReportService {
|
|||
} else {
|
||||
report.setUserId(SessionUtils.getUserId());
|
||||
}
|
||||
report.setTriggerMode(runMode);
|
||||
report.setExecuteType(ExecuteType.Saved.name());
|
||||
report.setProjectId(projectId);
|
||||
report.setScenarioName(scenarioNames.toString().substring(0, scenarioNames.toString().length() - 1));
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
*/
|
||||
package io.metersphere.api.service.task;
|
||||
|
||||
import io.metersphere.api.dto.automation.RunScenarioRequest;
|
||||
import io.metersphere.api.jmeter.JMeterService;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import org.apache.jorphan.collections.HashTree;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class ParallelExecTask<T> implements Callable<T> {
|
||||
private RunScenarioRequest request;
|
||||
private JMeterService jMeterService;
|
||||
private HashTree hashTree;
|
||||
private String id;
|
||||
|
||||
public ParallelExecTask(JMeterService jMeterService, String id, HashTree hashTree, RunScenarioRequest request) {
|
||||
this.jMeterService = jMeterService;
|
||||
this.request = request;
|
||||
this.hashTree = hashTree;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T call() {
|
||||
try {
|
||||
jMeterService.runDefinition(id, hashTree, request.getReportId(), request.getRunMode());
|
||||
return null;
|
||||
} catch (Exception ex) {
|
||||
LogUtil.error(ex.getMessage());
|
||||
MSException.throwException(ex.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -84,6 +84,8 @@ public class JSONSchemaGenerator {
|
|||
JsonObject propertyObj = propertiesObj.get(propertyKey).getAsJsonObject();
|
||||
analyzeProperty(rootObj, propertyKey, propertyObj);
|
||||
}
|
||||
} else if (object.has("type") && object.get("type").getAsString().equals("array")) {
|
||||
analyzeProperty(rootObj, "MS-OBJECT", object);
|
||||
} else if (object.has("type") && !object.get("type").getAsString().equals("object")) {
|
||||
analyzeProperty(rootObj, object.getAsString(), object);
|
||||
}
|
||||
|
@ -298,6 +300,9 @@ public class JSONSchemaGenerator {
|
|||
generator(jsonSchema, root);
|
||||
// 格式化返回
|
||||
Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();
|
||||
if (root.get("MS-OBJECT") != null) {
|
||||
return gson.toJson(root.get("MS-OBJECT"));
|
||||
}
|
||||
return gson.toJson(root);
|
||||
} else {
|
||||
return report.getExceptionThreshold().toString();
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
:request="request"
|
||||
:showScript="false"/>
|
||||
<ms-sql-basis-parameters v-if="request.protocol==='SQL'|| request.type==='JDBCSampler'"
|
||||
:request="request" :is-scenario="true" :environment="environment"
|
||||
:request="request" :is-scenario="false" :environment="environment"
|
||||
:showScript="false"/>
|
||||
<ms-dubbo-basis-parameters v-if="request.protocol==='DUBBO' || request.protocol==='dubbo://'|| request.type==='DubboSampler'"
|
||||
:request="request"
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
const isBoolean = require("lodash.isboolean")
|
||||
const isEmpty = require("lodash.isempty")
|
||||
const isInteger = require("lodash.isinteger")
|
||||
const isNull = require("lodash.isnull")
|
||||
const isNumber = require("lodash.isnumber")
|
||||
const isObject = require("lodash.isobject")
|
||||
const isString = require("lodash.isstring")
|
||||
const isArray = Array.isArray
|
||||
const isBoolean = require("lodash.isboolean");
|
||||
const isEmpty = require("lodash.isempty");
|
||||
const isInteger = require("lodash.isinteger");
|
||||
const isNull = require("lodash.isnull");
|
||||
const isNumber = require("lodash.isnumber");
|
||||
const isObject = require("lodash.isobject");
|
||||
const isString = require("lodash.isstring");
|
||||
const isArray = Array.isArray;
|
||||
|
||||
|
||||
class Convert {
|
||||
|
@ -14,7 +14,7 @@ class Convert {
|
|||
$id: "http://example.com/root.json",
|
||||
$schema: "http://json-schema.org/draft-07/schema#",
|
||||
}
|
||||
this._object = null
|
||||
this._object = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,22 +25,22 @@ class Convert {
|
|||
format(object, option = {}) {
|
||||
// 数据校验,确保传入的的object只能是对象或数组
|
||||
if (!isObject(object)) {
|
||||
throw new TypeError("传入参数只能是对象或数组")
|
||||
throw new TypeError("传入参数只能是对象或数组");
|
||||
}
|
||||
// 合并属性
|
||||
this._option = Object.assign(this._option, option)
|
||||
this._option = Object.assign(this._option, option);
|
||||
// 需要转换的对象
|
||||
this._object = object
|
||||
let convertRes
|
||||
this._object = object;
|
||||
let convertRes;
|
||||
// 数组类型和对象类型结构不一样
|
||||
if (isArray(object)) {
|
||||
convertRes = this._arrayToSchema()
|
||||
convertRes = this._arrayToSchema();
|
||||
} else {
|
||||
convertRes = this._objectToSchema()
|
||||
convertRes = this._objectToSchema();
|
||||
}
|
||||
// 释放
|
||||
this._object = null
|
||||
return convertRes
|
||||
this._object = null;
|
||||
return convertRes;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,16 +48,16 @@ class Convert {
|
|||
*/
|
||||
_arrayToSchema() {
|
||||
// root节点基本信息
|
||||
let result = this._value2object(this._object, this._option.$id, "", true)
|
||||
let result = this._value2object(this._object, this._option.$id, "", true);
|
||||
if (this._object.length > 0) {
|
||||
// 创建items对象的基本信息
|
||||
let objectItem = this._object[0]
|
||||
result["items"] = this._value2object(objectItem, `#/items`, 'items')
|
||||
result["items"] = this._value2object(objectItem, `#/items`, 'items');
|
||||
if (isObject(objectItem) && !isEmpty(objectItem)) {
|
||||
// 递归遍历
|
||||
let objectItemSchema = this._json2schema(objectItem, `#/items`)
|
||||
let objectItemSchema = this._json2schema(objectItem, `#/items`);
|
||||
// 合并对象
|
||||
result["items"] = Object.assign(result["items"], objectItemSchema)
|
||||
result["items"] = Object.assign(result["items"], objectItemSchema);
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
@ -90,9 +90,9 @@ class Convert {
|
|||
let result = {};
|
||||
// 判断传入object是对象还是数组。
|
||||
if (isArray(object)) {
|
||||
result.items = {}
|
||||
result.items = {};
|
||||
} else {
|
||||
result.properties = {}
|
||||
result.properties = {};
|
||||
}
|
||||
// 遍历传入的对象
|
||||
for (const key in object) {
|
||||
|
@ -100,7 +100,7 @@ class Convert {
|
|||
const element = object[key];
|
||||
// 如果只是undefined。跳过
|
||||
if (element === undefined) {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
let $id = `${name}/properties/${key}`
|
||||
// 判断当前 element 的值 是否也是对象,如果是就继续递归,不是就赋值给result
|
||||
|
@ -111,22 +111,22 @@ class Convert {
|
|||
// 针对空数组和有值的数组做不同处理
|
||||
if (element.length > 0) {
|
||||
// 如果是数组,那么就取第一项
|
||||
let elementItem = element[0]
|
||||
let elementItem = element[0];
|
||||
// 创建items对象的基本信息
|
||||
result["properties"][key]["items"] = this._value2object(elementItem, `${$id}/items`, key + 'items')
|
||||
result["properties"][key]["items"] = this._value2object(elementItem, `${$id}/items`, key + 'items');
|
||||
// 判断第一项是否是对象,且对象属性不为空
|
||||
if (isObject(elementItem) && !isEmpty(elementItem)) {
|
||||
// 新增的properties才合并进来
|
||||
result["properties"][key]["items"] = Object.assign(result["properties"][key]["items"], this._json2schema(elementItem, `${$id}/items`))
|
||||
result["properties"][key]["items"] = Object.assign(result["properties"][key]["items"], this._json2schema(elementItem, `${$id}/items`));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 不是数组,递归遍历获取,然后合并对象属性
|
||||
result["properties"][key] = Object.assign(result["properties"][key], this._json2schema(element, $id))
|
||||
result["properties"][key] = Object.assign(result["properties"][key], this._json2schema(element, $id));
|
||||
}
|
||||
} else {
|
||||
// 一般属性直接获取基本信息
|
||||
result["properties"][key] = this._value2object(element, $id, key)
|
||||
result["properties"][key] = this._value2object(element, $id, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,29 +150,31 @@ class Convert {
|
|||
|
||||
// 判断是否为初始化root数据
|
||||
if (root) {
|
||||
objectTemplate["$schema"] = this._option.$schema
|
||||
objectTemplate["title"] = `The Root Schema`
|
||||
objectTemplate["mock"] = undefined
|
||||
objectTemplate["$schema"] = this._option.$schema;
|
||||
objectTemplate["title"] = `The Root Schema`;
|
||||
objectTemplate["mock"] = undefined;
|
||||
}
|
||||
|
||||
if (isInteger(value)) {
|
||||
objectTemplate.type = "integer"
|
||||
objectTemplate.type = "integer";
|
||||
} else if (isNumber(value)) {
|
||||
objectTemplate.type = "number"
|
||||
objectTemplate.type = "number";
|
||||
} else if (isString(value)) {
|
||||
objectTemplate.type = "string"
|
||||
objectTemplate.type = "string";
|
||||
} else if (isBoolean(value)) {
|
||||
objectTemplate.type = "boolean"
|
||||
objectTemplate.type = "boolean";
|
||||
} else if (isNull(value)) {
|
||||
objectTemplate.type = "null"
|
||||
objectTemplate.type = "null";
|
||||
} else if (isArray(value)) {
|
||||
objectTemplate.type = "array"
|
||||
objectTemplate.type = "array";
|
||||
objectTemplate["mock"] = undefined;
|
||||
} else if (isObject(value)) {
|
||||
objectTemplate.type = "object"
|
||||
objectTemplate["mock"] = undefined;
|
||||
}
|
||||
|
||||
return objectTemplate
|
||||
return objectTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Convert
|
||||
module.exports = Convert;
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e50f0463826ac4d7837ea3a237333827774a1b19
|
||||
Subproject commit e7709b9a340394e78610b91105b2cec0f1b8289d
|
Loading…
Reference in New Issue