feat(接口测试): 报告增加统计指标
This commit is contained in:
parent
cce42065d7
commit
6c6edd4e44
|
@ -0,0 +1,5 @@
|
||||||
|
package io.metersphere.sdk.constants;
|
||||||
|
|
||||||
|
public enum ProcessDataStatus {
|
||||||
|
MS_RESOURCE_ID, MS_STEP_ID, MS_FAKE_ERROR
|
||||||
|
}
|
|
@ -6,15 +6,18 @@ import lombok.Data;
|
||||||
public class ProcessResultDTO {
|
public class ProcessResultDTO {
|
||||||
// 报告状态
|
// 报告状态
|
||||||
private String status;
|
private String status;
|
||||||
// 总数
|
|
||||||
|
// TODO 总数,放报告生成后计算
|
||||||
private long total;
|
private long total;
|
||||||
|
|
||||||
// 成功总数
|
// 成功总数
|
||||||
private long successCount;
|
private long successCount;
|
||||||
// 误报总数
|
// 误报总数
|
||||||
private long fakeErrorCount;
|
private long fakeErrorCount;
|
||||||
// 失败总数
|
// 失败总数
|
||||||
private long errorCount;
|
private long errorCount;
|
||||||
// 未执行总数
|
|
||||||
|
// TODO 根据初始步骤大小,在执行过程中进行标记; 初始大小 - 过程标记步骤
|
||||||
private long pendingCount;
|
private long pendingCount;
|
||||||
// 断言总数
|
// 断言总数
|
||||||
private long assertionCount;
|
private long assertionCount;
|
||||||
|
@ -28,7 +31,7 @@ public class ProcessResultDTO {
|
||||||
private String assertionPassRate;
|
private String assertionPassRate;
|
||||||
|
|
||||||
public void computerTotal() {
|
public void computerTotal() {
|
||||||
this.total = (this.successCount + this.errorCount + this.pendingCount);
|
this.total = this.pendingCount + this.errorCount + this.successCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void computerFakeError(long fakeErrorCount) {
|
public void computerFakeError(long fakeErrorCount) {
|
||||||
|
@ -43,10 +46,6 @@ public class ProcessResultDTO {
|
||||||
this.errorCount += error;
|
this.errorCount += error;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void computerPending(long pending) {
|
|
||||||
this.pendingCount += pending;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void computerAssertion(long assertion) {
|
public void computerAssertion(long assertion) {
|
||||||
this.assertionCount += assertion;
|
this.assertionCount += assertion;
|
||||||
}
|
}
|
||||||
|
@ -55,19 +54,35 @@ public class ProcessResultDTO {
|
||||||
this.successAssertionCount += successAssertion;
|
this.successAssertionCount += successAssertion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 整体执行完成后调用计算执行率
|
||||||
|
* (成功+失败 ) /总量* 100
|
||||||
|
*/
|
||||||
public void computerRequestExecutionRate() {
|
public void computerRequestExecutionRate() {
|
||||||
this.computerTotal();
|
long count = this.successCount + this.errorCount;
|
||||||
double executionRate = (double) this.total / (this.successCount + this.errorCount);
|
if (this.total > 0 && count > 0) {
|
||||||
|
double executionRate = (double) count / this.total * 100;
|
||||||
this.requestExecutionRate = String.format("%.2f", executionRate);
|
this.requestExecutionRate = String.format("%.2f", executionRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void computerRequestPassRate() {
|
|
||||||
this.computerTotal();
|
|
||||||
this.requestPassRate = String.format("%.2f", (double) this.total / (this.successCount));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 整体完成后调用计算通过率
|
||||||
|
* 成功总数 / 总量 * 100
|
||||||
|
*/
|
||||||
|
public void computerRequestPassRate() {
|
||||||
|
if (this.total > 0 && this.successCount > 0) {
|
||||||
|
this.requestPassRate = String.format("%.2f", (double) this.successCount / this.total * 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 整体完成后调用计算断言通过率
|
||||||
|
*/
|
||||||
public void computerAssertionPassRate() {
|
public void computerAssertionPassRate() {
|
||||||
this.assertionPassRate = String.format("%.2f", (double) this.assertionCount / successAssertionCount);
|
if (this.assertionCount > 0 && successAssertionCount > 0) {
|
||||||
|
this.assertionPassRate = String.format("%.2f", (double) successAssertionCount / this.assertionCount * 100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,10 @@ import java.util.List;
|
||||||
@Data
|
@Data
|
||||||
public class RequestResult {
|
public class RequestResult {
|
||||||
// 请求ID
|
// 请求ID
|
||||||
private String id;
|
private String resourceId;
|
||||||
|
|
||||||
// 步骤请求唯一ID
|
// 步骤请求唯一ID
|
||||||
private String resourceId;
|
private String stepId;
|
||||||
|
|
||||||
// 线程名称
|
// 线程名称
|
||||||
private String threadName;
|
private String threadName;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package io.metersphere.sdk.dto.api.result;
|
package io.metersphere.sdk.dto.api.result;
|
||||||
|
|
||||||
import io.metersphere.sdk.dto.api.CollectionReportDTO;
|
import io.metersphere.sdk.dto.api.task.TaskRequest;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
|
@ -13,40 +13,29 @@ public class TaskResult implements Serializable {
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
// TODO: 补充任务执行结果数据结构
|
|
||||||
|
|
||||||
private List<RequestResult> requestResults;
|
|
||||||
private String runMode;
|
|
||||||
private String queueId;
|
|
||||||
private String reportId;
|
|
||||||
private String reportType;
|
|
||||||
private String testPlanReportId;
|
|
||||||
private String testId;
|
|
||||||
private String runType;
|
|
||||||
private String console;
|
|
||||||
private String runningDebugSampler;
|
|
||||||
private Boolean hasEnded;
|
|
||||||
private boolean retryEnable;
|
|
||||||
/**
|
/**
|
||||||
* 项目id
|
* 任务执行结果数据结构
|
||||||
*/
|
*/
|
||||||
private String projectId;
|
private List<RequestResult> requestResults;
|
||||||
|
/**
|
||||||
|
* 控制台信息
|
||||||
|
*/
|
||||||
|
private String console;
|
||||||
|
/**
|
||||||
|
* debug 信息
|
||||||
|
*/
|
||||||
|
private String runningDebugSampler;
|
||||||
|
/**
|
||||||
|
* 线程组执行完成标识
|
||||||
|
*/
|
||||||
|
private Boolean hasEnded;
|
||||||
/**
|
/**
|
||||||
* 执行过程状态
|
* 执行过程状态
|
||||||
*/
|
*/
|
||||||
private ProcessResultDTO processResultDTO;
|
private ProcessResultDTO processResultDTO;
|
||||||
/**
|
|
||||||
* 资源类型
|
|
||||||
* ApiResourceType
|
|
||||||
*/
|
|
||||||
private String resourceType;
|
|
||||||
/**
|
|
||||||
* 环境变量处理信息
|
|
||||||
*/
|
|
||||||
String environmentId;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 集合报告,空则是单报告
|
* 请求参数
|
||||||
*/
|
*/
|
||||||
private CollectionReportDTO collectionReport;
|
private TaskRequest request;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,13 @@ public class TaskRequest implements Serializable {
|
||||||
* 执行模式
|
* 执行模式
|
||||||
*/
|
*/
|
||||||
private String runMode;
|
private String runMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发方式
|
||||||
|
* 手动执行,批量执行,API执行,定时任务
|
||||||
|
*/
|
||||||
|
private String triggerMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 资源类型
|
* 资源类型
|
||||||
* ApiResourceType
|
* ApiResourceType
|
||||||
|
@ -74,5 +81,10 @@ public class TaskRequest implements Serializable {
|
||||||
*/
|
*/
|
||||||
private CollectionReportDTO collectionReport;
|
private CollectionReportDTO collectionReport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 要执行的请求总量
|
||||||
|
*/
|
||||||
|
private Long requestCount;
|
||||||
|
|
||||||
// TODO 其它执行参数
|
// TODO 其它执行参数
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
package io.metersphere.sdk.util;
|
|
||||||
|
|
||||||
import io.metersphere.sdk.constants.ApiReportStatus;
|
|
||||||
import io.metersphere.sdk.dto.api.result.ProcessResultDTO;
|
|
||||||
import io.metersphere.sdk.dto.api.result.RequestResult;
|
|
||||||
import io.metersphere.sdk.dto.api.result.TaskResult;
|
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ReportStatusUtils {
|
|
||||||
public static List<RequestResult> filterRetryResults(List<RequestResult> results) {
|
|
||||||
List<RequestResult> list = new LinkedList<>();
|
|
||||||
if (CollectionUtils.isNotEmpty(results)) {
|
|
||||||
Map<String, List<RequestResult>> resultMap = results.stream().collect(Collectors.groupingBy(RequestResult::getResourceId));
|
|
||||||
resultMap.forEach((k, v) -> {
|
|
||||||
if (CollectionUtils.isNotEmpty(v)) {
|
|
||||||
// 校验是否含重试结果
|
|
||||||
List<RequestResult> isRetryResults = v.stream().filter(c ->
|
|
||||||
StringUtils.isNotEmpty(c.getName()) && c.getName().startsWith(RetryResultUtils.RETRY_CN))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (CollectionUtils.isNotEmpty(isRetryResults)) {
|
|
||||||
list.add(isRetryResults.getLast());
|
|
||||||
} else {
|
|
||||||
// 成功的结果
|
|
||||||
list.addAll(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回正确的报告状态
|
|
||||||
*
|
|
||||||
* @param dto jmeter返回
|
|
||||||
*/
|
|
||||||
public static ProcessResultDTO getStatus(TaskResult dto, ProcessResultDTO process) {
|
|
||||||
process.computerSuccess(dto.getRequestResults().stream()
|
|
||||||
.filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ApiReportStatus.SUCCESS.name())).count());
|
|
||||||
|
|
||||||
process.computerFakeError(dto.getRequestResults().stream()
|
|
||||||
.filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ApiReportStatus.FAKE_ERROR.name())).count());
|
|
||||||
|
|
||||||
process.computerError(dto.getRequestResults().stream()
|
|
||||||
.filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ApiReportStatus.ERROR.name())).count());
|
|
||||||
|
|
||||||
process.computerPending(dto.getRequestResults().stream()
|
|
||||||
.filter(requestResult -> StringUtils.equalsIgnoreCase(requestResult.getStatus(), ApiReportStatus.PENDING.name())).count());
|
|
||||||
|
|
||||||
// 断言计算
|
|
||||||
dto.getRequestResults().forEach(requestResult -> {
|
|
||||||
process.computerAssertion(requestResult.getAssertionTotal());
|
|
||||||
process.computerSuccessAssertion(requestResult.getPassAssertionsTotal());
|
|
||||||
});
|
|
||||||
|
|
||||||
// 各种通过率
|
|
||||||
process.computerRequestExecutionRate();
|
|
||||||
process.computerRequestPassRate();
|
|
||||||
process.computerAssertionPassRate();
|
|
||||||
|
|
||||||
if (StringUtils.equals(process.getStatus(), ApiReportStatus.ERROR.name())) {
|
|
||||||
return process;
|
|
||||||
}
|
|
||||||
if (ObjectUtils.isNotEmpty(dto.getProcessResultDTO())) {
|
|
||||||
// 资源池执行整体传输失败,单条传输内容,获取资源池执行统计的状态
|
|
||||||
process.setStatus(dto.getProcessResultDTO().getStatus());
|
|
||||||
}
|
|
||||||
// 过滤掉重试结果后进行统计
|
|
||||||
long errorSize = process.getErrorCount();
|
|
||||||
// 误报
|
|
||||||
long errorReportResultSize = process.getFakeErrorCount();
|
|
||||||
// 默认状态
|
|
||||||
String status = dto.getRequestResults().isEmpty() && StringUtils.isEmpty(process.getStatus())
|
|
||||||
? ApiReportStatus.PENDING.name()
|
|
||||||
: StringUtils.defaultIfEmpty(process.getStatus(), ApiReportStatus.SUCCESS.name());
|
|
||||||
|
|
||||||
if (errorSize > 0) {
|
|
||||||
status = ApiReportStatus.ERROR.name();
|
|
||||||
} else if (errorReportResultSize > 0) {
|
|
||||||
status = ApiReportStatus.FAKE_ERROR.name();
|
|
||||||
}
|
|
||||||
process.setStatus(status);
|
|
||||||
process.computerTotal();
|
|
||||||
return process;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ProcessResultDTO computedProcess(TaskResult dto) {
|
|
||||||
ProcessResultDTO result = dto.getProcessResultDTO();
|
|
||||||
result = getStatus(dto, result);
|
|
||||||
if (result.getTotal() > 0 && result.getTotal() == result.getSuccessCount()) {
|
|
||||||
result.setStatus(ApiReportStatus.SUCCESS.name());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,6 +9,7 @@ import io.metersphere.api.parser.jmeter.body.MsFormDataBodyConverter;
|
||||||
import io.metersphere.api.parser.jmeter.body.MsWWWFormBodyConverter;
|
import io.metersphere.api.parser.jmeter.body.MsWWWFormBodyConverter;
|
||||||
import io.metersphere.plugin.api.dto.ParameterConfig;
|
import io.metersphere.plugin.api.dto.ParameterConfig;
|
||||||
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
|
import io.metersphere.plugin.api.spi.AbstractJmeterElementConverter;
|
||||||
|
import io.metersphere.sdk.constants.ProcessDataStatus;
|
||||||
import io.metersphere.sdk.util.LogUtils;
|
import io.metersphere.sdk.util.LogUtils;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -42,6 +43,10 @@ public class MsHTTPElementConverter extends AbstractJmeterElementConverter<MsHTT
|
||||||
sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
|
sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
|
||||||
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass(HTTP_TEST_SAMPLE_GUI));
|
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass(HTTP_TEST_SAMPLE_GUI));
|
||||||
|
|
||||||
|
// TODO: 当前步骤唯一标识,很重要,结果和步骤匹配的关键
|
||||||
|
sampler.setProperty(ProcessDataStatus.MS_RESOURCE_ID.name(), msHTTPElement.getResourceId());
|
||||||
|
sampler.setProperty(ProcessDataStatus.MS_STEP_ID.name(), msHTTPElement.getStepId());
|
||||||
|
|
||||||
sampler.setMethod(msHTTPElement.getMethod());
|
sampler.setMethod(msHTTPElement.getMethod());
|
||||||
// todo 根据环境设置
|
// todo 根据环境设置
|
||||||
sampler.setDomain(msHTTPElement.getUrl());
|
sampler.setDomain(msHTTPElement.getUrl());
|
||||||
|
|
Loading…
Reference in New Issue