This commit is contained in:
chenjianxing 2020-12-24 18:21:59 +08:00
commit 0e876bdc22
16 changed files with 145 additions and 204 deletions

View File

@ -7,7 +7,6 @@ import io.metersphere.api.dto.QueryAPIReportRequest;
import io.metersphere.api.dto.automation.APIScenarioReportResult; import io.metersphere.api.dto.automation.APIScenarioReportResult;
import io.metersphere.api.dto.automation.ExecuteType; import io.metersphere.api.dto.automation.ExecuteType;
import io.metersphere.api.service.ApiScenarioReportService; import io.metersphere.api.service.ApiScenarioReportService;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.Pager;
@ -27,12 +26,9 @@ public class APIScenarioReportController {
@Resource @Resource
private ApiScenarioReportService apiReportService; private ApiScenarioReportService apiReportService;
@GetMapping("/get/{reportId}/{infoDb}") @GetMapping("/get/{reportId}")
public APIScenarioReportResult get(@PathVariable String reportId, @PathVariable Boolean infoDb) { public APIScenarioReportResult get(@PathVariable String reportId) {
if (infoDb) { return apiReportService.get(reportId);
return apiReportService.get(reportId);
}
return apiReportService.getCacheResult(reportId);
} }
@PostMapping("/list/{goPage}/{pageSize}") @PostMapping("/list/{goPage}/{pageSize}")
@ -42,13 +38,6 @@ public class APIScenarioReportController {
return PageUtils.setPageInfo(page, apiReportService.list(request)); return PageUtils.setPageInfo(page, apiReportService.list(request));
} }
@PostMapping("/add")
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public void add(@RequestBody APIScenarioReportResult node) {
node.setExecuteType(ExecuteType.Saved.name());
apiReportService.save(node, ApiRunMode.SCENARIO.name());
}
@PostMapping("/update") @PostMapping("/update")
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
public String update(@RequestBody APIScenarioReportResult node) { public String update(@RequestBody APIScenarioReportResult node) {

View File

@ -81,7 +81,7 @@ public class ApiAutomationController {
@PostMapping(value = "/run/debug") @PostMapping(value = "/run/debug")
public void runDebug(@RequestPart("request") RunDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) { public void runDebug(@RequestPart("request") RunDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
request.setExecuteType(ExecuteType.Debug.name()); request.setExecuteType(ExecuteType.Debug.name());
apiAutomationService.run(request, bodyFiles); apiAutomationService.debugRun(request, bodyFiles);
} }
@PostMapping(value = "/run") @PostMapping(value = "/run")
@ -90,6 +90,13 @@ public class ApiAutomationController {
apiAutomationService.run(request); apiAutomationService.run(request);
} }
@PostMapping(value = "/run/batch")
public void runBatch(@RequestBody RunScenarioRequest request) {
request.setExecuteType(ExecuteType.Saved.name());
apiAutomationService.run(request);
}
@PostMapping("/getReference") @PostMapping("/getReference")
public ReferenceDTO getReference(@RequestBody ApiScenarioRequest request) { public ReferenceDTO getReference(@RequestBody ApiScenarioRequest request) {
return apiAutomationService.getReference(request); return apiAutomationService.getReference(request);

View File

@ -21,6 +21,10 @@ public class RunDefinitionRequest {
private String projectId; private String projectId;
private String scenarioId;
private String scenarioName;
private String environmentId; private String environmentId;
private MsTestElement testElement; private MsTestElement testElement;

View File

@ -84,7 +84,7 @@ public class MsScenario extends MsTestElement {
} }
// 场景变量 // 场景变量
if (CollectionUtils.isNotEmpty(this.getVariables())) { if (CollectionUtils.isNotEmpty(this.getVariables())) {
tree.add(arguments()); tree.add(arguments(config));
} }
if (CollectionUtils.isNotEmpty(hashTree)) { if (CollectionUtils.isNotEmpty(hashTree)) {
@ -95,7 +95,7 @@ public class MsScenario extends MsTestElement {
} }
private Arguments arguments() { private Arguments arguments(ParameterConfig config) {
Arguments arguments = new Arguments(); Arguments arguments = new Arguments();
arguments.setEnabled(true); arguments.setEnabled(true);
arguments.setName(name + "Variables"); arguments.setName(name + "Variables");
@ -104,7 +104,12 @@ public class MsScenario extends MsTestElement {
variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue ->
arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=")
); );
if (config != null && config.getConfig() != null && config.getConfig().getCommonConfig() != null
&& CollectionUtils.isNotEmpty(config.getConfig().getCommonConfig().getVariables())) {
config.getConfig().getCommonConfig().getVariables().stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue ->
arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=")
);
}
return arguments; return arguments;
} }
} }

View File

@ -189,27 +189,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo(); BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
reportUrl = baseSystemConfigDTO.getUrl() + "/#/api/automation/report"; reportUrl = baseSystemConfigDTO.getUrl() + "/#/api/automation/report";
String scenaName = scenarioReport.getName(); testResult.setTestId(scenarioReport.getScenarioId());
if (scenaName == null) {
scenaName = "";
} else {
String[] sceneNameArr = scenaName.split("-");
if (sceneNameArr.length >= 4) {
//如果以yyyy-MM-dd 时间类型结尾
String endStr = "-" + sceneNameArr[sceneNameArr.length - 3] + "-" + sceneNameArr[sceneNameArr.length - 2] + "-" + sceneNameArr[sceneNameArr.length - 1];
scenaName = scenaName.split(endStr)[0];
} else {
//如果以时间戳结尾
scenaName = scenaName.split("-")[0];
}
}
ApiScenarioReport savedReport = apiScenarioReportService.get(testId);
String scenarioID = "";
if(savedReport!=null){
scenarioID = savedReport.getScenarioId();
}
testResult.setTestId(scenarioID);
} else { } else {
apiTestService.changeStatus(testId, APITestStatus.Completed); apiTestService.changeStatus(testId, APITestStatus.Completed);
report = apiReportService.getRunningReport(testResult.getTestId()); report = apiReportService.getRunningReport(testResult.getTestId());

View File

@ -260,10 +260,15 @@ public class ApiAutomationService {
return new ArrayList<>(); return new ArrayList<>();
} }
private void createAPIScenarioReportResult(String id, String triggerMode, String execType, String projectId, String userID) { private void createAPIScenarioReportResult(String id, String scenarioId, String scenarioName, String triggerMode, String execType, String projectId, String userID) {
APIScenarioReportResult report = new APIScenarioReportResult(); APIScenarioReportResult report = new APIScenarioReportResult();
report.setId(id); report.setId(id);
report.setName("测试执行结果"); report.setTestId(id);
if (StringUtils.isNotEmpty(scenarioName)) {
report.setName(scenarioName);
} else {
report.setName("零时调试名称");
}
report.setCreateTime(System.currentTimeMillis()); report.setCreateTime(System.currentTimeMillis());
report.setUpdateTime(System.currentTimeMillis()); report.setUpdateTime(System.currentTimeMillis());
report.setStatus(APITestStatus.Running.name()); report.setStatus(APITestStatus.Running.name());
@ -272,12 +277,12 @@ public class ApiAutomationService {
} else { } else {
report.setUserId(SessionUtils.getUserId()); report.setUserId(SessionUtils.getUserId());
} }
report.setTriggerMode(triggerMode); report.setTriggerMode(triggerMode);
report.setExecuteType(execType); report.setExecuteType(execType);
report.setProjectId(projectId); report.setProjectId(projectId);
apiReportService.addResult(report); report.setScenarioName(scenarioName);
report.setScenarioId(scenarioId);
apiScenarioReportMapper.insert(report);
} }
/** /**
@ -292,10 +297,17 @@ public class ApiAutomationService {
testPlan.setHashTree(new LinkedList<>()); testPlan.setHashTree(new LinkedList<>());
HashTree jmeterTestPlanHashTree = new ListedHashTree(); HashTree jmeterTestPlanHashTree = new ListedHashTree();
String projectID = request.getProjectId(); String projectID = request.getProjectId();
boolean isOne = true;
for (ApiScenarioWithBLOBs item : apiScenarios) { for (ApiScenarioWithBLOBs item : apiScenarios) {
MsThreadGroup group = new MsThreadGroup(); MsThreadGroup group = new MsThreadGroup();
group.setLabel(item.getName()); group.setLabel(item.getName());
group.setName(item.getName()); // 批量执行的结果直接存储为报告
if (isOne) {
group.setName(request.getId());
isOne = false;
} else {
group.setName(UUID.randomUUID().toString());
}
projectID = item.getProjectId(); projectID = item.getProjectId();
try { try {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
@ -318,6 +330,9 @@ public class ApiAutomationService {
group.setEnableCookieShare(scenario.isEnableCookieShare()); group.setEnableCookieShare(scenario.isEnableCookieShare());
LinkedList<MsTestElement> scenarios = new LinkedList<>(); LinkedList<MsTestElement> scenarios = new LinkedList<>();
scenarios.add(scenario); scenarios.add(scenario);
// 创建场景报告
createAPIScenarioReportResult(group.getName(), item.getId(), item.getName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
request.getExecuteType(), projectID, request.getReportUserID());
group.setHashTree(scenarios); group.setHashTree(scenarios);
testPlan.getHashTree().add(group); testPlan.getHashTree().add(group);
} catch (Exception ex) { } catch (Exception ex) {
@ -332,9 +347,6 @@ public class ApiAutomationService {
} }
// 调用执行方法 // 调用执行方法
jMeterService.runDefinition(request.getId(), jmeterTestPlanHashTree, request.getReportId(), runMode); jMeterService.runDefinition(request.getId(), jmeterTestPlanHashTree, request.getReportId(), runMode);
createAPIScenarioReportResult(request.getId(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
request.getExecuteType(), projectID, request.getReportUserID());
return request.getId(); return request.getId();
} }
@ -346,7 +358,7 @@ public class ApiAutomationService {
* @param bodyFiles * @param bodyFiles
* @return * @return
*/ */
public String run(RunDefinitionRequest request, List<MultipartFile> bodyFiles) { public String debugRun(RunDefinitionRequest request, List<MultipartFile> bodyFiles) {
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds()); List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
apiDefinitionService.createBodyFiles(bodyUploadIds, bodyFiles); apiDefinitionService.createBodyFiles(bodyUploadIds, bodyFiles);
EnvironmentConfig envConfig = null; EnvironmentConfig envConfig = null;
@ -359,7 +371,7 @@ public class ApiAutomationService {
HashTree hashTree = request.getTestElement().generateHashTree(config); HashTree hashTree = request.getTestElement().generateHashTree(config);
// 调用执行方法 // 调用执行方法
jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), ApiRunMode.SCENARIO.name()); jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), ApiRunMode.SCENARIO.name());
createAPIScenarioReportResult(request.getId(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(), createAPIScenarioReportResult(request.getId(), request.getScenarioId(), request.getScenarioName(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(),
SessionUtils.getUserId()); SessionUtils.getUserId());
return request.getId(); return request.getId();
} }

View File

@ -1,7 +1,6 @@
package io.metersphere.api.service; package io.metersphere.api.service;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.DeleteAPIReportRequest; import io.metersphere.api.dto.DeleteAPIReportRequest;
import io.metersphere.api.dto.QueryAPIReportRequest; import io.metersphere.api.dto.QueryAPIReportRequest;
import io.metersphere.api.dto.automation.APIScenarioReportResult; import io.metersphere.api.dto.automation.APIScenarioReportResult;
@ -15,30 +14,26 @@ import io.metersphere.base.mapper.ApiScenarioReportDetailMapper;
import io.metersphere.base.mapper.ApiScenarioReportMapper; import io.metersphere.base.mapper.ApiScenarioReportMapper;
import io.metersphere.base.mapper.TestPlanApiScenarioMapper; import io.metersphere.base.mapper.TestPlanApiScenarioMapper;
import io.metersphere.base.mapper.ext.ExtApiScenarioReportMapper; import io.metersphere.base.mapper.ext.ExtApiScenarioReportMapper;
import io.metersphere.commons.constants.APITestStatus;
import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.DateUtils; import io.metersphere.commons.utils.DateUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.ServiceUtils; import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.i18n.Translator; import io.metersphere.i18n.Translator;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import sun.security.util.Cache;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.*; import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Service @Service
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public class ApiScenarioReportService { public class ApiScenarioReportService {
private static Cache cache = Cache.newHardMemoryCache(0, 3600 * 24);
@Resource @Resource
private ExtApiScenarioReportMapper extApiScenarioReportMapper; private ExtApiScenarioReportMapper extApiScenarioReportMapper;
@Resource @Resource
@ -50,77 +45,18 @@ public class ApiScenarioReportService {
@Resource @Resource
private TestPlanApiScenarioMapper testPlanApiScenarioMapper; private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
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) { public ApiScenarioReport complete(TestResult result, String runMode) {
Object obj = cache.get(result.getTestId()); // 更新场景
if (obj == null) { if (result != null) {
MSException.throwException(Translator.get("api_report_is_null")); if (StringUtils.equals(runMode, ApiRunMode.SCENARIO_PLAN.name())) {
} return updatePlanCase(result);
APIScenarioReportResult report = (APIScenarioReportResult) obj;
report.setTestId(result.getTestId());
if (CollectionUtils.isNotEmpty(result.getScenarios())) {
try {
report.setName(result.getScenarios().get(0).getName() + "-" + DateUtils.getTimeString(System.currentTimeMillis()));
} catch (Exception e) {
LogUtil.error(e.getMessage());
}
}
// report detail
ApiScenarioReportDetail detail = new ApiScenarioReportDetail();
detail.setReportId(result.getTestId());
detail.setProjectId(report.getProjectId());
report.setTestId(result.getTestId());
detail.setContent(JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8));
// report
report.setUpdateTime(System.currentTimeMillis());
if (!StringUtils.equals(report.getStatus(), APITestStatus.Debug.name())) {
if (result.getError() > 0) {
report.setStatus(APITestStatus.Error.name());
} else { } else {
report.setStatus(APITestStatus.Success.name()); return updateScenario(result);
} }
} }
report.setContent(new String(detail.getContent(), StandardCharsets.UTF_8));
this.save(report, runMode);
// 此方法适用于前端发起
if (!report.getTriggerMode().equals(ReportTriggerMode.SCHEDULE.name())) {
cache.put(report.getId(), report);
}
return report;
}
/**
* 获取零时执行报告
*
* @param testId
*/
public APIScenarioReportResult getCacheResult(String testId) {
Object res = cache.get(testId);
if (res != null) {
APIScenarioReportResult reportResult = (APIScenarioReportResult) res;
if (!reportResult.getStatus().equals(APITestStatus.Running.name())) {
cache.remove(testId);
}
return reportResult;
}
return null; return null;
} }
public void addResult(APIScenarioReportResult res) {
cache.put(res.getId(), res);
}
public APIScenarioReportResult get(String reportId) { public APIScenarioReportResult get(String reportId) {
APIScenarioReportResult reportResult = extApiScenarioReportMapper.get(reportId); APIScenarioReportResult reportResult = extApiScenarioReportMapper.get(reportId);
ApiScenarioReportDetail detail = apiScenarioReportDetailMapper.selectByPrimaryKey(reportId); ApiScenarioReportDetail detail = apiScenarioReportDetailMapper.selectByPrimaryKey(reportId);
@ -143,26 +79,14 @@ public class ApiScenarioReportService {
} }
} }
public ApiScenarioReport createReport(APIScenarioReportResult test, String scenarioName, String scenarioId, String result, String testId) { public ApiScenarioReport editReport(ScenarioResult test) {
checkNameExist(test); ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(test.getName());
ApiScenarioReport report = new ApiScenarioReport(); report.setId(report.getId());
if (StringUtils.isNotEmpty(testId)) { report.setName(report.getScenarioName() + "-" + DateUtils.getTimeStr(System.currentTimeMillis()));
report.setId(testId);
} else {
report.setId(UUID.randomUUID().toString());
}
report.setProjectId(test.getProjectId());
report.setName(scenarioName + "-" + DateUtils.getTimeStr(System.currentTimeMillis()));
report.setTriggerMode(test.getTriggerMode());
report.setDescription(test.getDescription());
report.setCreateTime(System.currentTimeMillis());
report.setUpdateTime(System.currentTimeMillis()); report.setUpdateTime(System.currentTimeMillis());
report.setStatus(result); String status = test.getError() == 0 ? "Success" : "Error";
report.setUserId(test.getUserId()); report.setStatus(status);
report.setExecuteType(test.getExecuteType()); apiScenarioReportMapper.updateByPrimaryKeySelective(report);
report.setScenarioId(scenarioId);
report.setScenarioName(scenarioName);
apiScenarioReportMapper.insert(report);
return report; return report;
} }
@ -194,20 +118,8 @@ public class ApiScenarioReportService {
return testResult; return testResult;
} }
public void save(APIScenarioReportResult test, String runModel) { public ApiScenarioReport updatePlanCase(TestResult result) {
TestResult result = JSON.parseObject(test.getContent(), TestResult.class); TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(result.getTestId());
// 更新场景
if (result != null) {
if (StringUtils.equals(runModel, ApiRunMode.SCENARIO_PLAN.name())) {
updatePlanCase(result, test);
} else {
updateScenario(result, test);
}
}
}
public void updatePlanCase(TestResult result, APIScenarioReportResult scenarioReportResult) {
TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(scenarioReportResult.getId());
ScenarioResult scenarioResult = result.getScenarios().get(0); ScenarioResult scenarioResult = result.getScenarios().get(0);
if (scenarioResult.getError() > 0) { if (scenarioResult.getError() > 0) {
testPlanApiScenario.setLastResult("Fail"); testPlanApiScenario.setLastResult("Fail");
@ -217,33 +129,44 @@ public class ApiScenarioReportService {
String passRate = new DecimalFormat("0%").format((float) scenarioResult.getSuccess() / (scenarioResult.getSuccess() + scenarioResult.getError())); String passRate = new DecimalFormat("0%").format((float) scenarioResult.getSuccess() / (scenarioResult.getSuccess() + scenarioResult.getError()));
testPlanApiScenario.setPassRate(passRate); testPlanApiScenario.setPassRate(passRate);
// 存储场景报告 // 存储场景报告
String testId = null; ApiScenarioReport report = editReport(scenarioResult);
if (CollectionUtils.isNotEmpty(result.getScenarios()) && result.getScenarios().size() == 1) {
testId = scenarioReportResult.getTestId();
}
ApiScenarioReport report = createReport(scenarioReportResult, scenarioResult.getName(), testPlanApiScenario.getApiScenarioId(), scenarioResult.getError() == 0 ? "Success" : "Error", testId);
// 报告详情内容 // 报告详情内容
ApiScenarioReportDetail detail = new ApiScenarioReportDetail(); ApiScenarioReportDetail detail = new ApiScenarioReportDetail();
TestResult newResult = createTestResult(result); TestResult newResult = createTestResult(result);
List<ScenarioResult> scenarioResults = new ArrayList(); List<ScenarioResult> scenarioResults = new ArrayList();
scenarioResult.setName(report.getScenarioName());
scenarioResults.add(scenarioResult); scenarioResults.add(scenarioResult);
newResult.setScenarios(scenarioResults); newResult.setScenarios(scenarioResults);
detail.setContent(JSON.toJSONString(newResult).getBytes(StandardCharsets.UTF_8)); detail.setContent(JSON.toJSONString(newResult).getBytes(StandardCharsets.UTF_8));
detail.setReportId(report.getId()); detail.setReportId(report.getId());
detail.setProjectId(scenarioReportResult.getProjectId()); detail.setProjectId(report.getProjectId());
apiScenarioReportDetailMapper.insert(detail); apiScenarioReportDetailMapper.insert(detail);
testPlanApiScenario.setReportId(report.getId()); testPlanApiScenario.setReportId(report.getId());
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario); testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
return report;
} }
public void updateScenario(TestResult result, APIScenarioReportResult scenarioReportResult) { public ApiScenarioReport updateScenario(TestResult result) {
result.getScenarios().forEach(item -> { ApiScenarioReport lastReport = null;
ApiScenarioExample example = new ApiScenarioExample(); for (ScenarioResult item : result.getScenarios()) {
example.createCriteria().andNameEqualTo(item.getName()).andProjectIdEqualTo(scenarioReportResult.getProjectId()); // 更新报告状态
List<ApiScenario> list = apiScenarioMapper.selectByExample(example); ApiScenarioReport report = editReport(item);
if (list.size() > 0) {
ApiScenario scenario = list.get(0); // 报告详情内容
ApiScenarioReportDetail detail = new ApiScenarioReportDetail();
TestResult newResult = createTestResult(result);
List<ScenarioResult> scenarioResults = new ArrayList();
item.setName(report.getScenarioName());
scenarioResults.add(item);
newResult.setScenarios(scenarioResults);
detail.setContent(JSON.toJSONString(newResult).getBytes(StandardCharsets.UTF_8));
detail.setReportId(report.getId());
detail.setProjectId(report.getProjectId());
apiScenarioReportDetailMapper.insert(detail);
// 更新场景状态
ApiScenario scenario = apiScenarioMapper.selectByPrimaryKey(report.getScenarioId());
if (scenario != null) {
if (item.getError() > 0) { if (item.getError() > 0) {
scenario.setLastResult("Fail"); scenario.setLastResult("Fail");
} else { } else {
@ -251,28 +174,12 @@ public class ApiScenarioReportService {
} }
String passRate = new DecimalFormat("0%").format((float) item.getSuccess() / (item.getSuccess() + item.getError())); String passRate = new DecimalFormat("0%").format((float) item.getSuccess() / (item.getSuccess() + item.getError()));
scenario.setPassRate(passRate); scenario.setPassRate(passRate);
// 存储场景报告
String testId = null;
if (CollectionUtils.isNotEmpty(result.getScenarios()) && result.getScenarios().size() == 1) {
testId = scenarioReportResult.getTestId();
}
ApiScenarioReport report = createReport(scenarioReportResult, scenario.getName(), scenario.getId(), scenario.getLastResult(), testId);
// 报告详情内容
ApiScenarioReportDetail detail = new ApiScenarioReportDetail();
TestResult newResult = createTestResult(result);
List<ScenarioResult> scenarioResults = new ArrayList();
scenarioResults.add(item);
newResult.setScenarios(scenarioResults);
detail.setContent(JSON.toJSONString(newResult).getBytes(StandardCharsets.UTF_8));
detail.setReportId(report.getId());
detail.setProjectId(scenario.getProjectId());
apiScenarioReportDetailMapper.insert(detail);
// 更新场景状态
scenario.setReportId(report.getId()); scenario.setReportId(report.getId());
apiScenarioMapper.updateByPrimaryKey(scenario); apiScenarioMapper.updateByPrimaryKey(scenario);
} }
}); lastReport = report;
}
return lastReport;
} }
public String update(APIScenarioReportResult test) { public String update(APIScenarioReportResult test) {

View File

@ -37,8 +37,8 @@
SELECT testCase.testCaseName AS caseName,testCase.testPlanName AS testPlan ,caseErrorCountData.dataCountNumber AS failureTimes,'apiCase' AS caseType SELECT testCase.testCaseName AS caseName,testCase.testPlanName AS testPlan ,caseErrorCountData.dataCountNumber AS failureTimes,'apiCase' AS caseType
FROM ( FROM (
SELECT apiCase.id AS testCaseID,apiCase.`name` AS testCaseName,group_concat(testPlan.`name`) AS testPlanName FROM api_test_case apiCase SELECT apiCase.id AS testCaseID,apiCase.`name` AS testCaseName,group_concat(testPlan.`name`) AS testPlanName FROM api_test_case apiCase
LEFT JOIN test_plan_api_case testPlanCase ON testPlanCase.api_case_id = apiCase.id INNER JOIN test_plan_api_case testPlanCase ON testPlanCase.api_case_id = apiCase.id
LEFT JOIN test_plan testPlan ON testPlan.id = testPlanCase.test_plan_id INNER JOIN test_plan testPlan ON testPlan.id = testPlanCase.test_plan_id
GROUP BY apiCase.id GROUP BY apiCase.id
ORDER BY apiCase.create_time DESC ORDER BY apiCase.create_time DESC
)testCase )testCase
@ -54,7 +54,7 @@
FROM api_scenario_report report FROM api_scenario_report report
INNER JOIN api_scenario_report_detail reportDetail ON report.id = reportDetail.report_id INNER JOIN api_scenario_report_detail reportDetail ON report.id = reportDetail.report_id
INNER JOIN api_scenario scene ON report.scenario_id = scene.id INNER JOIN api_scenario scene ON report.scenario_id = scene.id
LEFT JOIN INNER JOIN
( (
SELECT SELECT
apiScene.api_scenario_id, apiScene.api_scenario_id,

View File

@ -192,5 +192,6 @@
SELECT acitem.`name`,acitem.id FROM api_scenario acitem INNER JOIN `schedule` sc ON acitem.id = sc.resource_id SELECT acitem.`name`,acitem.id FROM api_scenario acitem INNER JOIN `schedule` sc ON acitem.id = sc.resource_id
) ac on ar.scenario_id = ac.id ) ac on ar.scenario_id = ac.id
WHERE acr.project_id = #{projectId} WHERE acr.project_id = #{projectId}
GROUP BY groupField;
</select> </select>
</mapper> </mapper>

View File

@ -279,14 +279,14 @@
<select id="countProtocolByProjectID" resultType="io.metersphere.api.dto.datacount.ApiDataCountResult"> <select id="countProtocolByProjectID" resultType="io.metersphere.api.dto.datacount.ApiDataCountResult">
SELECT apiDef.protocol AS groupField,COUNT(testCase.id) AS countNumber FROM api_test_case testCase SELECT apiDef.protocol AS groupField,COUNT(testCase.id) AS countNumber FROM api_test_case testCase
INNER JOIN api_definition apiDef ON testCase.api_definition_id = apiDef.id INNER JOIN api_definition apiDef ON testCase.api_definition_id = apiDef.id
WHERE testCase.project_id = #{0} WHERE testCase.project_id = #{0} AND apiDef.status != "Trash"
GROUP BY apiDef.protocol GROUP BY apiDef.protocol
</select> </select>
<select id="countByProjectIDAndCreateInThisWeek" resultType="java.lang.Long"> <select id="countByProjectIDAndCreateInThisWeek" resultType="java.lang.Long">
SELECT count(testCase.id) AS countNumber FROM api_test_case testCase SELECT count(testCase.id) AS countNumber FROM api_test_case testCase
INNER JOIN api_definition apiDef ON testCase.api_definition_id = apiDef.id INNER JOIN api_definition apiDef ON testCase.api_definition_id = apiDef.id
WHERE testCase.project_id = #{projectId} WHERE testCase.project_id = #{projectId} AND apiDef.status != "Trash"
AND testCase.create_time BETWEEN #{firstDayTimestamp} AND #{lastDayTimestamp} AND testCase.create_time BETWEEN #{firstDayTimestamp} AND #{lastDayTimestamp}
</select> </select>

View File

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

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

View File

@ -2,7 +2,7 @@
<ms-container v-loading="loading"> <ms-container v-loading="loading">
<ms-main-container> <ms-main-container>
<el-card> <el-card>
<section class="report-container" v-if="this.report.testId"> <section class="report-container">
<ms-api-report-view-header :debug="debug" :report="report" @reportExport="handleExport" @reportSave="handleSave"/> <ms-api-report-view-header :debug="debug" :report="report" @reportExport="handleExport" @reportSave="handleSave"/>
@ -96,7 +96,7 @@
getReport() { getReport() {
this.init(); this.init();
if (this.reportId) { if (this.reportId) {
let url = "/api/scenario/report/get/" + this.reportId + "/" + this.infoDb; let url = "/api/scenario/report/get/" + this.reportId;
this.$get(url, response => { this.$get(url, response => {
this.report = response.data || {}; this.report = response.data || {};
if (response.data) { if (response.data) {

View File

@ -6,7 +6,7 @@
:show-create="false"/> :show-create="false"/>
</template> </template>
<el-table ref="scenarioTable" border :data="tableData" class="adjust-table" @select-all="select" @select="select"> <el-table ref="scenarioTable" border :data="tableData" class="adjust-table" @select-all="select" @select="select" v-loading="loading">
<el-table-column type="selection"/> <el-table-column type="selection"/>
<el-table-column width="40" :resizable="false" align="center"> <el-table-column width="40" :resizable="false" align="center">
<template v-slot:default="{row}"> <template v-slot:default="{row}">
@ -118,11 +118,14 @@
pageSize: 10, pageSize: 10,
total: 0, total: 0,
reportId: "", reportId: "",
batchReportId: "",
content: {},
infoDb: false, infoDb: false,
runVisible: false, runVisible: false,
planVisible: false, planVisible: false,
projectId: "", projectId: "",
runData: [], runData: [],
report: {},
buttons: [ buttons: [
{ {
name: this.$t('api_test.automation.batch_add_plan'), handleClick: this.handleBatchAddCase name: this.$t('api_test.automation.batch_add_plan'), handleClick: this.handleBatchAddCase
@ -145,12 +148,20 @@
this.search(); this.search();
} }
}, },
batchReportId() {
this.loading = true;
this.getReport();
}
},
computed: {
isNotRunning() {
return "Running" !== this.report.status;
}
}, },
methods: { methods: {
search() { search() {
this.loading = true; this.loading = true;
this.condition.filters = ["Prepare", "Underway", "Completed"]; this.condition.filters = ["Prepare", "Underway", "Completed"];
this.condition.moduleIds = this.selectNodeIds; this.condition.moduleIds = this.selectNodeIds;
if (this.trashEnable) { if (this.trashEnable) {
@ -197,9 +208,33 @@
this.$success(this.$t("commons.save_success")); this.$success(this.$t("commons.save_success"));
}); });
}, },
getReport() {
if (this.batchReportId) {
let url = "/api/scenario/report/get/" + this.batchReportId;
this.$get(url, response => {
this.report = response.data || {};
if (response.data) {
if (this.isNotRunning) {
try {
this.content = JSON.parse(this.report.content);
} catch (e) {
throw e;
}
this.loading = false;
this.$success("批量执行成功,请到报告页面查看详情!");
} else {
setTimeout(this.getReport, 2000)
}
} else {
this.loading = false;
this.$error(this.$t('api_report.not_exist'));
}
});
}
},
handleBatchExecute() { handleBatchExecute() {
this.infoDb = false; this.infoDb = false;
let url = "/api/automation/run"; let url = "/api/automation/run/batch";
let run = {}; let run = {};
let scenarioIds = this.selection; let scenarioIds = this.selection;
run.id = getUUID(); run.id = getUUID();
@ -207,8 +242,8 @@
run.projectId = getCurrentProjectID(); run.projectId = getCurrentProjectID();
this.$post(url, run, response => { this.$post(url, run, response => {
let data = response.data; let data = response.data;
this.runVisible = true; this.runVisible = false;
this.reportId = run.id; this.batchReportId = run.id;
}); });
}, },
selectAllChange() { selectAllChange() {

View File

@ -92,11 +92,11 @@
let testPlan = createComponent('TestPlan'); let testPlan = createComponent('TestPlan');
let threadGroup = createComponent('ThreadGroup'); let threadGroup = createComponent('ThreadGroup');
threadGroup.hashTree = []; threadGroup.hashTree = [];
threadGroup.name = this.runData.name ? this.runData.name : "Debug-Scenario"; threadGroup.name = this.reportId;
threadGroup.enableCookieShare = this.runData.enableCookieShare; threadGroup.enableCookieShare = this.runData.enableCookieShare;
threadGroup.hashTree.push(this.runData); threadGroup.hashTree.push(this.runData);
testPlan.hashTree.push(threadGroup); testPlan.hashTree.push(threadGroup);
let reqObj = {id: this.reportId, reportId: this.reportId, environmentId: this.environment, testElement: testPlan, projectId: getCurrentProjectID()}; let reqObj = {id: this.reportId, reportId: this.reportId, scenarioName: this.runData.name, scenarioId: this.runData.id, environmentId: this.environment, testElement: testPlan, projectId: getCurrentProjectID()};
let bodyFiles = this.getBodyUploadFiles(reqObj); let bodyFiles = this.getBodyUploadFiles(reqObj);
let url = "/api/automation/run/debug"; let url = "/api/automation/run/debug";
this.$fileUpload(url, null, bodyFiles, reqObj, response => { this.$fileUpload(url, null, bodyFiles, reqObj, response => {

@ -1 +1 @@
Subproject commit 010ad7a5f072a5e9d368c756a2473bbd20781433 Subproject commit 8cda5c873cd9985c97adb34efacf507167fa4182