feat(接口测试): 场景批量执行

This commit is contained in:
AgAngle 2024-03-19 17:22:57 +08:00 committed by Craftsman
parent efa5387cf1
commit 95d1e28e05
32 changed files with 656 additions and 301 deletions

View File

@ -75,9 +75,6 @@ public class ApiScenarioReport implements Serializable {
@Size(min = 1, max = 50, message = "{api_scenario_report.pool_id.length_range}", groups = {Created.class, Updated.class}) @Size(min = 1, max = 50, message = "{api_scenario_report.pool_id.length_range}", groups = {Created.class, Updated.class})
private String poolId; private String poolId;
@Schema(description = "版本fk")
private String versionId;
@Schema(description = "是否是集成报告", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "是否是集成报告", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "{api_scenario_report.integrated.not_blank}", groups = {Created.class}) @NotNull(message = "{api_scenario_report.integrated.not_blank}", groups = {Created.class})
private Boolean integrated; private Boolean integrated;
@ -161,7 +158,6 @@ public class ApiScenarioReport implements Serializable {
triggerMode("trigger_mode", "triggerMode", "VARCHAR", false), triggerMode("trigger_mode", "triggerMode", "VARCHAR", false),
runMode("run_mode", "runMode", "VARCHAR", false), runMode("run_mode", "runMode", "VARCHAR", false),
poolId("pool_id", "poolId", "VARCHAR", false), poolId("pool_id", "poolId", "VARCHAR", false),
versionId("version_id", "versionId", "VARCHAR", false),
integrated("integrated", "integrated", "BIT", false), integrated("integrated", "integrated", "BIT", false),
projectId("project_id", "projectId", "VARCHAR", false), projectId("project_id", "projectId", "VARCHAR", false),
environmentId("environment_id", "environmentId", "VARCHAR", false), environmentId("environment_id", "environmentId", "VARCHAR", false),

View File

@ -1164,76 +1164,6 @@ public class ApiScenarioReportExample {
return (Criteria) this; return (Criteria) this;
} }
public Criteria andVersionIdIsNull() {
addCriterion("version_id is null");
return (Criteria) this;
}
public Criteria andVersionIdIsNotNull() {
addCriterion("version_id is not null");
return (Criteria) this;
}
public Criteria andVersionIdEqualTo(String value) {
addCriterion("version_id =", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdNotEqualTo(String value) {
addCriterion("version_id <>", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdGreaterThan(String value) {
addCriterion("version_id >", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdGreaterThanOrEqualTo(String value) {
addCriterion("version_id >=", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdLessThan(String value) {
addCriterion("version_id <", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdLessThanOrEqualTo(String value) {
addCriterion("version_id <=", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdLike(String value) {
addCriterion("version_id like", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdNotLike(String value) {
addCriterion("version_id not like", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdIn(List<String> values) {
addCriterion("version_id in", values, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdNotIn(List<String> values) {
addCriterion("version_id not in", values, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdBetween(String value1, String value2) {
addCriterion("version_id between", value1, value2, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdNotBetween(String value1, String value2) {
addCriterion("version_id not between", value1, value2, "versionId");
return (Criteria) this;
}
public Criteria andIntegratedIsNull() { public Criteria andIntegratedIsNull() {
addCriterion("integrated is null"); addCriterion("integrated is null");
return (Criteria) this; return (Criteria) this;

View File

@ -18,7 +18,6 @@
<result column="trigger_mode" jdbcType="VARCHAR" property="triggerMode" /> <result column="trigger_mode" jdbcType="VARCHAR" property="triggerMode" />
<result column="run_mode" jdbcType="VARCHAR" property="runMode" /> <result column="run_mode" jdbcType="VARCHAR" property="runMode" />
<result column="pool_id" jdbcType="VARCHAR" property="poolId" /> <result column="pool_id" jdbcType="VARCHAR" property="poolId" />
<result column="version_id" jdbcType="VARCHAR" property="versionId" />
<result column="integrated" jdbcType="BIT" property="integrated" /> <result column="integrated" jdbcType="BIT" property="integrated" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" /> <result column="project_id" jdbcType="VARCHAR" property="projectId" />
<result column="environment_id" jdbcType="VARCHAR" property="environmentId" /> <result column="environment_id" jdbcType="VARCHAR" property="environmentId" />
@ -96,10 +95,9 @@
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id, `name`, test_plan_id, create_user, delete_time, delete_user, deleted, update_user, id, `name`, test_plan_id, create_user, delete_time, delete_user, deleted, update_user,
update_time, start_time, end_time, request_duration, `status`, trigger_mode, run_mode, update_time, start_time, end_time, request_duration, `status`, trigger_mode, run_mode,
pool_id, version_id, integrated, project_id, environment_id, error_count, fake_error_count, pool_id, integrated, project_id, environment_id, error_count, fake_error_count, pending_count,
pending_count, success_count, assertion_count, assertion_success_count, request_error_rate, success_count, assertion_count, assertion_success_count, request_error_rate, request_pending_rate,
request_pending_rate, request_fake_error_rate, request_pass_rate, assertion_pass_rate, request_fake_error_rate, request_pass_rate, assertion_pass_rate, script_identifier
script_identifier
</sql> </sql>
<select id="selectByExample" parameterType="io.metersphere.api.domain.ApiScenarioReportExample" resultMap="BaseResultMap"> <select id="selectByExample" parameterType="io.metersphere.api.domain.ApiScenarioReportExample" resultMap="BaseResultMap">
select select
@ -137,10 +135,10 @@
deleted, update_user, update_time, deleted, update_user, update_time,
start_time, end_time, request_duration, start_time, end_time, request_duration,
`status`, trigger_mode, run_mode, `status`, trigger_mode, run_mode,
pool_id, version_id, integrated, pool_id, integrated, project_id,
project_id, environment_id, error_count, environment_id, error_count, fake_error_count,
fake_error_count, pending_count, success_count, pending_count, success_count, assertion_count,
assertion_count, assertion_success_count, request_error_rate, assertion_success_count, request_error_rate,
request_pending_rate, request_fake_error_rate, request_pending_rate, request_fake_error_rate,
request_pass_rate, assertion_pass_rate, script_identifier request_pass_rate, assertion_pass_rate, script_identifier
) )
@ -149,10 +147,10 @@
#{deleted,jdbcType=BIT}, #{updateUser,jdbcType=VARCHAR}, #{updateTime,jdbcType=BIGINT}, #{deleted,jdbcType=BIT}, #{updateUser,jdbcType=VARCHAR}, #{updateTime,jdbcType=BIGINT},
#{startTime,jdbcType=BIGINT}, #{endTime,jdbcType=BIGINT}, #{requestDuration,jdbcType=BIGINT}, #{startTime,jdbcType=BIGINT}, #{endTime,jdbcType=BIGINT}, #{requestDuration,jdbcType=BIGINT},
#{status,jdbcType=VARCHAR}, #{triggerMode,jdbcType=VARCHAR}, #{runMode,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{triggerMode,jdbcType=VARCHAR}, #{runMode,jdbcType=VARCHAR},
#{poolId,jdbcType=VARCHAR}, #{versionId,jdbcType=VARCHAR}, #{integrated,jdbcType=BIT}, #{poolId,jdbcType=VARCHAR}, #{integrated,jdbcType=BIT}, #{projectId,jdbcType=VARCHAR},
#{projectId,jdbcType=VARCHAR}, #{environmentId,jdbcType=VARCHAR}, #{errorCount,jdbcType=BIGINT}, #{environmentId,jdbcType=VARCHAR}, #{errorCount,jdbcType=BIGINT}, #{fakeErrorCount,jdbcType=BIGINT},
#{fakeErrorCount,jdbcType=BIGINT}, #{pendingCount,jdbcType=BIGINT}, #{successCount,jdbcType=BIGINT}, #{pendingCount,jdbcType=BIGINT}, #{successCount,jdbcType=BIGINT}, #{assertionCount,jdbcType=BIGINT},
#{assertionCount,jdbcType=BIGINT}, #{assertionSuccessCount,jdbcType=BIGINT}, #{requestErrorRate,jdbcType=VARCHAR}, #{assertionSuccessCount,jdbcType=BIGINT}, #{requestErrorRate,jdbcType=VARCHAR},
#{requestPendingRate,jdbcType=VARCHAR}, #{requestFakeErrorRate,jdbcType=VARCHAR}, #{requestPendingRate,jdbcType=VARCHAR}, #{requestFakeErrorRate,jdbcType=VARCHAR},
#{requestPassRate,jdbcType=VARCHAR}, #{assertionPassRate,jdbcType=VARCHAR}, #{scriptIdentifier,jdbcType=VARCHAR} #{requestPassRate,jdbcType=VARCHAR}, #{assertionPassRate,jdbcType=VARCHAR}, #{scriptIdentifier,jdbcType=VARCHAR}
) )
@ -208,9 +206,6 @@
<if test="poolId != null"> <if test="poolId != null">
pool_id, pool_id,
</if> </if>
<if test="versionId != null">
version_id,
</if>
<if test="integrated != null"> <if test="integrated != null">
integrated, integrated,
</if> </if>
@ -306,9 +301,6 @@
<if test="poolId != null"> <if test="poolId != null">
#{poolId,jdbcType=VARCHAR}, #{poolId,jdbcType=VARCHAR},
</if> </if>
<if test="versionId != null">
#{versionId,jdbcType=VARCHAR},
</if>
<if test="integrated != null"> <if test="integrated != null">
#{integrated,jdbcType=BIT}, #{integrated,jdbcType=BIT},
</if> </if>
@ -413,9 +405,6 @@
<if test="record.poolId != null"> <if test="record.poolId != null">
pool_id = #{record.poolId,jdbcType=VARCHAR}, pool_id = #{record.poolId,jdbcType=VARCHAR},
</if> </if>
<if test="record.versionId != null">
version_id = #{record.versionId,jdbcType=VARCHAR},
</if>
<if test="record.integrated != null"> <if test="record.integrated != null">
integrated = #{record.integrated,jdbcType=BIT}, integrated = #{record.integrated,jdbcType=BIT},
</if> </if>
@ -484,7 +473,6 @@
trigger_mode = #{record.triggerMode,jdbcType=VARCHAR}, trigger_mode = #{record.triggerMode,jdbcType=VARCHAR},
run_mode = #{record.runMode,jdbcType=VARCHAR}, run_mode = #{record.runMode,jdbcType=VARCHAR},
pool_id = #{record.poolId,jdbcType=VARCHAR}, pool_id = #{record.poolId,jdbcType=VARCHAR},
version_id = #{record.versionId,jdbcType=VARCHAR},
integrated = #{record.integrated,jdbcType=BIT}, integrated = #{record.integrated,jdbcType=BIT},
project_id = #{record.projectId,jdbcType=VARCHAR}, project_id = #{record.projectId,jdbcType=VARCHAR},
environment_id = #{record.environmentId,jdbcType=VARCHAR}, environment_id = #{record.environmentId,jdbcType=VARCHAR},
@ -552,9 +540,6 @@
<if test="poolId != null"> <if test="poolId != null">
pool_id = #{poolId,jdbcType=VARCHAR}, pool_id = #{poolId,jdbcType=VARCHAR},
</if> </if>
<if test="versionId != null">
version_id = #{versionId,jdbcType=VARCHAR},
</if>
<if test="integrated != null"> <if test="integrated != null">
integrated = #{integrated,jdbcType=BIT}, integrated = #{integrated,jdbcType=BIT},
</if> </if>
@ -620,7 +605,6 @@
trigger_mode = #{triggerMode,jdbcType=VARCHAR}, trigger_mode = #{triggerMode,jdbcType=VARCHAR},
run_mode = #{runMode,jdbcType=VARCHAR}, run_mode = #{runMode,jdbcType=VARCHAR},
pool_id = #{poolId,jdbcType=VARCHAR}, pool_id = #{poolId,jdbcType=VARCHAR},
version_id = #{versionId,jdbcType=VARCHAR},
integrated = #{integrated,jdbcType=BIT}, integrated = #{integrated,jdbcType=BIT},
project_id = #{projectId,jdbcType=VARCHAR}, project_id = #{projectId,jdbcType=VARCHAR},
environment_id = #{environmentId,jdbcType=VARCHAR}, environment_id = #{environmentId,jdbcType=VARCHAR},
@ -642,7 +626,7 @@
insert into api_scenario_report insert into api_scenario_report
(id, `name`, test_plan_id, create_user, delete_time, delete_user, deleted, update_user, (id, `name`, test_plan_id, create_user, delete_time, delete_user, deleted, update_user,
update_time, start_time, end_time, request_duration, `status`, trigger_mode, run_mode, update_time, start_time, end_time, request_duration, `status`, trigger_mode, run_mode,
pool_id, version_id, integrated, project_id, environment_id, error_count, fake_error_count, pool_id, integrated, project_id, environment_id, error_count, fake_error_count,
pending_count, success_count, assertion_count, assertion_success_count, request_error_rate, pending_count, success_count, assertion_count, assertion_success_count, request_error_rate,
request_pending_rate, request_fake_error_rate, request_pass_rate, assertion_pass_rate, request_pending_rate, request_fake_error_rate, request_pass_rate, assertion_pass_rate,
script_identifier) script_identifier)
@ -653,14 +637,13 @@
#{item.deleted,jdbcType=BIT}, #{item.updateUser,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=BIGINT}, #{item.deleted,jdbcType=BIT}, #{item.updateUser,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=BIGINT},
#{item.startTime,jdbcType=BIGINT}, #{item.endTime,jdbcType=BIGINT}, #{item.requestDuration,jdbcType=BIGINT}, #{item.startTime,jdbcType=BIGINT}, #{item.endTime,jdbcType=BIGINT}, #{item.requestDuration,jdbcType=BIGINT},
#{item.status,jdbcType=VARCHAR}, #{item.triggerMode,jdbcType=VARCHAR}, #{item.runMode,jdbcType=VARCHAR}, #{item.status,jdbcType=VARCHAR}, #{item.triggerMode,jdbcType=VARCHAR}, #{item.runMode,jdbcType=VARCHAR},
#{item.poolId,jdbcType=VARCHAR}, #{item.versionId,jdbcType=VARCHAR}, #{item.integrated,jdbcType=BIT}, #{item.poolId,jdbcType=VARCHAR}, #{item.integrated,jdbcType=BIT}, #{item.projectId,jdbcType=VARCHAR},
#{item.projectId,jdbcType=VARCHAR}, #{item.environmentId,jdbcType=VARCHAR}, #{item.errorCount,jdbcType=BIGINT}, #{item.environmentId,jdbcType=VARCHAR}, #{item.errorCount,jdbcType=BIGINT}, #{item.fakeErrorCount,jdbcType=BIGINT},
#{item.fakeErrorCount,jdbcType=BIGINT}, #{item.pendingCount,jdbcType=BIGINT}, #{item.successCount,jdbcType=BIGINT}, #{item.pendingCount,jdbcType=BIGINT}, #{item.successCount,jdbcType=BIGINT}, #{item.assertionCount,jdbcType=BIGINT},
#{item.assertionCount,jdbcType=BIGINT}, #{item.assertionSuccessCount,jdbcType=BIGINT}, #{item.assertionSuccessCount,jdbcType=BIGINT}, #{item.requestErrorRate,jdbcType=VARCHAR},
#{item.requestErrorRate,jdbcType=VARCHAR}, #{item.requestPendingRate,jdbcType=VARCHAR}, #{item.requestPendingRate,jdbcType=VARCHAR}, #{item.requestFakeErrorRate,jdbcType=VARCHAR},
#{item.requestFakeErrorRate,jdbcType=VARCHAR}, #{item.requestPassRate,jdbcType=VARCHAR}, #{item.requestPassRate,jdbcType=VARCHAR}, #{item.assertionPassRate,jdbcType=VARCHAR},
#{item.assertionPassRate,jdbcType=VARCHAR}, #{item.scriptIdentifier,jdbcType=VARCHAR} #{item.scriptIdentifier,jdbcType=VARCHAR})
)
</foreach> </foreach>
</insert> </insert>
<insert id="batchInsertSelective" parameterType="map"> <insert id="batchInsertSelective" parameterType="map">
@ -721,9 +704,6 @@
<if test="'pool_id'.toString() == column.value"> <if test="'pool_id'.toString() == column.value">
#{item.poolId,jdbcType=VARCHAR} #{item.poolId,jdbcType=VARCHAR}
</if> </if>
<if test="'version_id'.toString() == column.value">
#{item.versionId,jdbcType=VARCHAR}
</if>
<if test="'integrated'.toString() == column.value"> <if test="'integrated'.toString() == column.value">
#{item.integrated,jdbcType=BIT} #{item.integrated,jdbcType=BIT}
</if> </if>

View File

@ -352,7 +352,6 @@ CREATE TABLE IF NOT EXISTS api_scenario_report(
`trigger_mode` VARCHAR(20) NOT NULL COMMENT '触发方式' , `trigger_mode` VARCHAR(20) NOT NULL COMMENT '触发方式' ,
`run_mode` VARCHAR(20) NOT NULL COMMENT '执行模式' , `run_mode` VARCHAR(20) NOT NULL COMMENT '执行模式' ,
`pool_id` VARCHAR(50) NOT NULL COMMENT '资源池' , `pool_id` VARCHAR(50) NOT NULL COMMENT '资源池' ,
`version_id` VARCHAR(50) COMMENT '版本fk' ,
`integrated` BIT(1) NOT NULL DEFAULT 0 COMMENT '是否是集成报告' , `integrated` BIT(1) NOT NULL DEFAULT 0 COMMENT '是否是集成报告' ,
`project_id` VARCHAR(50) NOT NULL COMMENT '项目fk' , `project_id` VARCHAR(50) NOT NULL COMMENT '项目fk' ,
`environment_id` VARCHAR(50) COMMENT '环境' , `environment_id` VARCHAR(50) COMMENT '环境' ,

View File

@ -2,6 +2,7 @@ package io.metersphere.sdk.dto.api.task;
import io.metersphere.sdk.constants.ApiBatchRunMode; import io.metersphere.sdk.constants.ApiBatchRunMode;
import lombok.Data; import lombok.Data;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.io.Serial; import java.io.Serial;
@ -52,4 +53,9 @@ public class ApiRunModeConfigDTO implements Serializable {
public Boolean isParallel() { public Boolean isParallel() {
return StringUtils.equals(runMode, ApiBatchRunMode.PARALLEL.name()); return StringUtils.equals(runMode, ApiBatchRunMode.PARALLEL.name());
} }
public Boolean isIntegratedReport() {
return BooleanUtils.isTrue(integratedReport);
}
} }

View File

@ -33,6 +33,12 @@ public class ExecutionQueue implements Serializable {
*/ */
private Long retryNumber; private Long retryNumber;
/**
* 资源类型 / APICASEPLAN_CASE,PLAN_SCENARIOAPI_SCENARIO
* {@link io.metersphere.sdk.constants.ApiExecuteResourceType}
*/
private String resourceType;
/** /**
* 运行模式配置 * 运行模式配置
*/ */

View File

@ -19,10 +19,4 @@ public class ExecutionQueueDetail implements Serializable {
* 排序 * 排序
*/ */
private Integer sort; private Integer sort;
/**
* 资源类型 / APICASEPLAN_CASE,PLAN_SCENARIOAPI_SCENARIO
* {@link io.metersphere.sdk.constants.ApiExecuteResourceType}
*/
private String resourceType;
} }

View File

@ -3,6 +3,7 @@ package io.metersphere.api.controller;
import io.metersphere.api.service.ApiExecuteService; import io.metersphere.api.service.ApiExecuteService;
import io.metersphere.api.service.definition.ApiReportService; import io.metersphere.api.service.definition.ApiReportService;
import io.metersphere.api.service.scenario.ApiScenarioReportService; import io.metersphere.api.service.scenario.ApiScenarioReportService;
import io.metersphere.sdk.constants.ApiReportStatus;
import io.metersphere.sdk.file.FileRequest; import io.metersphere.sdk.file.FileRequest;
import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.LogUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -43,8 +44,8 @@ public class ApiExecuteResourceController {
LogUtils.info("获取执行脚本: ", key); LogUtils.info("获取执行脚本: ", key);
String script = stringRedisTemplate.opsForValue().get(key); String script = stringRedisTemplate.opsForValue().get(key);
stringRedisTemplate.delete(key); stringRedisTemplate.delete(key);
apiReportService.updateRunningReport(reportId); apiReportService.updateReportStatus(reportId, ApiReportStatus.RERUNNING.name());
apiScenarioReportService.updateRunningReport(reportId); apiScenarioReportService.updateReportStatus(reportId, ApiReportStatus.RERUNNING.name());
return Optional.ofNullable(script).orElse(StringUtils.EMPTY); return Optional.ofNullable(script).orElse(StringUtils.EMPTY);
} }

View File

@ -5,7 +5,9 @@ import io.metersphere.api.dto.response.ApiScenarioBatchOperationResponse;
import io.metersphere.api.dto.scenario.ApiScenarioBatchCopyMoveRequest; import io.metersphere.api.dto.scenario.ApiScenarioBatchCopyMoveRequest;
import io.metersphere.api.dto.scenario.ApiScenarioBatchEditRequest; import io.metersphere.api.dto.scenario.ApiScenarioBatchEditRequest;
import io.metersphere.api.dto.scenario.ApiScenarioBatchRequest; import io.metersphere.api.dto.scenario.ApiScenarioBatchRequest;
import io.metersphere.api.dto.scenario.ApiScenarioBatchRunRequest;
import io.metersphere.api.service.ApiValidateService; import io.metersphere.api.service.ApiValidateService;
import io.metersphere.api.service.scenario.ApiScenarioBatchRunService;
import io.metersphere.api.service.scenario.ApiScenarioNoticeService; import io.metersphere.api.service.scenario.ApiScenarioNoticeService;
import io.metersphere.api.service.scenario.ApiScenarioService; import io.metersphere.api.service.scenario.ApiScenarioService;
import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.HttpMethodConstants;
@ -33,6 +35,8 @@ public class ApiScenarioBatchOperationController {
private ApiValidateService apiValidateService; private ApiValidateService apiValidateService;
@Resource @Resource
private ApiScenarioService apiScenarioService; private ApiScenarioService apiScenarioService;
@Resource
private ApiScenarioBatchRunService apiScenarioBatchRunService;
@PostMapping("/batch-operation/edit") @PostMapping("/batch-operation/edit")
@Operation(summary = "接口测试-接口场景批量操作-批量编辑") @Operation(summary = "接口测试-接口场景批量操作-批量编辑")
@ -93,4 +97,11 @@ public class ApiScenarioBatchOperationController {
return apiScenarioService.batchCopy(request, new LogInsertModule(SessionUtils.getUserId(), "/api/scenario/batch-operation/copy", HttpMethodConstants.POST.name())); return apiScenarioService.batchCopy(request, new LogInsertModule(SessionUtils.getUserId(), "/api/scenario/batch-operation/copy", HttpMethodConstants.POST.name()));
} }
@PostMapping("/batch-operation/run")
@Operation(summary = "接口测试-接口场景批量操作-场景列表操作-批量执行")
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_EXECUTE)
public void batchRun(@Validated @RequestBody ApiScenarioBatchRunRequest request) {
apiScenarioBatchRunService.asyncBatchRun(request, SessionUtils.getUserId());
}
} }

View File

@ -0,0 +1,40 @@
package io.metersphere.api.dto;
import io.metersphere.sdk.constants.ApiBatchRunMode;
import io.metersphere.system.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serializable;
/**
* @Author: jianxing
* @CreateTime: 2024-03-18 10:49
*/
@Data
public class ApiRunModeRequest implements Serializable {
private static final long serialVersionUID = 1L;
@EnumValue(enumClass = ApiBatchRunMode.class)
@Schema(description = "运行模式(SERIAL 串行/ PARALLEL并行)")
@NotBlank
private String runMode;
@Schema(description = "是否是集成报告")
private Boolean integratedReport;
@Schema(description = "集合报告名称")
private String integratedReportName;
@Schema(description = "失败停止")
private Boolean stopOnFailure = false;
@Schema(description = "资源池ID")
private String poolId;
@Schema(description = "是否为环境组")
private Boolean grouped = false;
@Schema(description = "环境或者环境组ID")
private String environmentId;
}

View File

@ -1,10 +1,8 @@
package io.metersphere.api.dto.definition; package io.metersphere.api.dto.definition;
import io.metersphere.sdk.constants.ApiBatchRunMode; import io.metersphere.api.dto.ApiRunModeRequest;
import io.metersphere.system.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -24,30 +22,4 @@ public class ApiTestCaseBatchRunRequest extends ApiTestCaseBatchRequest implemen
@Valid @Valid
@Schema(description = "运行模式配置") @Schema(description = "运行模式配置")
private ApiRunModeRequest runModeConfig; private ApiRunModeRequest runModeConfig;
@Data
public static class ApiRunModeRequest {
@EnumValue(enumClass = ApiBatchRunMode.class)
@Schema(description = "运行模式(SERIAL 串行/ PARALLEL并行)")
@NotBlank
private String runMode;
@Schema(description = "是否是集成报告")
private Boolean integratedReport;
@Schema(description = "集合报告名称")
private String integratedReportName;
@Schema(description = "失败停止")
private Boolean stopOnFailure = false;
@Schema(description = "资源池ID")
private String poolId;
@Schema(description = "是否为环境组")
private Boolean grouped = false;
@Schema(description = "环境或者环境组ID")
private String environmentId;
}
} }

View File

@ -0,0 +1,20 @@
package io.metersphere.api.dto.scenario;
import io.metersphere.api.dto.ApiRunModeRequest;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
@Data
@EqualsAndHashCode(callSuper = false)
public class ApiScenarioBatchRunRequest extends ApiScenarioBatchRequest implements Serializable {
private static final long serialVersionUID = 1L;
@Valid
@Schema(description = "运行模式配置")
private ApiRunModeRequest runModeConfig;
}

View File

@ -4,7 +4,9 @@ import io.metersphere.api.event.ApiEventSource;
import io.metersphere.api.service.ApiReportSendNoticeService; import io.metersphere.api.service.ApiReportSendNoticeService;
import io.metersphere.api.service.definition.ApiTestCaseBatchRunService; import io.metersphere.api.service.definition.ApiTestCaseBatchRunService;
import io.metersphere.api.service.queue.ApiExecutionQueueService; import io.metersphere.api.service.queue.ApiExecutionQueueService;
import io.metersphere.api.service.scenario.ApiScenarioBatchRunService;
import io.metersphere.sdk.constants.ApiExecuteResourceType; import io.metersphere.sdk.constants.ApiExecuteResourceType;
import io.metersphere.sdk.constants.ApiReportStatus;
import io.metersphere.sdk.constants.ApplicationScope; import io.metersphere.sdk.constants.ApplicationScope;
import io.metersphere.sdk.constants.KafkaTopicConstants; import io.metersphere.sdk.constants.KafkaTopicConstants;
import io.metersphere.sdk.dto.api.notice.ApiNoticeDTO; import io.metersphere.sdk.dto.api.notice.ApiNoticeDTO;
@ -34,6 +36,8 @@ public class MessageListener {
private ApiExecutionQueueService apiExecutionQueueService; private ApiExecutionQueueService apiExecutionQueueService;
@Resource @Resource
private ApiTestCaseBatchRunService apiTestCaseBatchRunService; private ApiTestCaseBatchRunService apiTestCaseBatchRunService;
@Resource
private ApiScenarioBatchRunService apiScenarioBatchRunService;
@KafkaListener(id = MESSAGE_CONSUME_ID, topics = KafkaTopicConstants.API_REPORT_TASK_TOPIC, groupId = MESSAGE_CONSUME_ID) @KafkaListener(id = MESSAGE_CONSUME_ID, topics = KafkaTopicConstants.API_REPORT_TASK_TOPIC, groupId = MESSAGE_CONSUME_ID)
public void messageConsume(ConsumerRecord<?, String> record) { public void messageConsume(ConsumerRecord<?, String> record) {
@ -72,10 +76,18 @@ public class MessageListener {
if (queue == null || BooleanUtils.isTrue(queue.getRunModeConfig().isParallel())) { if (queue == null || BooleanUtils.isTrue(queue.getRunModeConfig().isParallel())) {
return; return;
} }
ApiExecuteResourceType resourceType = EnumValidator.validateEnum(ApiExecuteResourceType.class, queue.getResourceType());
if (BooleanUtils.isTrue(queue.getRunModeConfig().getStopOnFailure()) && StringUtils.equals(dto.getReportStatus(), ApiReportStatus.ERROR.name())) {
// 如果是失败停止清空队列不继续执行
apiExecutionQueueService.deleteQueue(queue.getQueueId());
return;
}
ExecutionQueueDetail nextDetail = apiExecutionQueueService.getNextDetail(dto.getQueueId()); ExecutionQueueDetail nextDetail = apiExecutionQueueService.getNextDetail(dto.getQueueId());
ApiExecuteResourceType resourceType = EnumValidator.validateEnum(ApiExecuteResourceType.class, nextDetail.getResourceType());
switch (resourceType) { switch (resourceType) {
case API_CASE -> apiTestCaseBatchRunService.executeNextTask(queue, nextDetail); case API_CASE -> apiTestCaseBatchRunService.executeNextTask(queue, nextDetail);
case API_SCENARIO -> apiScenarioBatchRunService.executeNextTask(queue, nextDetail);
default -> { default -> {
} }
} }

View File

@ -44,7 +44,9 @@ public class DocumentAssertionConverter extends ResponseBodyTypeAssertionConvert
} }
private <T extends TestElement> List<T> parseAssertion(MsDocumentAssertionElement assertion, boolean globalEnable, T t) { private <T extends TestElement> List<T> parseAssertion(MsDocumentAssertionElement assertion, boolean globalEnable, T t) {
if (assertion == null) {
return List.of();
}
List<T> list = new LinkedList<>(); List<T> list = new LinkedList<>();
Map<String, ElementCondition> conditionMap = new java.util.HashMap<>(); Map<String, ElementCondition> conditionMap = new java.util.HashMap<>();
List<MsDocumentAssertionElement> dataList = new ArrayList<>(); List<MsDocumentAssertionElement> dataList = new ArrayList<>();

View File

@ -34,7 +34,7 @@ public class RegexExtractConverter extends ExtractConverter<RegexExtract> {
} }
private String getTemplate(String expressionMatchingRule) { private String getTemplate(String expressionMatchingRule) {
// $1$提取 JSON 响应中的第一个匹配项 $0$用于提取整个 JSON 响应 // $1$提取 JSON 响应中的第一个匹配项 $1$用于提取整个 JSON 响应
HashMap<String, String> ruleValueMap = new HashMap<>() {{ HashMap<String, String> ruleValueMap = new HashMap<>() {{
put(RegexExtract.ExpressionRuleType.EXPRESSION.name(), "$0$"); put(RegexExtract.ExpressionRuleType.EXPRESSION.name(), "$0$");
put(RegexExtract.ExpressionRuleType.GROUP.name(), "$1$"); put(RegexExtract.ExpressionRuleType.GROUP.name(), "$1$");

View File

@ -0,0 +1,52 @@
package io.metersphere.api.service;
import io.metersphere.api.service.queue.ApiExecutionQueueService;
import io.metersphere.sdk.constants.ApiExecuteResourceType;
import io.metersphere.sdk.dto.api.task.ApiRunModeConfigDTO;
import io.metersphere.sdk.dto.queue.ExecutionQueue;
import io.metersphere.sdk.dto.queue.ExecutionQueueDetail;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
@Service
@Transactional(rollbackFor = Exception.class)
public class ApiBatchRunBaseService {
@Resource
private ApiExecutionQueueService apiExecutionQueueService;
/**
* 初始化执行队列
*
* @param resourceIds
* @param runModeConfig
* @return
*/
public ExecutionQueue initExecutionqueue(List<String> resourceIds, ApiRunModeConfigDTO runModeConfig, String userId) {
ExecutionQueue queue = getExecutionQueue(runModeConfig, userId);
List<ExecutionQueueDetail> queueDetails = new ArrayList<>();
AtomicInteger sort = new AtomicInteger(1);
for (String resourceId : resourceIds) {
ExecutionQueueDetail queueDetail = new ExecutionQueueDetail();
queueDetail.setResourceId(resourceId);
queueDetail.setSort(sort.getAndIncrement());
queueDetails.add(queueDetail);
}
apiExecutionQueueService.insertQueue(queue, queueDetails);
return queue;
}
private ExecutionQueue getExecutionQueue(ApiRunModeConfigDTO runModeConfig, String userId) {
ExecutionQueue queue = new ExecutionQueue();
queue.setQueueId(UUID.randomUUID().toString());
queue.setRunModeConfig(runModeConfig);
queue.setResourceType(ApiExecuteResourceType.API_SCENARIO.name());
queue.setCreateTime(System.currentTimeMillis());
queue.setUserId(userId);
return queue;
}
}

View File

@ -238,6 +238,9 @@ public class ApiCommonService {
List<MsProcessor> processors = new ArrayList<>(); List<MsProcessor> processors = new ArrayList<>();
for (MsCommonElement commonElement : commonElements) { for (MsCommonElement commonElement : commonElements) {
if (commonElement.getPreProcessorConfig() == null) {
continue;
}
processors.addAll(commonElement.getPreProcessorConfig().getProcessors()); processors.addAll(commonElement.getPreProcessorConfig().getProcessors());
processors.addAll(commonElement.getPostProcessorConfig().getProcessors()); processors.addAll(commonElement.getPostProcessorConfig().getProcessors());
} }

View File

@ -150,6 +150,9 @@ public class ApiExecuteService {
stringRedisTemplate.opsForValue().set(scriptRedisKey, executeScript); stringRedisTemplate.opsForValue().set(scriptRedisKey, executeScript);
if (StringUtils.equals(taskRequest.getRunMode(), ApiExecuteRunMode.FRONTEND_DEBUG.name())) { if (StringUtils.equals(taskRequest.getRunMode(), ApiExecuteRunMode.FRONTEND_DEBUG.name())) {
// 清空mino和kafka配置信息避免前端获取
taskRequest.setMinioConfig(null);
taskRequest.setKafkaConfig(null);
// 前端调试返回执行参数由前端调用本地资源池执行 // 前端调试返回执行参数由前端调用本地资源池执行
return taskRequest; return taskRequest;
} }

View File

@ -222,10 +222,10 @@ public class ApiReportService {
* 更新执行中的用例报告 * 更新执行中的用例报告
* @param reportId * @param reportId
*/ */
public void updateRunningReport(String reportId) { public void updateReportStatus(String reportId, String status) {
ApiReport apiReport = new ApiReport(); ApiReport apiReport = new ApiReport();
apiReport.setId(reportId); apiReport.setId(reportId);
apiReport.setStatus(ApiReportStatus.RUNNING.name()); apiReport.setStatus(status);
apiReport.setUpdateTime(System.currentTimeMillis()); apiReport.setUpdateTime(System.currentTimeMillis());
apiReportMapper.updateByPrimaryKeySelective(apiReport); apiReportMapper.updateByPrimaryKeySelective(apiReport);
} }

View File

@ -7,6 +7,7 @@ import io.metersphere.api.dto.definition.ApiTestCaseBatchRunRequest;
import io.metersphere.api.mapper.ApiTestCaseBlobMapper; import io.metersphere.api.mapper.ApiTestCaseBlobMapper;
import io.metersphere.api.mapper.ApiTestCaseMapper; import io.metersphere.api.mapper.ApiTestCaseMapper;
import io.metersphere.api.mapper.ExtApiTestCaseMapper; import io.metersphere.api.mapper.ExtApiTestCaseMapper;
import io.metersphere.api.service.ApiBatchRunBaseService;
import io.metersphere.api.service.ApiExecuteService; import io.metersphere.api.service.ApiExecuteService;
import io.metersphere.api.service.queue.ApiExecutionQueueService; import io.metersphere.api.service.queue.ApiExecutionQueueService;
import io.metersphere.api.service.queue.ApiExecutionSetService; import io.metersphere.api.service.queue.ApiExecutionSetService;
@ -61,6 +62,8 @@ public class ApiTestCaseBatchRunService {
private ApiExecutionSetService apiExecutionSetService; private ApiExecutionSetService apiExecutionSetService;
@Resource @Resource
private ApiReportService apiReportService; private ApiReportService apiReportService;
@Resource
private ApiBatchRunBaseService apiBatchRunBaseService;
/** /**
* 异步批量执行 * 异步批量执行
@ -97,11 +100,11 @@ public class ApiTestCaseBatchRunService {
List<String> ids = apiTestCaseService.doSelectIds(request, false); List<String> ids = apiTestCaseService.doSelectIds(request, false);
ApiRunModeConfigDTO runModeConfig = getRunModeConfig(request); ApiRunModeConfigDTO runModeConfig = getRunModeConfig(request);
// 初始化集成报告 // 初始化集成报告
if (isIntegratedReport(runModeConfig)) { if (runModeConfig.isIntegratedReport()) {
initIntegratedReport(runModeConfig, ids, userId, request.getProjectId()); initIntegratedReport(runModeConfig, ids, userId, request.getProjectId());
} }
// 先初始化集成报告设置好报告ID再初始化执行队列 // 先初始化集成报告设置好报告ID再初始化执行队列
ExecutionQueue queue = initExecutionqueue(ids, runModeConfig, userId); ExecutionQueue queue = apiBatchRunBaseService.initExecutionqueue(ids, runModeConfig, userId);
// 执行第一个任务 // 执行第一个任务
ExecutionQueueDetail nextDetail = apiExecutionQueueService.getNextDetail(queue.getQueueId()); ExecutionQueueDetail nextDetail = apiExecutionQueueService.getNextDetail(queue.getQueueId());
executeNextTask(queue, nextDetail); executeNextTask(queue, nextDetail);
@ -117,14 +120,15 @@ public class ApiTestCaseBatchRunService {
ApiRunModeConfigDTO runModeConfig = getRunModeConfig(request); ApiRunModeConfigDTO runModeConfig = getRunModeConfig(request);
if (isIntegratedReport(runModeConfig)) { if (runModeConfig.isIntegratedReport()) {
// 初始化集成报告 // 初始化集成报告
ApiReport apiReport = initIntegratedReport(runModeConfig, ids, userId, request.getProjectId()); ApiReport apiReport = initIntegratedReport(runModeConfig, ids, userId, request.getProjectId());
// 集成报告才需要初始化执行队列用于统计整体执行情况 // 集成报告才需要初始化执行集合用于统计整体执行情况
apiExecutionSetService.initSet(apiReport.getId(), ids); apiExecutionSetService.initSet(apiReport.getId(), ids);
} }
AtomicInteger errorCount = new AtomicInteger(); AtomicInteger errorCount = new AtomicInteger();
AtomicLong sort = new AtomicLong(1);
// 分批处理 // 分批处理
SubListUtils.dealForSubList(ids, 100, subIds -> { SubListUtils.dealForSubList(ids, 100, subIds -> {
@ -141,10 +145,10 @@ public class ApiTestCaseBatchRunService {
Map<String, ApiTestCaseBlob> apiTestCaseBlobMap = apiTestCaseBlobMapper.selectByExampleWithBLOBs(example).stream() Map<String, ApiTestCaseBlob> apiTestCaseBlobMap = apiTestCaseBlobMapper.selectByExampleWithBLOBs(example).stream()
.collect(Collectors.toMap(ApiTestCaseBlob::getId, Function.identity())); .collect(Collectors.toMap(ApiTestCaseBlob::getId, Function.identity()));
if (isIntegratedReport(runModeConfig)) { if (runModeConfig.isIntegratedReport()) {
// 获取集成报告ID // 获取集成报告ID
integratedReportId = runModeConfig.getCollectionReport().getReportId(); integratedReportId = runModeConfig.getCollectionReport().getReportId();
initApiReportSteps(ids, apiCaseMap, integratedReportId); initApiReportSteps(subIds, apiCaseMap, integratedReportId, sort);
} else { } else {
// 初始化非集成报告 // 初始化非集成报告
List<ApiTestCaseRecord> apiTestCaseRecords = initApiReport(runModeConfig, apiTestCases, userId); List<ApiTestCaseRecord> apiTestCaseRecords = initApiReport(runModeConfig, apiTestCases, userId);
@ -160,16 +164,16 @@ public class ApiTestCaseBatchRunService {
ApiTestCaseBlob apiTestCaseBlob = apiTestCaseBlobMap.get(id); ApiTestCaseBlob apiTestCaseBlob = apiTestCaseBlobMap.get(id);
if (apiTestCase == null) { if (apiTestCase == null) {
if (isIntegratedReport(runModeConfig)) { if (runModeConfig.isIntegratedReport()) {
// 用例不存在则在执行集合中删除 // 用例不存在则在执行集合中删除
apiExecutionSetService.removeItem(integratedReportId, id); apiExecutionSetService.removeItem(integratedReportId, id);
} }
LogUtils.info("当前执行任务的用例已删除 {}", apiTestCase.getId()); LogUtils.info("当前执行任务的用例已删除 {}", id);
break; break;
} }
// 如果是集成报告则生成唯一的虚拟ID非集成报告使用单用例的报告ID // 如果是集成报告则生成唯一的虚拟ID非集成报告使用单用例的报告ID
reportId = isIntegratedReport(runModeConfig) ? UUID.randomUUID().toString() : caseReportMap.get(id); reportId = runModeConfig.isIntegratedReport() ? UUID.randomUUID().toString() : caseReportMap.get(id);
TaskRequestDTO taskRequest = getTaskRequestDTO(reportId, apiTestCase, runModeConfig); TaskRequestDTO taskRequest = getTaskRequestDTO(reportId, apiTestCase, runModeConfig);
execute(taskRequest, apiTestCase, apiTestCaseBlob); execute(taskRequest, apiTestCase, apiTestCaseBlob);
} catch (Exception e) { } catch (Exception e) {
@ -191,8 +195,7 @@ public class ApiTestCaseBatchRunService {
* @param apiCaseMap * @param apiCaseMap
* @param reportId * @param reportId
*/ */
private void initApiReportSteps(List<String> ids, Map<String, ApiTestCase> apiCaseMap, String reportId) { private void initApiReportSteps(List<String> ids, Map<String, ApiTestCase> apiCaseMap, String reportId, AtomicLong sort) {
AtomicLong sort = new AtomicLong(1);
List<ApiReportStep> apiReportSteps = ids.stream() List<ApiReportStep> apiReportSteps = ids.stream()
.map(id -> getApiReportStep(apiCaseMap.get(id), reportId, sort.getAndIncrement())) .map(id -> getApiReportStep(apiCaseMap.get(id), reportId, sort.getAndIncrement()))
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -219,17 +222,13 @@ public class ApiTestCaseBatchRunService {
private ApiRunModeConfigDTO getRunModeConfig(ApiTestCaseBatchRunRequest request) { private ApiRunModeConfigDTO getRunModeConfig(ApiTestCaseBatchRunRequest request) {
ApiRunModeConfigDTO runModeConfig = BeanUtils.copyBean(new ApiRunModeConfigDTO(), request.getRunModeConfig()); ApiRunModeConfigDTO runModeConfig = BeanUtils.copyBean(new ApiRunModeConfigDTO(), request.getRunModeConfig());
if (StringUtils.isNotBlank(request.getRunModeConfig().getIntegratedReportName()) && isIntegratedReport(runModeConfig)) { if (StringUtils.isNotBlank(request.getRunModeConfig().getIntegratedReportName()) && runModeConfig.isIntegratedReport()) {
runModeConfig.setCollectionReport(new CollectionReportDTO()); runModeConfig.setCollectionReport(new CollectionReportDTO());
runModeConfig.getCollectionReport().setReportName(request.getRunModeConfig().getIntegratedReportName()); runModeConfig.getCollectionReport().setReportName(request.getRunModeConfig().getIntegratedReportName());
} }
return runModeConfig; return runModeConfig;
} }
private boolean isIntegratedReport(ApiRunModeConfigDTO runModeConfig) {
return BooleanUtils.isTrue(runModeConfig.getIntegratedReport());
}
/** /**
* 预生成用例的执行报告 * 预生成用例的执行报告
* *
@ -248,7 +247,7 @@ public class ApiTestCaseBatchRunService {
record.setApiReportId(apiReport.getId()); record.setApiReportId(apiReport.getId());
record.setApiTestCaseId(id); record.setApiTestCaseId(id);
return record; return record;
}).collect(Collectors.toList()); }).toList();
apiReportService.insertApiReport(List.of(apiReport), records); apiReportService.insertApiReport(List.of(apiReport), records);
// 设置集成报告执行参数 // 设置集成报告执行参数
runModeConfig.getCollectionReport().setReportId(apiReport.getId()); runModeConfig.getCollectionReport().setReportId(apiReport.getId());
@ -274,7 +273,7 @@ public class ApiTestCaseBatchRunService {
} }
String reportId; String reportId;
if (isIntegratedReport(runModeConfig)) { if (runModeConfig.isIntegratedReport()) {
String integratedReportId = runModeConfig.getCollectionReport().getReportId(); String integratedReportId = runModeConfig.getCollectionReport().getReportId();
initApiReportSteps(apiTestCase, integratedReportId, queueDetail.getSort()); initApiReportSteps(apiTestCase, integratedReportId, queueDetail.getSort());
reportId = UUID.randomUUID().toString(); reportId = UUID.randomUUID().toString();
@ -363,35 +362,4 @@ public class ApiTestCaseBatchRunService {
public String getEnvId(ApiRunModeConfigDTO runModeConfig, ApiTestCase apiTestCase) { public String getEnvId(ApiRunModeConfigDTO runModeConfig, ApiTestCase apiTestCase) {
return StringUtils.isBlank(runModeConfig.getEnvironmentId()) ? apiTestCase.getEnvironmentId() : runModeConfig.getEnvironmentId(); return StringUtils.isBlank(runModeConfig.getEnvironmentId()) ? apiTestCase.getEnvironmentId() : runModeConfig.getEnvironmentId();
} }
/**
* 初始化执行队列
*
* @param resourceIds
* @param runModeConfig
* @return
*/
private ExecutionQueue initExecutionqueue(List<String> resourceIds, ApiRunModeConfigDTO runModeConfig, String userId) {
ExecutionQueue queue = getExecutionQueue(runModeConfig, userId);
List<ExecutionQueueDetail> queueDetails = new ArrayList<>();
AtomicInteger sort = new AtomicInteger(0);
for (String resourceId : resourceIds) {
ExecutionQueueDetail queueDetail = new ExecutionQueueDetail();
queueDetail.setResourceType(ApiExecuteResourceType.API_CASE.name());
queueDetail.setResourceId(resourceId);
queueDetail.setSort(sort.getAndIncrement());
queueDetails.add(queueDetail);
}
apiExecutionQueueService.insertQueue(queue, queueDetails);
return queue;
}
private ExecutionQueue getExecutionQueue(ApiRunModeConfigDTO runModeConfig, String userId) {
ExecutionQueue queue = new ExecutionQueue();
queue.setQueueId(UUID.randomUUID().toString());
queue.setRunModeConfig(runModeConfig);
queue.setCreateTime(System.currentTimeMillis());
queue.setUserId(userId);
return queue;
}
} }

View File

@ -53,19 +53,22 @@ public class ApiExecutionQueueService {
Long size = size(queueId); Long size = size(queueId);
if (size == null || size == 0) { if (size == null || size == 0) {
// 最后一个节点清理队列 // 最后一个节点清理队列
redisTemplate.delete(queueKey); deleteQueue(queueId);
redisTemplate.delete(QUEUE_PREFIX + queueId);
} }
return JSON.parseObject(queueDetail, ExecutionQueueDetail.class); return JSON.parseObject(queueDetail, ExecutionQueueDetail.class);
} }
// 整体获取完清理队列 // 整体获取完清理队列
redisTemplate.delete(queueKey); deleteQueue(queueId);
redisTemplate.delete(QUEUE_PREFIX + queueId);
return null; return null;
} }
public void deleteQueue(String queueId) {
redisTemplate.delete(QUEUE_DETAIL_PREFIX + queueId);
redisTemplate.delete(QUEUE_PREFIX + queueId);
}
/** /**
* 获取所有节点 * 获取所有节点
*/ */

View File

@ -0,0 +1,332 @@
package io.metersphere.api.service.scenario;
import io.metersphere.api.constants.ApiScenarioStepRefType;
import io.metersphere.api.domain.ApiScenario;
import io.metersphere.api.domain.ApiScenarioRecord;
import io.metersphere.api.domain.ApiScenarioReport;
import io.metersphere.api.domain.ApiScenarioReportStep;
import io.metersphere.api.dto.ApiScenarioParamConfig;
import io.metersphere.api.dto.ApiScenarioParseTmpParam;
import io.metersphere.api.dto.debug.ApiResourceRunRequest;
import io.metersphere.api.dto.request.MsScenario;
import io.metersphere.api.dto.scenario.ApiScenarioBatchRunRequest;
import io.metersphere.api.dto.scenario.ApiScenarioDetail;
import io.metersphere.api.dto.scenario.ApiScenarioParseParam;
import io.metersphere.api.service.ApiBatchRunBaseService;
import io.metersphere.api.service.ApiExecuteService;
import io.metersphere.api.service.queue.ApiExecutionQueueService;
import io.metersphere.api.service.queue.ApiExecutionSetService;
import io.metersphere.sdk.constants.ApiBatchRunMode;
import io.metersphere.sdk.constants.ApiExecuteResourceType;
import io.metersphere.sdk.constants.ApiExecuteRunMode;
import io.metersphere.sdk.constants.TaskTriggerMode;
import io.metersphere.sdk.dto.api.task.ApiRunModeConfigDTO;
import io.metersphere.sdk.dto.api.task.CollectionReportDTO;
import io.metersphere.sdk.dto.api.task.TaskRequestDTO;
import io.metersphere.sdk.dto.queue.ExecutionQueue;
import io.metersphere.sdk.dto.queue.ExecutionQueueDetail;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class ApiScenarioBatchRunService {
@Resource
private ApiScenarioService apiScenarioService;
@Resource
private ApiExecuteService apiExecuteService;
@Resource
private ApiExecutionQueueService apiExecutionQueueService;
@Resource
private ApiExecutionSetService apiExecutionSetService;
@Resource
private ApiScenarioReportService apiScenarioReportService;
@Resource
private ApiBatchRunBaseService apiBatchRunBaseService;
/**
* 异步批量执行
*
* @param request
* @param userId
*/
public void asyncBatchRun(ApiScenarioBatchRunRequest request, String userId) {
Thread.startVirtualThread(() -> batchRun(request, userId));
}
/**
* 批量执行
*
* @param request
* @param userId
*/
private void batchRun(ApiScenarioBatchRunRequest request, String userId) {
try {
if (StringUtils.equals(request.getRunModeConfig().getRunMode(), ApiBatchRunMode.PARALLEL.name())) {
parallelExecute(request, userId);
} else {
serialExecute(request, userId);
}
} catch (Exception e) {
LogUtils.error("批量执行用例失败: ", e);
}
}
/**
* 串行批量执行
*
* @param request
*/
public void serialExecute(ApiScenarioBatchRunRequest request, String userId) throws Exception {
List<String> ids = apiScenarioService.doSelectIds(request, false);
ApiRunModeConfigDTO runModeConfig = getRunModeConfig(request);
// 初始化集成报告
if (runModeConfig.isIntegratedReport()) {
initIntegratedReport(runModeConfig, ids, userId, request.getProjectId());
}
// 先初始化集成报告设置好报告ID再初始化执行队列
ExecutionQueue queue = apiBatchRunBaseService.initExecutionqueue(ids, runModeConfig, userId);
// 执行第一个任务
ExecutionQueueDetail nextDetail = apiExecutionQueueService.getNextDetail(queue.getQueueId());
executeNextTask(queue, nextDetail);
}
/**
* 并行批量执行
*
* @param request
*/
public void parallelExecute(ApiScenarioBatchRunRequest request, String userId) {
List<String> ids = apiScenarioService.doSelectIds(request, false);
ApiRunModeConfigDTO runModeConfig = getRunModeConfig(request);
if (runModeConfig.isIntegratedReport()) {
// 初始化集成报告
ApiScenarioReport apiScenarioReport = initIntegratedReport(runModeConfig, ids, userId, request.getProjectId());
// 集成报告才需要初始化执行集合用于统计整体执行情况
apiExecutionSetService.initSet(apiScenarioReport.getId(), ids);
}
AtomicInteger errorCount = new AtomicInteger();
AtomicInteger sort = new AtomicInteger(1);
// 这里ID顺序和队列的ID顺序保持一致
for (String id : ids) {
String reportId = IDGenerator.nextStr();
try {
ApiScenarioDetail apiScenarioDetail = apiScenarioService.get(id);
if (apiScenarioDetail == null) {
if (runModeConfig.isIntegratedReport()) {
// 用例不存在则在执行集合中删除
apiExecutionSetService.removeItem(runModeConfig.getCollectionReport().getReportId(), id);
}
LogUtils.info("当前执行任务的用例已删除 {}", id);
break;
}
TaskRequestDTO taskRequest = getTaskRequestDTO(reportId, apiScenarioDetail, runModeConfig);
execute(taskRequest, apiScenarioDetail, userId, sort.getAndIncrement());
} catch (Exception e) {
LogUtils.error("执行用例失败 {}-{}", reportId, id);
LogUtils.error(e);
if (errorCount.getAndIncrement() > 10) {
LogUtils.error("批量执行用例失败错误次数超过10次停止执行");
return;
}
}
}
}
/**
* 初始化集成报告的报告步骤
*/
private void initIntegratedReportSteps(ApiScenarioDetail apiScenarioDetail, String reportId, long sort) {
// 将当前场景生成一级报告步骤
ApiScenarioReportStep apiScenarioReportStep = getApiScenarioReportStep(apiScenarioDetail, reportId, sort);
// 初始化报告步骤
List<ApiScenarioReportStep> scenarioReportSteps = apiScenarioService.getScenarioReportSteps(apiScenarioReportStep.getStepId(), apiScenarioDetail.getSteps(), reportId);
scenarioReportSteps.addFirst(apiScenarioReportStep);
apiScenarioReportService.insertApiScenarioReportStep(scenarioReportSteps);
}
private ApiScenarioReportStep getApiScenarioReportStep(ApiScenario apiScenario, String reportId, long sort) {
ApiScenarioReportStep apiReportStep = new ApiScenarioReportStep();
apiReportStep.setReportId(reportId);
apiReportStep.setStepId(apiScenario.getId());
apiReportStep.setSort(sort);
apiReportStep.setName(apiScenario.getName());
apiReportStep.setStepType(ApiExecuteResourceType.API_SCENARIO.name());
return apiReportStep;
}
private ApiRunModeConfigDTO getRunModeConfig(ApiScenarioBatchRunRequest request) {
ApiRunModeConfigDTO runModeConfig = BeanUtils.copyBean(new ApiRunModeConfigDTO(), request.getRunModeConfig());
if (StringUtils.isNotBlank(request.getRunModeConfig().getIntegratedReportName()) && runModeConfig.isIntegratedReport()) {
runModeConfig.setCollectionReport(new CollectionReportDTO());
runModeConfig.getCollectionReport().setReportName(request.getRunModeConfig().getIntegratedReportName());
}
return runModeConfig;
}
/**
* 预生成用例的执行报告
*
* @param runModeConfig
* @param ids
* @return
*/
private ApiScenarioReport initIntegratedReport(ApiRunModeConfigDTO runModeConfig, List<String> ids, String userId, String projectId) {
ApiScenarioReport apiScenarioReport = getScenarioReport(runModeConfig, userId);
apiScenarioReport.setName(runModeConfig.getCollectionReport().getReportName());
apiScenarioReport.setIntegrated(true);
apiScenarioReport.setProjectId(projectId);
// 初始化集成报告与用例的关联关系
List<ApiScenarioRecord> records = ids.stream().map(id -> {
ApiScenarioRecord scenarioRecord = new ApiScenarioRecord();
scenarioRecord.setApiScenarioReportId(apiScenarioReport.getId());
scenarioRecord.setApiScenarioId(id);
return scenarioRecord;
}).toList();
apiScenarioReportService.insertApiScenarioReport(List.of(apiScenarioReport), records);
// 设置集成报告执行参数
runModeConfig.getCollectionReport().setReportId(apiScenarioReport.getId());
return apiScenarioReport;
}
/**
* 执行串行的下一个任务
*
* @param queue
* @param queueDetail
*/
public void executeNextTask(ExecutionQueue queue, ExecutionQueueDetail queueDetail) {
ApiScenarioDetail apiScenarioDetail = apiScenarioService.get(queueDetail.getResourceId());
if (apiScenarioDetail == null) {
LogUtils.info("当前执行任务的用例已删除 {}", queueDetail.getResourceId());
return;
}
TaskRequestDTO taskRequest = getTaskRequestDTO(IDGenerator.nextStr(), apiScenarioDetail, queue.getRunModeConfig());
taskRequest.setQueueId(queue.getQueueId());
execute(taskRequest, apiScenarioDetail, queue.getUserId(), queueDetail.getSort());
}
/**
* 执行批量的单个任务
*/
public void execute(TaskRequestDTO taskRequest, ApiScenarioDetail apiScenarioDetail, String userId, int sort) {
ApiRunModeConfigDTO runModeConfig = taskRequest.getRunModeConfig();
String reportId = taskRequest.getReportId();
String envId = getEnvId(runModeConfig, apiScenarioDetail);
boolean envGroup = getEnvGroup(runModeConfig, apiScenarioDetail);
// 解析生成待执行的场景树
MsScenario msScenario = new MsScenario();
msScenario.setRefType(ApiScenarioStepRefType.DIRECT.name());
msScenario.setScenarioConfig(apiScenarioDetail.getScenarioConfig());
msScenario.setProjectId(apiScenarioDetail.getProjectId());
ApiScenarioParseParam parseParam = new ApiScenarioParseParam();
parseParam.setScenarioConfig(apiScenarioDetail.getScenarioConfig());
parseParam.setStepDetails(Map.of());
parseParam.setEnvironmentId(envId);
parseParam.setGrouped(envGroup);
if (runModeConfig.isIntegratedReport()) {
// 初始化集成报告步骤
initIntegratedReportSteps(apiScenarioDetail, runModeConfig.getCollectionReport().getReportId(), sort);
} else {
// 初始化非集成报告
initScenarioReport(reportId, runModeConfig, apiScenarioDetail, userId).getApiScenarioReportId();
// 初始化报告步骤
apiScenarioService.initScenarioReportSteps(apiScenarioDetail.getSteps(), reportId);
}
taskRequest.setReportId(reportId);
ApiScenarioParseTmpParam tmpParam = apiScenarioService.parse(msScenario, apiScenarioDetail.getSteps(), parseParam);
ApiResourceRunRequest runRequest = apiScenarioService.getApiResourceRunRequest(msScenario, tmpParam);
ApiScenarioParamConfig parseConfig = apiScenarioService.getApiScenarioParamConfig(parseParam, tmpParam.getScenarioParseEnvInfo());
parseConfig.setReportId(reportId);
apiExecuteService.execute(runRequest, taskRequest, parseConfig);
}
private TaskRequestDTO getTaskRequestDTO(String reportId, ApiScenarioDetail apiScenarioDetail, ApiRunModeConfigDTO runModeConfig) {
TaskRequestDTO taskRequest = apiScenarioService.getTaskRequest(reportId, apiScenarioDetail.getId(), apiScenarioDetail.getProjectId(), ApiExecuteRunMode.RUN.name());
taskRequest.setSaveResult(true);
taskRequest.setRealTime(false);
taskRequest.setRunModeConfig(runModeConfig);
runModeConfig.setEnvironmentId(getEnvId(runModeConfig, apiScenarioDetail));
runModeConfig.setGrouped(getEnvGroup(runModeConfig, apiScenarioDetail));
return taskRequest;
}
/**
* 预生成用例的执行报告
*
* @param runModeConfig
* @param apiScenario
* @return
*/
public ApiScenarioRecord initScenarioReport(String reportId, ApiRunModeConfigDTO runModeConfig, ApiScenario apiScenario, String userId) {
// 初始化报告
ApiScenarioReport apiScenarioReport = getScenarioReport(runModeConfig, apiScenario, userId);
apiScenarioReport.setId(reportId);
// 创建报告和用例的关联关系
ApiScenarioRecord apiScenarioRecord = apiScenarioService.getApiScenarioRecord(apiScenario, apiScenarioReport);
apiScenarioReportService.insertApiScenarioReport(List.of(apiScenarioReport), List.of(apiScenarioRecord));
return apiScenarioRecord;
}
private ApiScenarioReport getScenarioReport(ApiRunModeConfigDTO runModeConfig, ApiScenario apiScenario, String userId) {
ApiScenarioReport apiScenarioReport = getScenarioReport(runModeConfig, userId);
apiScenarioReport.setEnvironmentId(getEnvId(runModeConfig, apiScenario));
apiScenarioReport.setName(apiScenario.getName());
apiScenarioReport.setProjectId(apiScenario.getProjectId());
apiScenarioReport.setTriggerMode(TaskTriggerMode.BATCH.name());
return apiScenarioReport;
}
public ApiScenarioReport getScenarioReport(ApiRunModeConfigDTO runModeConfig, String userId) {
ApiScenarioReport apiScenarioReport = apiScenarioService.getScenarioReport(userId);
apiScenarioReport.setEnvironmentId(runModeConfig.getEnvironmentId());
apiScenarioReport.setRunMode(runModeConfig.getRunMode());
apiScenarioReport.setPoolId(runModeConfig.getPoolId());
apiScenarioReport.setTriggerMode(TaskTriggerMode.BATCH.name());
return apiScenarioReport;
}
/**
* 获取执行的环境ID
* 优先使用运行配置的环境
* 没有则使用用例自身的环境
*
* @param runModeConfig
* @param apiScenario
* @return
*/
public String getEnvId(ApiRunModeConfigDTO runModeConfig, ApiScenario apiScenario) {
return StringUtils.isBlank(runModeConfig.getEnvironmentId()) ? apiScenario.getEnvironmentId() : runModeConfig.getEnvironmentId();
}
public boolean getEnvGroup(ApiRunModeConfigDTO runModeConfig, ApiScenario apiScenario) {
return StringUtils.isBlank(runModeConfig.getEnvironmentId()) ? apiScenario.getGrouped() : runModeConfig.getGrouped();
}
}

View File

@ -235,10 +235,10 @@ public class ApiScenarioReportService {
* 更新执行中的场景报告 * 更新执行中的场景报告
* @param reportId * @param reportId
*/ */
public void updateRunningReport(String reportId) { public void updateReportStatus(String reportId, String status) {
ApiScenarioReport scenarioReport = new ApiScenarioReport(); ApiScenarioReport scenarioReport = new ApiScenarioReport();
scenarioReport.setId(reportId); scenarioReport.setId(reportId);
scenarioReport.setStatus(ApiReportStatus.RUNNING.name()); scenarioReport.setStatus(status);
scenarioReport.setUpdateTime(System.currentTimeMillis()); scenarioReport.setUpdateTime(System.currentTimeMillis());
apiScenarioReportMapper.updateByPrimaryKeySelective(scenarioReport); apiScenarioReportMapper.updateByPrimaryKeySelective(scenarioReport);
} }

View File

@ -1062,9 +1062,6 @@ public class ApiScenarioService extends MoveNodeService {
ApiScenarioParseTmpParam tmpParam = parse(msScenario, request.getSteps(), request); ApiScenarioParseTmpParam tmpParam = parse(msScenario, request.getSteps(), request);
ApiResourceRunRequest runRequest = getApiResourceRunRequest(msScenario, tmpParam); ApiResourceRunRequest runRequest = getApiResourceRunRequest(msScenario, tmpParam);
runRequest.setRefResourceIds(tmpParam.getRefResourceIds());
runRequest.setRefProjectIds(tmpParam.getRefProjectIds());
runRequest.setTestElement(msScenario);
TaskRequestDTO taskRequest = getTaskRequest(request.getReportId(), request.getId(), request.getProjectId(), TaskRequestDTO taskRequest = getTaskRequest(request.getReportId(), request.getId(), request.getProjectId(),
apiExecuteService.getDebugRunModule(request.getFrontendDebug())); apiExecuteService.getDebugRunModule(request.getFrontendDebug()));
@ -1116,9 +1113,6 @@ public class ApiScenarioService extends MoveNodeService {
ApiScenarioParseTmpParam tmpParam = parse(msScenario, steps, parseParam); ApiScenarioParseTmpParam tmpParam = parse(msScenario, steps, parseParam);
ApiResourceRunRequest runRequest = getApiResourceRunRequest(msScenario, tmpParam); ApiResourceRunRequest runRequest = getApiResourceRunRequest(msScenario, tmpParam);
runRequest.setRefResourceIds(tmpParam.getRefResourceIds());
runRequest.setRefProjectIds(tmpParam.getRefProjectIds());
runRequest.setTestElement(msScenario);
String poolId = apiExecuteService.getProjectApiResourcePoolId(apiScenario.getProjectId()); String poolId = apiExecuteService.getProjectApiResourcePoolId(apiScenario.getProjectId());
@ -1167,7 +1161,7 @@ public class ApiScenarioService extends MoveNodeService {
scenarioReport.setProjectId(apiScenario.getProjectId()); scenarioReport.setProjectId(apiScenario.getProjectId());
// 创建报告和用例的关联关系 // 创建报告和用例的关联关系
ApiScenarioRecord scenarioRecord = getApiTestCaseRecord(apiScenario, scenarioReport); ApiScenarioRecord scenarioRecord = getApiScenarioRecord(apiScenario, scenarioReport);
apiScenarioReportService.insertApiScenarioReport(List.of(scenarioReport), List.of(scenarioRecord)); apiScenarioReportService.insertApiScenarioReport(List.of(scenarioReport), List.of(scenarioRecord));
return scenarioRecord; return scenarioRecord;
@ -1175,11 +1169,12 @@ public class ApiScenarioService extends MoveNodeService {
/** /**
* 初始化场景报告步骤 * 初始化场景报告步骤
*
* @param steps * @param steps
* @param reportId * @param reportId
*/ */
private void initScenarioReportSteps(List<? extends ApiScenarioStepCommonDTO> steps, String reportId) { public void initScenarioReportSteps(List<? extends ApiScenarioStepCommonDTO> steps, String reportId) {
List<ApiScenarioReportStep> scenarioReportSteps = getScenarioReportSteps(steps, reportId); List<ApiScenarioReportStep> scenarioReportSteps = getScenarioReportSteps(null, steps, reportId);
apiScenarioReportService.insertApiScenarioReportStep(scenarioReportSteps); apiScenarioReportService.insertApiScenarioReportStep(scenarioReportSteps);
} }
@ -1189,14 +1184,16 @@ public class ApiScenarioService extends MoveNodeService {
* @param steps * @param steps
* @param reportId * @param reportId
*/ */
private List<ApiScenarioReportStep> getScenarioReportSteps(List<? extends ApiScenarioStepCommonDTO> steps, String reportId) { public List<ApiScenarioReportStep> getScenarioReportSteps(String parentId, List<? extends ApiScenarioStepCommonDTO> steps, String reportId) {
AtomicLong sort = new AtomicLong(1); AtomicLong sort = new AtomicLong(1);
List<ApiScenarioReportStep> scenarioReportSteps = new ArrayList<>(); List<ApiScenarioReportStep> scenarioReportSteps = new ArrayList<>();
for (ApiScenarioStepCommonDTO step : steps) { for (ApiScenarioStepCommonDTO step : steps) {
scenarioReportSteps.add(getScenarioReportStep(step, reportId, sort.getAndIncrement())); ApiScenarioReportStep scenarioReportStep = getScenarioReportStep(step, reportId, sort.getAndIncrement());
scenarioReportStep.setParentId(parentId);
scenarioReportSteps.add(scenarioReportStep);
List<? extends ApiScenarioStepCommonDTO> children = step.getChildren(); List<? extends ApiScenarioStepCommonDTO> children = step.getChildren();
if (CollectionUtils.isNotEmpty(children)) { if (CollectionUtils.isNotEmpty(children)) {
scenarioReportSteps.addAll(getScenarioReportSteps(steps, reportId)); scenarioReportSteps.addAll(getScenarioReportSteps(step.getId(), children, reportId));
} }
} }
return scenarioReportSteps; return scenarioReportSteps;
@ -1208,11 +1205,11 @@ public class ApiScenarioService extends MoveNodeService {
scenarioReportStep.setStepId(step.getId()); scenarioReportStep.setStepId(step.getId());
scenarioReportStep.setSort(sort); scenarioReportStep.setSort(sort);
scenarioReportStep.setName(step.getName()); scenarioReportStep.setName(step.getName());
scenarioReportStep.setStepType(ApiExecuteResourceType.API_CASE.name()); scenarioReportStep.setStepType(step.getStepType());
return scenarioReportStep; return scenarioReportStep;
} }
public ApiScenarioRecord getApiTestCaseRecord(ApiScenario apiScenario, ApiScenarioReport scenarioReport) { public ApiScenarioRecord getApiScenarioRecord(ApiScenario apiScenario, ApiScenarioReport scenarioReport) {
ApiScenarioRecord scenarioRecord = new ApiScenarioRecord(); ApiScenarioRecord scenarioRecord = new ApiScenarioRecord();
scenarioRecord.setApiScenarioId(apiScenario.getId()); scenarioRecord.setApiScenarioId(apiScenario.getId());
scenarioRecord.setApiScenarioReportId(scenarioReport.getId()); scenarioRecord.setApiScenarioReportId(scenarioReport.getId());
@ -1232,7 +1229,7 @@ public class ApiScenarioService extends MoveNodeService {
return scenarioReport; return scenarioReport;
} }
private ApiScenarioParamConfig getApiScenarioParamConfig(ApiScenarioParseParam request, ApiScenarioParseEnvInfo scenarioParseEnvInfo) { public ApiScenarioParamConfig getApiScenarioParamConfig(ApiScenarioParseParam request, ApiScenarioParseEnvInfo scenarioParseEnvInfo) {
ApiScenarioParamConfig parseConfig = new ApiScenarioParamConfig(); ApiScenarioParamConfig parseConfig = new ApiScenarioParamConfig();
parseConfig.setTestElementClassPluginIdMap(apiPluginService.getTestElementPluginMap()); parseConfig.setTestElementClassPluginIdMap(apiPluginService.getTestElementPluginMap());
parseConfig.setTestElementClassProtocalMap(apiPluginService.getTestElementProtocolMap()); parseConfig.setTestElementClassProtocalMap(apiPluginService.getTestElementProtocolMap());
@ -1247,7 +1244,7 @@ public class ApiScenarioService extends MoveNodeService {
return parseConfig; return parseConfig;
} }
private ApiResourceRunRequest getApiResourceRunRequest(MsScenario msScenario, ApiScenarioParseTmpParam tmpParam) { public ApiResourceRunRequest getApiResourceRunRequest(MsScenario msScenario, ApiScenarioParseTmpParam tmpParam) {
ApiResourceRunRequest runRequest = new ApiResourceRunRequest(); ApiResourceRunRequest runRequest = new ApiResourceRunRequest();
runRequest.setRefResourceIds(tmpParam.getRefResourceIds()); runRequest.setRefResourceIds(tmpParam.getRefResourceIds());
runRequest.setRefProjectIds(tmpParam.getRefProjectIds()); runRequest.setRefProjectIds(tmpParam.getRefProjectIds());
@ -1258,6 +1255,7 @@ public class ApiScenarioService extends MoveNodeService {
/** /**
* 将步骤转换成场景树 * 将步骤转换成场景树
* 并保存临时变量 * 并保存临时变量
*
* @param msScenario * @param msScenario
* @param steps * @param steps
* @param parseParam * @param parseParam
@ -1291,7 +1289,7 @@ public class ApiScenarioService extends MoveNodeService {
return tmpParam; return tmpParam;
} }
private TaskRequestDTO getTaskRequest(String reportId, String resourceId, String projectId, String runModule) { public TaskRequestDTO getTaskRequest(String reportId, String resourceId, String projectId, String runModule) {
TaskRequestDTO taskRequest = apiExecuteService.getTaskRequest(reportId, resourceId, projectId); TaskRequestDTO taskRequest = apiExecuteService.getTaskRequest(reportId, resourceId, projectId);
taskRequest.setResourceType(ApiResourceType.API_SCENARIO.name()); taskRequest.setResourceType(ApiResourceType.API_SCENARIO.name());
taskRequest.setRunMode(runModule); taskRequest.setRunMode(runModule);
@ -1467,9 +1465,10 @@ public class ApiScenarioService extends MoveNodeService {
.ifPresent(msCommonElement -> parseParam.getCommonElements().add(msCommonElement)); .ifPresent(msCommonElement -> parseParam.getCommonElements().add(msCommonElement));
// 组装树结构 // 组装树结构
parentElement.getChildren().add(msTestElement); parentElement.getChildren().add(msTestElement);
}
if (CollectionUtils.isNotEmpty(step.getChildren())) { if (CollectionUtils.isNotEmpty(step.getChildren())) {
parseStep2MsElement(msTestElement, step.getChildren(), parseParam); parseStep2MsElement(msTestElement, step.getChildren(), parseParam);
}
} }
} }
} }
@ -1574,23 +1573,7 @@ public class ApiScenarioService extends MoveNodeService {
} }
private Map<String, String> getStepDetailMap(List<? extends ApiScenarioStepCommonDTO> steps, Map<String, Object> stepDetailsParam) { private Map<String, String> getStepDetailMap(List<? extends ApiScenarioStepCommonDTO> steps, Map<String, Object> stepDetailsParam) {
List<String> needBlobStepIds = new ArrayList<>(); List<String> needBlobStepIds = getHasDetailStepIds(steps, stepDetailsParam);
for (ApiScenarioStepCommonDTO step : steps) {
if (BooleanUtils.isFalse(step.getEnable())) {
continue;
}
if (StringUtils.equalsAny(step.getStepType(), ApiScenarioStepRefType.REF.name())
&& !StringUtils.equals(step.getRefType(), ApiScenarioStepType.API.name())) {
// 非完全引用的步骤和接口定义的步骤才需要查blob
continue;
}
if (stepDetailsParam != null && stepDetailsParam.containsKey(step.getId())) {
// 前端传了blob不需要再查
continue;
}
needBlobStepIds.add(step.getId());
}
Map<String, String> stepDetails = getStepBlobByIds(needBlobStepIds).stream() Map<String, String> stepDetails = getStepBlobByIds(needBlobStepIds).stream()
.collect(Collectors.toMap(ApiScenarioStepBlob::getId, blob -> new String(blob.getContent()))); .collect(Collectors.toMap(ApiScenarioStepBlob::getId, blob -> new String(blob.getContent())));
// 前端有传就用前端传的 // 前端有传就用前端传的
@ -1600,6 +1583,39 @@ public class ApiScenarioService extends MoveNodeService {
return stepDetails; return stepDetails;
} }
private List<String> getHasDetailStepIds(List<? extends ApiScenarioStepCommonDTO> steps, Map<String, Object> stepDetailsParam) {
List<String> needBlobStepIds = new ArrayList<>();
for (ApiScenarioStepCommonDTO step : steps) {
if (BooleanUtils.isFalse(step.getEnable())) {
continue;
}
if (!hasStepDetail(step.getStepType())) {
continue;
}
if (stepDetailsParam != null && stepDetailsParam.containsKey(step.getId())) {
// 前端传了blob不需要再查
continue;
}
needBlobStepIds.add(step.getId());
List<? extends ApiScenarioStepCommonDTO> children = step.getChildren();
if (CollectionUtils.isNotEmpty(children)) {
needBlobStepIds.addAll(getHasDetailStepIds(children, stepDetailsParam));
}
}
return needBlobStepIds;
}
/**
* 非完全引用的步骤和接口定义的步骤才需要查 blob
*
* @param stepType
* @return
*/
private boolean hasStepDetail(String stepType) {
return !StringUtils.equals(stepType, ApiScenarioStepRefType.REF.name())
|| StringUtils.equals(stepType, ApiScenarioStepType.API.name());
}
private Map<String, String> getResourceDetailMap(Map<String, List<String>> refResourceMap) { private Map<String, String> getResourceDetailMap(Map<String, List<String>> refResourceMap) {
Map<String, String> resourceBlobMap = new HashMap<>(); Map<String, String> resourceBlobMap = new HashMap<>();
List<String> apiIds = refResourceMap.get(ApiScenarioStepType.API.name()); List<String> apiIds = refResourceMap.get(ApiScenarioStepType.API.name());
@ -1649,18 +1665,17 @@ public class ApiScenarioService extends MoveNodeService {
} }
private ScenarioConfig getScenarioConfig(ApiScenarioDebugRequest request, boolean hasSave) { private ScenarioConfig getScenarioConfig(ApiScenarioDebugRequest request, boolean hasSave) {
ScenarioConfig scenarioConfig = null;
if (request.getScenarioConfig() != null) { if (request.getScenarioConfig() != null) {
// 优先使用前端传的配置 // 优先使用前端传的配置
scenarioConfig = request.getScenarioConfig(); return request.getScenarioConfig();
} else if (hasSave) { } else if (hasSave) {
// 没传并且保存过则从数据库获取 // 没传并且保存过则从数据库获取
ApiScenarioBlob apiScenarioBlob = apiScenarioBlobMapper.selectByPrimaryKey(request.getId()); ApiScenarioBlob apiScenarioBlob = apiScenarioBlobMapper.selectByPrimaryKey(request.getId());
if (apiScenarioBlob != null) { if (apiScenarioBlob != null) {
scenarioConfig = JSON.parseObject(new String(apiScenarioBlob.getConfig()), ScenarioConfig.class); return JSON.parseObject(new String(apiScenarioBlob.getConfig()), ScenarioConfig.class);
} }
} }
return scenarioConfig; return new ScenarioConfig();
} }
public void updateStatus(String id, String status, String userId) { public void updateStatus(String id, String status, String userId) {
@ -1716,8 +1731,8 @@ public class ApiScenarioService extends MoveNodeService {
Map<String, List<ApiScenarioStepDTO>> scenarioStepMap = allSteps.stream() Map<String, List<ApiScenarioStepDTO>> scenarioStepMap = allSteps.stream()
.collect(Collectors.groupingBy(step -> Optional.ofNullable(step.getScenarioId()).orElse(StringUtils.EMPTY))); .collect(Collectors.groupingBy(step -> Optional.ofNullable(step.getScenarioId()).orElse(StringUtils.EMPTY)));
// 查询部分引用的步骤详情和接口定义的步骤详情 // 查询步骤详情
Map<String, String> stepDetailMap = getStepDetailMap(allSteps); Map<String, String> stepDetailMap = getStepDetailMap(allSteps, Map.of());
// key 为父步骤IDvalue 为子步骤列表 // key 为父步骤IDvalue 为子步骤列表
if (MapUtils.isEmpty(scenarioStepMap)) { if (MapUtils.isEmpty(scenarioStepMap)) {
@ -1726,7 +1741,7 @@ public class ApiScenarioService extends MoveNodeService {
Map<String, List<ApiScenarioStepDTO>> parentStepMap = scenarioStepMap.get(scenarioId) Map<String, List<ApiScenarioStepDTO>> parentStepMap = scenarioStepMap.get(scenarioId)
.stream() .stream()
.collect(Collectors.groupingBy(step -> Optional.ofNullable(step.getParentId()).orElse(StringUtils.EMPTY))); .collect(Collectors.groupingBy(step -> Optional.ofNullable(step.getParentId()).orElse(StringUtils.EMPTY)));
List<ApiScenarioStepDTO> steps = buildStepTree(parentStepMap.get(StringUtils.EMPTY), scenarioStepMap, scenarioStepMap); List<ApiScenarioStepDTO> steps = buildStepTree(parentStepMap.get(StringUtils.EMPTY), parentStepMap, scenarioStepMap);
// 设置部分引用的步骤的启用状态 // 设置部分引用的步骤的启用状态
setPartialRefStepsEnable(steps, stepDetailMap); setPartialRefStepsEnable(steps, stepDetailMap);
@ -1750,23 +1765,6 @@ public class ApiScenarioService extends MoveNodeService {
} }
} }
/**
* 查询部分引用的步骤详情 接口定义的步骤详情
*/
private Map<String, String> getStepDetailMap(List<ApiScenarioStepDTO> allSteps) {
List<String> stepDetailIds = allSteps.stream().filter(step -> isRefApi(step.getStepType(), step.getRefType())
|| StringUtils.equals(step.getRefType(), ApiScenarioStepRefType.PARTIAL_REF.name()))
.map(ApiScenarioStepDTO::getId)
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(stepDetailIds)) {
return new HashMap<>(0);
}
ApiScenarioBlobExample example = new ApiScenarioBlobExample();
example.createCriteria().andIdIn(stepDetailIds);
return apiScenarioBlobMapper.selectByExample(example).stream()
.collect(Collectors.toMap(ApiScenarioBlob::getId, blob -> new String(blob.getConfig())));
}
/** /**
* 判断步骤是否是引用的接口定义 * 判断步骤是否是引用的接口定义
* 引用的接口定义允许修改参数值需要特殊处理 * 引用的接口定义允许修改参数值需要特殊处理

View File

@ -162,7 +162,6 @@ public class ApiReportSendNoticeTests extends BaseTest {
scenarioReport.setEnvironmentId("api-environment-id"); scenarioReport.setEnvironmentId("api-environment-id");
scenarioReport.setRunMode("api-run-mode" + i); scenarioReport.setRunMode("api-run-mode" + i);
scenarioReport.setTriggerMode("api-trigger-mode" + i); scenarioReport.setTriggerMode("api-trigger-mode" + i);
scenarioReport.setVersionId("api-version-id" + i);
scenarioReports.add(scenarioReport); scenarioReports.add(scenarioReport);
ApiScenarioRecord record = new ApiScenarioRecord(); ApiScenarioRecord record = new ApiScenarioRecord();
record.setApiScenarioId("send-scenario-id" + i); record.setApiScenarioId("send-scenario-id" + i);

View File

@ -3,6 +3,7 @@ package io.metersphere.api.controller;
import io.metersphere.api.constants.*; import io.metersphere.api.constants.*;
import io.metersphere.api.domain.*; import io.metersphere.api.domain.*;
import io.metersphere.api.dto.ApiFile; import io.metersphere.api.dto.ApiFile;
import io.metersphere.api.dto.ApiRunModeRequest;
import io.metersphere.api.dto.ReferenceRequest; import io.metersphere.api.dto.ReferenceRequest;
import io.metersphere.api.dto.assertion.MsAssertionConfig; import io.metersphere.api.dto.assertion.MsAssertionConfig;
import io.metersphere.api.dto.debug.ModuleCreateRequest; import io.metersphere.api.dto.debug.ModuleCreateRequest;
@ -100,6 +101,7 @@ public class ApiScenarioControllerTests extends BaseTest {
protected static final String RUN_REAL_TIME = "run/{0}?reportId={1}"; protected static final String RUN_REAL_TIME = "run/{0}?reportId={1}";
private static final String UPDATE_STATUS = "update-status"; private static final String UPDATE_STATUS = "update-status";
private static final String UPDATE_PRIORITY = "update-priority"; private static final String UPDATE_PRIORITY = "update-priority";
private static final String BATCH_RUN = "batch-operation/run";
private static final Map<String, String> BATCH_OPERATION_SCENARIO_MODULE_MAP = new HashMap<>(); private static final Map<String, String> BATCH_OPERATION_SCENARIO_MODULE_MAP = new HashMap<>();
private static final List<String> BATCH_OPERATION_SCENARIO_ID = new ArrayList<>(); private static final List<String> BATCH_OPERATION_SCENARIO_ID = new ArrayList<>();
@ -1015,6 +1017,38 @@ public class ApiScenarioControllerTests extends BaseTest {
requestGetPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_EXECUTE, RUN_REAL_TIME, addApiScenario.getId(), "reportId"); requestGetPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_EXECUTE, RUN_REAL_TIME, addApiScenario.getId(), "reportId");
} }
@Order(6)
public void batchRun() throws Exception {
mockPost("/api/run", "");
ApiScenarioBatchRunRequest request = new ApiScenarioBatchRunRequest();
List<String> ids = new ArrayList<>();
ids.add(addApiScenario.getId());
request.setSelectIds(ids);
request.setProjectId(addApiScenario.getProjectId());
ApiRunModeRequest apiRunModeRequest = new ApiRunModeRequest();
apiRunModeRequest.setRunMode(ApiBatchRunMode.PARALLEL.name());
apiRunModeRequest.setIntegratedReport(true);
apiRunModeRequest.setStopOnFailure(false);
apiRunModeRequest.setIntegratedReportName("aaaa");
apiRunModeRequest.setPoolId("poolId");
request.setRunModeConfig(apiRunModeRequest);
this.requestPostWithOk(BATCH_RUN, request);
apiRunModeRequest.setIntegratedReport(false);
apiRunModeRequest.setStopOnFailure(true);
this.requestPostWithOk(BATCH_RUN, request);
apiRunModeRequest.setRunMode(ApiBatchRunMode.SERIAL.name());
this.requestPostWithOk(BATCH_RUN, request);
apiRunModeRequest.setIntegratedReport(true);
this.requestPostWithOk(BATCH_RUN, request);
// @@校验权限
requestPostPermissionTest(PermissionConstants.PROJECT_API_SCENARIO_EXECUTE, BATCH_RUN, request);
}
public Plugin addEnvTestPlugin() throws Exception { public Plugin addEnvTestPlugin() throws Exception {
PluginUpdateRequest request = new PluginUpdateRequest(); PluginUpdateRequest request = new PluginUpdateRequest();
File jarFile = new File( File jarFile = new File(
@ -2382,7 +2416,6 @@ public class ApiScenarioControllerTests extends BaseTest {
apiReport.setStatus(ApiReportStatus.ERROR.name()); apiReport.setStatus(ApiReportStatus.ERROR.name());
} }
apiReport.setTriggerMode("api-trigger-mode" + i); apiReport.setTriggerMode("api-trigger-mode" + i);
apiReport.setVersionId("api-version-id" + i);
reports.add(apiReport); reports.add(apiReport);
ApiScenarioRecord record = new ApiScenarioRecord(); ApiScenarioRecord record = new ApiScenarioRecord();
record.setApiScenarioId(first.getId()); record.setApiScenarioId(first.getId());

View File

@ -102,7 +102,6 @@ public class ApiScenarioReportControllerTests extends BaseTest {
scenarioReport.setEnvironmentId("api-environment-id" + i); scenarioReport.setEnvironmentId("api-environment-id" + i);
scenarioReport.setRunMode("api-run-mode" + i); scenarioReport.setRunMode("api-run-mode" + i);
scenarioReport.setTriggerMode("api-trigger-mode" + i); scenarioReport.setTriggerMode("api-trigger-mode" + i);
scenarioReport.setVersionId("api-version-id" + i);
reports.add(scenarioReport); reports.add(scenarioReport);
ApiScenarioRecord apiScenarioRecord = new ApiScenarioRecord(); ApiScenarioRecord apiScenarioRecord = new ApiScenarioRecord();
apiScenarioRecord.setApiScenarioId("scenario-record-id" + i); apiScenarioRecord.setApiScenarioId("scenario-record-id" + i);
@ -262,7 +261,6 @@ public class ApiScenarioReportControllerTests extends BaseTest {
scenarioReport.setEnvironmentId(environments.getFirst().getId()); scenarioReport.setEnvironmentId(environments.getFirst().getId());
scenarioReport.setRunMode("api-run-mode"); scenarioReport.setRunMode("api-run-mode");
scenarioReport.setTriggerMode("api-trigger-mode"); scenarioReport.setTriggerMode("api-trigger-mode");
scenarioReport.setVersionId("api-version-id");
reports.add(scenarioReport); reports.add(scenarioReport);
ApiScenarioRecord apiScenarioRecord = new ApiScenarioRecord(); ApiScenarioRecord apiScenarioRecord = new ApiScenarioRecord();
apiScenarioRecord.setApiScenarioId("test-scenario-record-id"); apiScenarioRecord.setApiScenarioId("test-scenario-record-id");

View File

@ -275,7 +275,6 @@ public class ApiTaskCenterControllerTests extends BaseTest {
scenarioReport.setEnvironmentId("api-environment-id" + i); scenarioReport.setEnvironmentId("api-environment-id" + i);
scenarioReport.setRunMode("api-run-mode" + i); scenarioReport.setRunMode("api-run-mode" + i);
scenarioReport.setTriggerMode("task-MANUAL"); scenarioReport.setTriggerMode("task-MANUAL");
scenarioReport.setVersionId("api-version-id" + i);
scenarioReports.add(scenarioReport); scenarioReports.add(scenarioReport);
ApiScenarioRecord scenarioRecord = new ApiScenarioRecord(); ApiScenarioRecord scenarioRecord = new ApiScenarioRecord();
scenarioRecord.setApiScenarioId("task-api-resource-id" + i); scenarioRecord.setApiScenarioId("task-api-resource-id" + i);

View File

@ -6,6 +6,7 @@ import io.metersphere.api.controller.param.ApiTestCaseAddRequestDefinition;
import io.metersphere.api.controller.result.ApiResultCode; import io.metersphere.api.controller.result.ApiResultCode;
import io.metersphere.api.domain.*; import io.metersphere.api.domain.*;
import io.metersphere.api.dto.ApiFile; import io.metersphere.api.dto.ApiFile;
import io.metersphere.api.dto.ApiRunModeRequest;
import io.metersphere.api.dto.ReferenceRequest; import io.metersphere.api.dto.ReferenceRequest;
import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.*;
import io.metersphere.api.dto.request.ApiTransferRequest; import io.metersphere.api.dto.request.ApiTransferRequest;
@ -457,7 +458,7 @@ public class ApiTestCaseControllerTests extends BaseTest {
ids.add(apiTestCase.getId()); ids.add(apiTestCase.getId());
request.setSelectIds(ids); request.setSelectIds(ids);
request.setProjectId(apiTestCase.getProjectId()); request.setProjectId(apiTestCase.getProjectId());
ApiTestCaseBatchRunRequest.ApiRunModeRequest apiRunModeRequest = new ApiTestCaseBatchRunRequest.ApiRunModeRequest(); ApiRunModeRequest apiRunModeRequest = new ApiRunModeRequest();
apiRunModeRequest.setRunMode(ApiBatchRunMode.PARALLEL.name()); apiRunModeRequest.setRunMode(ApiBatchRunMode.PARALLEL.name());
apiRunModeRequest.setIntegratedReport(true); apiRunModeRequest.setIntegratedReport(true);
apiRunModeRequest.setStopOnFailure(false); apiRunModeRequest.setStopOnFailure(false);

View File

@ -293,7 +293,6 @@ public class CleanupApiTests {
scenarioReport.setEnvironmentId("api-environment-id" + i); scenarioReport.setEnvironmentId("api-environment-id" + i);
scenarioReport.setRunMode("api-run-mode" + i); scenarioReport.setRunMode("api-run-mode" + i);
scenarioReport.setTriggerMode("api-trigger-mode" + i); scenarioReport.setTriggerMode("api-trigger-mode" + i);
scenarioReport.setVersionId("api-version-id" + i);
scenarioReports.add(scenarioReport); scenarioReports.add(scenarioReport);
ApiScenarioRecord record = new ApiScenarioRecord(); ApiScenarioRecord record = new ApiScenarioRecord();
record.setApiScenarioId("clean-scenario-id" + i); record.setApiScenarioId("clean-scenario-id" + i);

View File

@ -53,12 +53,10 @@ public class ApiExecutionQueueServiceTest {
ExecutionQueueDetail queueDetail1 = new ExecutionQueueDetail(); ExecutionQueueDetail queueDetail1 = new ExecutionQueueDetail();
queueDetail1.setResourceId("resourceId1"); queueDetail1.setResourceId("resourceId1");
queueDetail1.setSort(1); queueDetail1.setSort(1);
queueDetail1.setResourceType("API");
ExecutionQueueDetail queueDetail2 = new ExecutionQueueDetail(); ExecutionQueueDetail queueDetail2 = new ExecutionQueueDetail();
queueDetail2.setResourceId("resourceId2"); queueDetail2.setResourceId("resourceId2");
queueDetail2.setSort(2); queueDetail2.setSort(2);
queueDetail2.setResourceType("CASE");
List<ExecutionQueueDetail> queueDetails = List.of(queueDetail1, queueDetail2); List<ExecutionQueueDetail> queueDetails = List.of(queueDetail1, queueDetail2);

View File

@ -125,26 +125,26 @@ INSERT INTO `api_scenario` (`id`, `name`, `priority`, `status`, `step_total`, `r
INSERT INTO `api_scenario` (`id`, `name`, `priority`, `status`, `step_total`, `request_pass_rate`, `last_report_status`, `last_report_id`, `num`, `deleted`, `pos`, `version_id`, `ref_id`, `latest`, `project_id`, `module_id`, `description`, `tags`, `grouped`, `environment_id`, `create_user`, `create_time`, `delete_time`, `delete_user`, `update_user`, `update_time`) VALUES ('9', 'Scenario 9', 'P2', 'Not Planned', 16, 'Calculating', NULL, NULL, 1009, b'0', 9, 'version_9', 'ref_9', b'1', '100001100001', 'module_9', 'Description 9', '[\"tag1\",\"tag3\"]', b'1', 'env_5', 'admin', 1640772869000, NULL, NULL, 'admin', 1640772869000); INSERT INTO `api_scenario` (`id`, `name`, `priority`, `status`, `step_total`, `request_pass_rate`, `last_report_status`, `last_report_id`, `num`, `deleted`, `pos`, `version_id`, `ref_id`, `latest`, `project_id`, `module_id`, `description`, `tags`, `grouped`, `environment_id`, `create_user`, `create_time`, `delete_time`, `delete_user`, `update_user`, `update_time`) VALUES ('9', 'Scenario 9', 'P2', 'Not Planned', 16, 'Calculating', NULL, NULL, 1009, b'0', 9, 'version_9', 'ref_9', b'1', '100001100001', 'module_9', 'Description 9', '[\"tag1\",\"tag3\"]', b'1', 'env_5', 'admin', 1640772869000, NULL, NULL, 'admin', 1640772869000);
DELETE FROM `api_scenario_report` WHERE `id` in ('report_1', 'report_2', 'report_3', 'report_4','report_5','report_6', 'report_7', 'report_8', 'report_9','report_10','report_11', 'report_12', 'report_13', 'report_14','report_15','report_16', 'report_17', 'report_18', 'report_19','report_20'); DELETE FROM `api_scenario_report` WHERE `id` in ('report_1', 'report_2', 'report_3', 'report_4','report_5','report_6', 'report_7', 'report_8', 'report_9','report_10','report_11', 'report_12', 'report_13', 'report_14','report_15','report_16', 'report_17', 'report_18', 'report_19','report_20');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_1', 'Report 1', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773000000, UNIX_TIMESTAMP() * 1000, 1640774000000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', 'version_1', b'0', '100001100001', 'env_1', 2, 0, 0, 2, 20, 18, '95%', 'Calculating', 'Calculating', '90%', '90%', 'script_1'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_1', 'Report 1', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773000000, UNIX_TIMESTAMP() * 1000, 1640774000000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', b'0', '100001100001', 'env_1', 2, 0, 0, 2, 20, 18, '95%', 'Calculating', 'Calculating', '90%', '90%', 'script_1');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_10', 'Report 10', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773900000, UNIX_TIMESTAMP() * 1000, 1640774900000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', 'version_10', b'0', '100001100001', 'env_10', 2, 0, 0, 2, 22, 20, '90%', 'Calculating', 'Calculating', '85%', '80%', 'script_10'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_10', 'Report 10', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773900000, UNIX_TIMESTAMP() * 1000, 1640774900000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', b'0', '100001100001', 'env_10', 2, 0, 0, 2, 22, 20, '90%', 'Calculating', 'Calculating', '85%', '80%', 'script_10');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_11', 'Report 11', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774000000, UNIX_TIMESTAMP() * 1000, 1640775000000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', 'version_11', b'0', '100001100001', 'env_11', 3, 1, 0, 2, 28, 26, '75%', 'Calculating', 'Calculating', '80%', '85%', 'script_11'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_11', 'Report 11', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774000000, UNIX_TIMESTAMP() * 1000, 1640775000000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', b'0', '100001100001', 'env_11', 3, 1, 0, 2, 28, 26, '75%', 'Calculating', 'Calculating', '80%', '85%', 'script_11');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_12', 'Report 12', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774100000, UNIX_TIMESTAMP() * 1000, 1640775100000, 5000, 'PENDING', 'Automated', 'Standalone', '100660357777795313', 'version_12', b'1', '100001100001', 'env_12', 0, 0, 16, 16, 26, 24, 'Calculating', 'Calculating', 'Calculating', 'Calculating', 'Calculating', 'script_12'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_12', 'Report 12', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774100000, UNIX_TIMESTAMP() * 1000, 1640775100000, 5000, 'PENDING', 'Automated', 'Standalone', '100660357777795313', b'1', '100001100001', 'env_12', 0, 0, 16, 16, 26, 24, 'Calculating', 'Calculating', 'Calculating', 'Calculating', 'Calculating', 'script_12');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_13', 'Report 13', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774200000, UNIX_TIMESTAMP() * 1000, 1640775200000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', 'version_13', b'0', '100001100001', 'env_13', 2, 0, 0, 2, 24, 22, '80%', 'Calculating', 'Calculating', '85%', '90%', 'script_13'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_13', 'Report 13', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774200000, UNIX_TIMESTAMP() * 1000, 1640775200000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', b'0', '100001100001', 'env_13', 2, 0, 0, 2, 24, 22, '80%', 'Calculating', 'Calculating', '85%', '90%', 'script_13');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_14', 'Report 14', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774300000, UNIX_TIMESTAMP() * 1000, 1640775300000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', 'version_14', b'0', '100001100001', 'env_14', 3, 1, 0, 2, 20, 18, '70%', 'Calculating', 'Calculating', '75%', '80%', 'script_14'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_14', 'Report 14', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774300000, UNIX_TIMESTAMP() * 1000, 1640775300000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', b'0', '100001100001', 'env_14', 3, 1, 0, 2, 20, 18, '70%', 'Calculating', 'Calculating', '75%', '80%', 'script_14');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_15', 'Report 15', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774400000, UNIX_TIMESTAMP() * 1000, 1640775400000, 5000, 'PENDING', 'Automated', 'Standalone', '100660357777795313', 'version_15', b'1', '100001100001', 'env_15', 0, 0, 18, 18, 22, 20, 'Calculating','Calculating', 'Calculating', 'Calculating', 'Calculating', 'script_15'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_15', 'Report 15', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774400000, UNIX_TIMESTAMP() * 1000, 1640775400000, 5000, 'PENDING', 'Automated', 'Standalone', '100660357777795313', b'1', '100001100001', 'env_15', 0, 0, 18, 18, 22, 20, 'Calculating','Calculating', 'Calculating', 'Calculating', 'Calculating', 'script_15');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_16', 'Report 16', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774500000, UNIX_TIMESTAMP() * 1000, 1640775500000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', 'version_16', b'0', '100001100001', 'env_16', 2, 0, 0, 2, 20, 18, '85%', 'Calculating', 'Calculating', '90%', '90%', 'script_16'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_16', 'Report 16', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774500000, UNIX_TIMESTAMP() * 1000, 1640775500000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', b'0', '100001100001', 'env_16', 2, 0, 0, 2, 20, 18, '85%', 'Calculating', 'Calculating', '90%', '90%', 'script_16');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_17', 'Report 17', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774600000, UNIX_TIMESTAMP() * 1000, 1640775600000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', 'version_17', b'0', '100001100001', 'env_17', 3, 1, 0, 2, 26, 24, '75%', 'Calculating', 'Calculating', '80%', '85%', 'script_17'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_17', 'Report 17', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774600000, UNIX_TIMESTAMP() * 1000, 1640775600000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', b'0', '100001100001', 'env_17', 3, 1, 0, 2, 26, 24, '75%', 'Calculating', 'Calculating', '80%', '85%', 'script_17');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_18', 'Report 18', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774700000, UNIX_TIMESTAMP() * 1000, 1640775700000, 5000, 'PENDING', 'Automated', 'Standalone', '100660357777795313', 'version_18', b'1', '100001100001', 'env_18', 0, 0, 20, 20, 30, 28, 'Calculating', 'Calculating', 'Calculating', 'Calculating', 'Calculating', 'script_18'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_18', 'Report 18', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774700000, UNIX_TIMESTAMP() * 1000, 1640775700000, 5000, 'PENDING', 'Automated', 'Standalone', '100660357777795313', b'1', '100001100001', 'env_18', 0, 0, 20, 20, 30, 28, 'Calculating', 'Calculating', 'Calculating', 'Calculating', 'Calculating', 'script_18');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_19', 'Report 19', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774800000, UNIX_TIMESTAMP() * 1000, 1640775800000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', 'version_19', b'0', '100001100001', 'env_19', 2, 0, 0, 2, 18, 16, '90%', 'Calculating', 'Calculating', '85%', '80%', 'script_19'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_19', 'Report 19', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774800000, UNIX_TIMESTAMP() * 1000, 1640775800000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', b'0', '100001100001', 'env_19', 2, 0, 0, 2, 18, 16, '90%', 'Calculating', 'Calculating', '85%', '80%', 'script_19');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_2', 'Report 2', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773100000, UNIX_TIMESTAMP() * 1000, 1640774100000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', 'version_2', b'0', '100001100001', 'env_2', 3, 1, 0, 2, 22, 20, '80%', 'Calculating', 'Calculating', '85%', '90%', 'script_2'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_2', 'Report 2', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773100000, UNIX_TIMESTAMP() * 1000, 1640774100000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', b'0', '100001100001', 'env_2', 3, 1, 0, 2, 22, 20, '80%', 'Calculating', 'Calculating', '85%', '90%', 'script_2');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_20', 'Report 20', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774900000, UNIX_TIMESTAMP() * 1000, 1640775900000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', 'version_20', b'0', '100001100001', 'env_20', 3, 1, 0, 2, 22, 20, '70%', 'Calculating', 'Calculating', '75%', '80%', 'script_20'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_20', 'Report 20', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640774900000, UNIX_TIMESTAMP() * 1000, 1640775900000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', b'0', '100001100001', 'env_20', 3, 1, 0, 2, 22, 20, '70%', 'Calculating', 'Calculating', '75%', '80%', 'script_20');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_3', 'Report 3', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773200000, UNIX_TIMESTAMP() * 1000, 1640774200000, 5000, 'PENDING', 'Automated', 'Standalone', '100660357777795313', 'version_3', b'1', '100001100001', 'env_3', 0, 0, 10, 10, 30, 28, 'Calculating','Calculating', 'Calculating', 'Calculating', 'Calculating', 'script_3'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_3', 'Report 3', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773200000, UNIX_TIMESTAMP() * 1000, 1640774200000, 5000, 'PENDING', 'Automated', 'Standalone', '100660357777795313', b'1', '100001100001', 'env_3', 0, 0, 10, 10, 30, 28, 'Calculating','Calculating', 'Calculating', 'Calculating', 'Calculating', 'script_3');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_4', 'Report 4', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773300000, UNIX_TIMESTAMP() * 1000, 1640774300000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', 'version_4', b'0', '100001100001', 'env_4', 2, 0, 0, 2, 18, 16, '90%','Calculating', 'Calculating', '85%', '80%', 'script_4'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_4', 'Report 4', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773300000, UNIX_TIMESTAMP() * 1000, 1640774300000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', b'0', '100001100001', 'env_4', 2, 0, 0, 2, 18, 16, '90%','Calculating', 'Calculating', '85%', '80%', 'script_4');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_5', 'Report 5', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773400000, UNIX_TIMESTAMP() * 1000, 1640774400000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', 'version_5', b'0', '100001100001', 'env_5', 3, 1, 0, 2, 24, 22, '70%', 'Calculating', 'Calculating', '75%', '80%', 'script_5'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_5', 'Report 5', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773400000, UNIX_TIMESTAMP() * 1000, 1640774400000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', b'0', '100001100001', 'env_5', 3, 1, 0, 2, 24, 22, '70%', 'Calculating', 'Calculating', '75%', '80%', 'script_5');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_6', 'Report 6', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773500000, UNIX_TIMESTAMP() * 1000, 1640774500000, 5000, 'PENDING', 'Automated', 'Standalone', '100660357777795313', 'version_6', b'1', '100001100001', 'env_6', 0, 0, 12, 12, 20, 18, 'Calculating','Calculating', 'Calculating', 'Calculating', 'Calculating', 'script_6'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_6', 'Report 6', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773500000, UNIX_TIMESTAMP() * 1000, 1640774500000, 5000, 'PENDING', 'Automated', 'Standalone', '100660357777795313', b'1', '100001100001', 'env_6', 0, 0, 12, 12, 20, 18, 'Calculating','Calculating', 'Calculating', 'Calculating', 'Calculating', 'script_6');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_7', 'Report 7', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773600000, UNIX_TIMESTAMP() * 1000, 1640774600000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', 'version_7', b'0', '100001100001', 'env_7', 2, 0, 0, 2, 16, 14, '85%', 'Calculating', 'Calculating', '90%', '90%', 'script_7'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_7', 'Report 7', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773600000, UNIX_TIMESTAMP() * 1000, 1640774600000, 5000, 'SUCCESS', 'Manual', 'Standalone', '100660357777795313', b'0', '100001100001', 'env_7', 2, 0, 0, 2, 16, 14, '85%', 'Calculating', 'Calculating', '90%', '90%', 'script_7');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_8', 'Report 8', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773700000, UNIX_TIMESTAMP() * 1000, 1640774700000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', 'version_8', b'0', '100001100001', 'env_8', 3, 1, 0, 2, 20, 18, 'Calculating', 'Calculating', '70%', '75%', '80%', 'script_8'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_8', 'Report 8', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773700000, UNIX_TIMESTAMP() * 1000, 1640774700000, 5000, 'ERROR', 'Automated', 'Distributed', '100660357777795313', b'0', '100001100001', 'env_8', 3, 1, 0, 2, 20, 18, 'Calculating', 'Calculating', '70%', '75%', '80%', 'script_8');
INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `version_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_9', 'Report 9', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773800000, UNIX_TIMESTAMP() * 1000, 1640774800000, 5000, 'PENDING', 'Automated', 'Standalone', '100660357777795313', 'version_9', b'1', '100001100001', 'env_9', 0, 0, 14, 14, 18, 16, 'Calculating', 'Calculating', 'Calculating', 'Calculating', 'Calculating', 'script_9'); INSERT INTO `api_scenario_report` (`id`, `name`, `test_plan_id`, `create_user`, `delete_time`, `delete_user`, `deleted`, `update_user`, `update_time`, `start_time`, `end_time`, `request_duration`, `status`, `trigger_mode`, `run_mode`, `pool_id`, `integrated`, `project_id`, `environment_id`, `error_count`, `fake_error_count`, `pending_count`, `success_count`, `assertion_count`, `assertion_success_count`, `request_error_rate`, `request_pending_rate`, `request_fake_error_rate`, `request_pass_rate`, `assertion_pass_rate`, `script_identifier`) VALUES ('report_9', 'Report 9', 'NONE', 'admin', NULL, NULL, b'0', 'admin', 1640773800000, UNIX_TIMESTAMP() * 1000, 1640774800000, 5000, 'PENDING', 'Automated', 'Standalone', '100660357777795313', b'1', '100001100001', 'env_9', 0, 0, 14, 14, 18, 16, 'Calculating', 'Calculating', 'Calculating', 'Calculating', 'Calculating', 'script_9');