fix(接口定义) 修复并发批量执行用例问题

This commit is contained in:
fit2-zhao 2021-09-24 18:59:56 +08:00 committed by fit2-zhao
parent ec092e4038
commit 6fd1ffdda7
8 changed files with 108 additions and 21 deletions

View File

@ -47,7 +47,7 @@ public class MsDNSCacheManager extends MsTestElement {
}
public static void addEnvironmentDNS(HashTree samplerHashTree, String name, EnvironmentConfig config, HttpConfig httpConfig) {
if (config.getCommonConfig().isEnableHost() && CollectionUtils.isNotEmpty(config.getCommonConfig().getHosts()) && httpConfig != null) {
if (config.getCommonConfig().isEnableHost() && CollectionUtils.isNotEmpty(config.getCommonConfig().getHosts()) && httpConfig != null && httpConfig.getDomain() != null) {
String domain = httpConfig.getDomain().trim();
List<Host> hosts = new ArrayList<>();
config.getCommonConfig().getHosts().forEach(host -> {

View File

@ -1,5 +1,6 @@
package io.metersphere.api.jmeter;
import io.metersphere.base.domain.ApiDefinitionExecResult;
import org.apache.jmeter.engine.StandardJMeterEngine;
import javax.websocket.Session;
@ -16,4 +17,7 @@ public class MessageCache {
public static ConcurrentHashMap<String, StandardJMeterEngine> runningEngine = new ConcurrentHashMap<>();
public static ConcurrentLinkedDeque<String> terminationOrderDeque = new ConcurrentLinkedDeque<>();
public static ConcurrentHashMap<String, ApiDefinitionExecResult> batchTestCases = new ConcurrentHashMap<>();
}

View File

@ -1966,7 +1966,7 @@ public class ApiAutomationService {
}
}
}
if (CollectionUtils.isNotEmpty(object.getJSONArray("hashTree"))) {
if (object != null && CollectionUtils.isNotEmpty(object.getJSONArray("hashTree"))) {
setHashTree(object.getJSONArray("hashTree"));
}
}
@ -1985,8 +1985,10 @@ public class ApiAutomationService {
if (StringUtils.isNotEmpty(item.getScenarioDefinition())) {
JSONObject scenario = JSONObject.parseObject(item.getScenarioDefinition());
JSONArray hashTree = scenario.getJSONArray("hashTree");
setHashTree(hashTree);
scenario.put("hashTree", hashTree);
if (hashTree != null) {
setHashTree(hashTree);
scenario.put("hashTree", hashTree);
}
item.setScenarioDefinition(JSON.toJSONString(scenario));
}
});

View File

@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.cache.TestPlanReportExecuteCatch;
import io.metersphere.api.dto.datacount.ExecutedCaseInfoResult;
import io.metersphere.api.jmeter.MessageCache;
import io.metersphere.api.jmeter.TestResult;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
@ -57,7 +58,8 @@ public class ApiDefinitionExecResultService {
TestCaseReviewApiCaseMapper testCaseReviewApiCaseMapper;
@Resource
SqlSessionFactory sqlSessionFactory;
private ApiDefinitionService apiDefinitionService;
@Resource
private NoticeSendService noticeSendService;
@ -67,13 +69,14 @@ public class ApiDefinitionExecResultService {
public void saveApiResult(TestResult result, String type, String triggerMode) {
if (CollectionUtils.isNotEmpty(result.getScenarios())) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiDefinitionExecResultMapper definitionExecResultMapper = sqlSession.getMapper(ApiDefinitionExecResultMapper.class);
final boolean[] isFirst = {true};
result.getScenarios().forEach(scenarioResult -> {
if (scenarioResult != null && CollectionUtils.isNotEmpty(scenarioResult.getRequestResults())) {
scenarioResult.getRequestResults().forEach(item -> {
ApiDefinitionExecResult saveResult = definitionExecResultMapper.selectByPrimaryKey(result.getTestId());
ApiDefinitionExecResult saveResult = MessageCache.batchTestCases.get(result.getTestId());
if (saveResult == null) {
saveResult = apiDefinitionExecResultMapper.selectByPrimaryKey(result.getTestId());
}
item.getResponseResult().setConsole(result.getConsole());
boolean saved = true;
if (saveResult == null || scenarioResult.getRequestResults().size() > 1) {
@ -88,6 +91,7 @@ public class ApiDefinitionExecResultService {
saveResult.setName(item.getName());
saveResult.setTriggerMode(triggerMode);
saveResult.setType(type);
saveResult.setCreateTime(item.getStartTime());
if (StringUtils.isNotEmpty(result.getUserId())) {
saveResult.setUserId(result.getUserId());
} else {
@ -98,7 +102,6 @@ public class ApiDefinitionExecResultService {
String status = item.isSuccess() ? "success" : "error";
saveResult.setName(getName(type, item.getName(), status, saveResult.getCreateTime(), saveResult.getId()));
saveResult.setStatus(status);
saveResult.setCreateTime(item.getStartTime());
saveResult.setResourceId(item.getName());
saveResult.setContent(JSON.toJSONString(item));
saveResult.setStartTime(item.getStartTime());
@ -108,23 +111,23 @@ public class ApiDefinitionExecResultService {
ApiDefinitionExecResult prevResult = extApiDefinitionExecResultMapper.selectMaxResultByResourceIdAndType(item.getName(), type);
if (prevResult != null) {
prevResult.setContent(null);
definitionExecResultMapper.updateByPrimaryKeyWithBLOBs(prevResult);
apiDefinitionExecResultMapper.updateByPrimaryKeyWithBLOBs(prevResult);
}
if (StringUtils.isNotEmpty(saveResult.getTriggerMode()) && saveResult.getTriggerMode().equals("CASE")) {
saveResult.setTriggerMode(TriggerMode.MANUAL.name());
}
if (!saved) {
definitionExecResultMapper.insert(saveResult);
apiDefinitionExecResultMapper.insert(saveResult);
} else {
definitionExecResultMapper.updateByPrimaryKeyWithBLOBs(saveResult);
apiDefinitionExecResultMapper.updateByPrimaryKeyWithBLOBs(saveResult);
}
apiDefinitionService.removeCache(result.getTestId());
// 发送通知
sendNotice(saveResult);
});
}
});
sqlSession.flushStatements();
}
}
@ -284,7 +287,7 @@ public class ApiDefinitionExecResultService {
if (StringUtils.equals(type, ApiRunMode.SCHEDULE_API_PLAN.name())) {
TestPlanApiCase apiCase = testPlanApiCaseService.getById(item.getName());
if(StringUtils.isEmpty(creator)){
if (StringUtils.isEmpty(creator)) {
creator = testPlanService.findScheduleCreateUserById(apiCase.getTestPlanId());
}
apiCase.setStatus(status);
@ -299,7 +302,7 @@ public class ApiDefinitionExecResultService {
testPlanApiCaseService.setExecResult(item.getName(), status, item.getStartTime());
testCaseReviewApiCaseService.setExecResult(item.getName(), status, item.getStartTime());
}
if(creator == null){
if (creator == null) {
creator = "";
}
saveResult.setUserId(creator);

View File

@ -97,8 +97,6 @@ public class ApiDefinitionService {
@Resource
private ExtSwaggerUrlScheduleMapper extSwaggerUrlScheduleMapper;
@Resource
private ScheduleMapper scheduleMapper;
@Resource
private ApiTestCaseMapper apiTestCaseMapper;
@Resource
private ApiTestEnvironmentService environmentService;
@ -117,7 +115,7 @@ public class ApiDefinitionService {
@Resource
private ExtApiTestCaseMapper extApiTestCaseMapper;
private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24);
private static Cache cache = Cache.newHardMemoryCache(0, 3600);
private ThreadLocal<Long> currentApiOrder = new ThreadLocal<>();
private ThreadLocal<Long> currentApiCaseOrder = new ThreadLocal<>();
@ -800,6 +798,12 @@ public class ApiDefinitionService {
return null;
}
public void removeCache(String testId) {
if (StringUtils.isNotEmpty(testId)) {
cache.remove(testId);
}
}
/**
* 获取存储执行结果报告
*

View File

@ -18,6 +18,7 @@ import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.jmeter.MessageCache;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.*;
@ -494,7 +495,7 @@ public class ApiTestCaseService {
ExtTestPlanApiCaseMapper batchMapper = sqlSession.getMapper(ExtTestPlanApiCaseMapper.class);
Long nextOrder = ServiceUtils.getNextOrder(request.getPlanId(), extTestPlanApiCaseMapper::getLastOrder);
for (ApiTestCase apiTestCase: apiTestCases) {
for (ApiTestCase apiTestCase : apiTestCases) {
TestPlanApiCase testPlanApiCase = new TestPlanApiCase();
testPlanApiCase.setId(UUID.randomUUID().toString());
testPlanApiCase.setCreateUser(SessionUtils.getUserId());
@ -701,7 +702,7 @@ public class ApiTestCaseService {
public void batchRun(ApiCaseBatchRequest request) {
ServiceUtils.getSelectAllIds(request, request.getCondition(),
(query) -> extApiTestCaseMapper.selectIdsByQuery((ApiTestCaseRequest)query));
(query) -> extApiTestCaseMapper.selectIdsByQuery((ApiTestCaseRequest) query));
Map<String, ApiDefinitionExecResult> executeQueue = new HashMap<>();
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiDefinitionExecResultMapper batchMapper = sqlSession.getMapper(ApiDefinitionExecResultMapper.class);
@ -727,6 +728,7 @@ public class ApiTestCaseService {
runCaseRequest.setReportId(executeQueue.get(caseId).getId());
runCaseRequest.setEnvironmentId(request.getEnvironmentId());
run(runCaseRequest);
MessageCache.batchTestCases.put(executeQueue.get(caseId).getId(), executeQueue.get(caseId));
}
}
@ -1089,6 +1091,7 @@ public class ApiTestCaseService {
/**
* 用例自定义排序
*
* @param request
*/
public void updateOrder(ResetOrderRequest request) {

View File

@ -212,7 +212,7 @@ export default {
mockSetting() {
let mockParam = {};
mockParam.projectId = this.projectId;
if(this.currentApi.id){
if (this.currentApi.id) {
mockParam.apiId = this.currentApi.id;
this.$post('/mockConfig/genMockConfig', mockParam, response => {
let mockConfig = response.data;
@ -283,6 +283,7 @@ export default {
this.api = this.$store.state.currentApiCase.api;
this.$refs.caseList.open();
}
this.$store.state.currentApiCase = {case: true};
} else if (tabType === "test") {
this.showApiList = false;
this.showTestCaseList = false;

View File

@ -230,6 +230,7 @@ import {
getCustomTableHeader,
getCustomTableWidth,
getLastTableSortField,
handleRowDrop
} from "@/common/js/tableUtils";
import {API_CASE_LIST} from "@/common/js/constants";
import HeaderLabelOperate from "@/business/components/common/head/HeaderLabelOperate";
@ -361,6 +362,7 @@ export default {
environments: [],
resVisible: false,
response: {},
timeoutIndex: 0,
};
},
props: {
@ -526,6 +528,7 @@ export default {
this.$refs.caseTable.openCustomHeader();
},
initTable(id) {
this.timeoutIndex = 0;
if (this.$refs.caseTable) {
this.$refs.caseTable.clearSelectRows();
}
@ -603,6 +606,73 @@ export default {
isNext = true;
}
});
this.$nextTick(() => {
if (this.$refs.caseTable) {
this.$refs.caseTable.clear();
}
handleRowDrop(this.tableData, (param) => {
param.groupId = this.condition.projectId;
editApiTestCaseOrder(param);
});
})
if (isNext) {
this.refreshStatus();
}
});
}
},
refreshStatus() {
if (this.apiDefinitionId) {
this.condition.apiDefinitionId = this.apiDefinitionId;
}
this.condition.status = "";
this.condition.moduleIds = this.selectNodeIds;
if (this.condition.filters && !this.condition.filters.status) {
this.$delete(this.condition.filters, 'status');
}
if (!this.selectAll) {
this.selectAll = false;
this.unSelection = [];
this.selectDataCounts = 0;
}
this.condition.projectId = this.projectId;
if (this.currentProtocol != null) {
this.condition.protocol = this.currentProtocol;
}
//
this.isSelectThissWeekData();
this.condition.selectThisWeedData = false;
this.condition.id = null;
if (this.selectDataRange == 'thisWeekCount') {
this.condition.selectThisWeedData = true;
} else if (this.selectDataRange != null) {
let selectParamArr = this.selectDataRange.split("single:");
if (selectParamArr.length === 2) {
this.condition.id = selectParamArr[1];
}
}
if (this.condition.projectId) {
this.result = this.$post('/api/testcase/list/' + this.currentPage + "/" + this.pageSize, this.condition, response => {
let isNext = false;
let tableData = response.data.listObject;
this.tableData.forEach(item => {
for (let i in tableData) {
if (item.id === tableData[i].id) {
item.status = tableData[i].status;
item.lastResultId = tableData[i].lastResultId;
}
}
if (item.status === 'Running') {
isNext = true;
}
});
if (isNext && this.$store.state.currentApiCase && this.$store.state.currentApiCase.case && this.timeoutIndex < 12) {
this.timeoutIndex++;
setTimeout(() => {
this.refreshStatus();
}, 12000);
}
});
}
},