feat: 测试计划报告初版
This commit is contained in:
parent
abb446dbef
commit
3176bd45ee
|
@ -0,0 +1,16 @@
|
|||
package io.metersphere.api.dto.automation;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class TestPlanFailureApiDTO extends TestPlanApiCaseDTO {
|
||||
|
||||
private String projectName;
|
||||
|
||||
private String caseId;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package io.metersphere.api.dto.automation;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class TestPlanFailureScenarioDTO extends ApiScenarioDTO {
|
||||
|
||||
private String projectName;
|
||||
|
||||
private String caseId;
|
||||
}
|
|
@ -45,7 +45,5 @@ public class TestPlan implements Serializable {
|
|||
|
||||
private Boolean automaticStatusUpdate;
|
||||
|
||||
private String tags;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package io.metersphere.base.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class TestPlanWithBLOBs extends TestPlan implements Serializable {
|
||||
private String tags;
|
||||
|
||||
private String reportSummary;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
|
@ -2,6 +2,7 @@ package io.metersphere.base.mapper;
|
|||
|
||||
import io.metersphere.base.domain.TestPlan;
|
||||
import io.metersphere.base.domain.TestPlanExample;
|
||||
import io.metersphere.base.domain.TestPlanWithBLOBs;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
|
@ -12,25 +13,25 @@ public interface TestPlanMapper {
|
|||
|
||||
int deleteByPrimaryKey(String id);
|
||||
|
||||
int insert(TestPlan record);
|
||||
int insert(TestPlanWithBLOBs record);
|
||||
|
||||
int insertSelective(TestPlan record);
|
||||
int insertSelective(TestPlanWithBLOBs record);
|
||||
|
||||
List<TestPlan> selectByExampleWithBLOBs(TestPlanExample example);
|
||||
List<TestPlanWithBLOBs> selectByExampleWithBLOBs(TestPlanExample example);
|
||||
|
||||
List<TestPlan> selectByExample(TestPlanExample example);
|
||||
|
||||
TestPlan selectByPrimaryKey(String id);
|
||||
TestPlanWithBLOBs selectByPrimaryKey(String id);
|
||||
|
||||
int updateByExampleSelective(@Param("record") TestPlan record, @Param("example") TestPlanExample example);
|
||||
int updateByExampleSelective(@Param("record") TestPlanWithBLOBs record, @Param("example") TestPlanExample example);
|
||||
|
||||
int updateByExampleWithBLOBs(@Param("record") TestPlan record, @Param("example") TestPlanExample example);
|
||||
int updateByExampleWithBLOBs(@Param("record") TestPlanWithBLOBs record, @Param("example") TestPlanExample example);
|
||||
|
||||
int updateByExample(@Param("record") TestPlan record, @Param("example") TestPlanExample example);
|
||||
|
||||
int updateByPrimaryKeySelective(TestPlan record);
|
||||
int updateByPrimaryKeySelective(TestPlanWithBLOBs record);
|
||||
|
||||
int updateByPrimaryKeyWithBLOBs(TestPlan record);
|
||||
int updateByPrimaryKeyWithBLOBs(TestPlanWithBLOBs record);
|
||||
|
||||
int updateByPrimaryKey(TestPlan record);
|
||||
}
|
|
@ -23,8 +23,9 @@
|
|||
<result column="execution_times" jdbcType="INTEGER" property="executionTimes" />
|
||||
<result column="automatic_status_update" jdbcType="BIT" property="automaticStatusUpdate" />
|
||||
</resultMap>
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestPlan">
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestPlanWithBLOBs">
|
||||
<result column="tags" jdbcType="LONGVARCHAR" property="tags" />
|
||||
<result column="report_summary" jdbcType="LONGVARCHAR" property="reportSummary" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -90,7 +91,7 @@
|
|||
actual_start_time, actual_end_time, creator, project_id, execution_times, automatic_status_update
|
||||
</sql>
|
||||
<sql id="Blob_Column_List">
|
||||
tags
|
||||
tags, report_summary
|
||||
</sql>
|
||||
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.base.domain.TestPlanExample" resultMap="ResultMapWithBLOBs">
|
||||
select
|
||||
|
@ -140,25 +141,25 @@
|
|||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.base.domain.TestPlan">
|
||||
<insert id="insert" parameterType="io.metersphere.base.domain.TestPlanWithBLOBs">
|
||||
insert into test_plan (id, workspace_id, report_id,
|
||||
`name`, description, `status`,
|
||||
stage, principal, test_case_match_rule,
|
||||
executor_match_rule, create_time, update_time,
|
||||
planned_start_time, planned_end_time, actual_start_time,
|
||||
actual_end_time, creator, project_id,
|
||||
execution_times, automatic_status_update, tags
|
||||
)
|
||||
execution_times, automatic_status_update, tags,
|
||||
report_summary)
|
||||
values (#{id,jdbcType=VARCHAR}, #{workspaceId,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR},
|
||||
#{name,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
|
||||
#{stage,jdbcType=VARCHAR}, #{principal,jdbcType=VARCHAR}, #{testCaseMatchRule,jdbcType=VARCHAR},
|
||||
#{executorMatchRule,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||
#{plannedStartTime,jdbcType=BIGINT}, #{plannedEndTime,jdbcType=BIGINT}, #{actualStartTime,jdbcType=BIGINT},
|
||||
#{actualEndTime,jdbcType=BIGINT}, #{creator,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR},
|
||||
#{executionTimes,jdbcType=INTEGER}, #{automaticStatusUpdate,jdbcType=BIT}, #{tags,jdbcType=LONGVARCHAR}
|
||||
)
|
||||
#{executionTimes,jdbcType=INTEGER}, #{automaticStatusUpdate,jdbcType=BIT}, #{tags,jdbcType=LONGVARCHAR},
|
||||
#{reportSummary,jdbcType=LONGVARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlan">
|
||||
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlanWithBLOBs">
|
||||
insert into test_plan
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -224,6 +225,9 @@
|
|||
<if test="tags != null">
|
||||
tags,
|
||||
</if>
|
||||
<if test="reportSummary != null">
|
||||
report_summary,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -289,6 +293,9 @@
|
|||
<if test="tags != null">
|
||||
#{tags,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="reportSummary != null">
|
||||
#{reportSummary,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.base.domain.TestPlanExample" resultType="java.lang.Long">
|
||||
|
@ -363,6 +370,9 @@
|
|||
<if test="record.tags != null">
|
||||
tags = #{record.tags,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="record.reportSummary != null">
|
||||
report_summary = #{record.reportSummary,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
|
@ -390,7 +400,8 @@
|
|||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
execution_times = #{record.executionTimes,jdbcType=INTEGER},
|
||||
automatic_status_update = #{record.automaticStatusUpdate,jdbcType=BIT},
|
||||
tags = #{record.tags,jdbcType=LONGVARCHAR}
|
||||
tags = #{record.tags,jdbcType=LONGVARCHAR},
|
||||
report_summary = #{record.reportSummary,jdbcType=LONGVARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -421,7 +432,7 @@
|
|||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.TestPlan">
|
||||
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.TestPlanWithBLOBs">
|
||||
update test_plan
|
||||
<set>
|
||||
<if test="workspaceId != null">
|
||||
|
@ -484,10 +495,13 @@
|
|||
<if test="tags != null">
|
||||
tags = #{tags,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
<if test="reportSummary != null">
|
||||
report_summary = #{reportSummary,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.TestPlan">
|
||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.TestPlanWithBLOBs">
|
||||
update test_plan
|
||||
set workspace_id = #{workspaceId,jdbcType=VARCHAR},
|
||||
report_id = #{reportId,jdbcType=VARCHAR},
|
||||
|
@ -508,7 +522,8 @@
|
|||
project_id = #{projectId,jdbcType=VARCHAR},
|
||||
execution_times = #{executionTimes,jdbcType=INTEGER},
|
||||
automatic_status_update = #{automaticStatusUpdate,jdbcType=BIT},
|
||||
tags = #{tags,jdbcType=LONGVARCHAR}
|
||||
tags = #{tags,jdbcType=LONGVARCHAR},
|
||||
report_summary = #{reportSummary,jdbcType=LONGVARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.TestPlan">
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.base.mapper.ext;
|
|||
|
||||
import io.metersphere.base.domain.Issues;
|
||||
import io.metersphere.base.domain.IssuesDao;
|
||||
import io.metersphere.track.dto.PlanReportIssueDTO;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
|
@ -11,11 +12,13 @@ public interface ExtIssuesMapper {
|
|||
|
||||
List<IssuesDao> getIssuesByCaseId(@Param("request") IssuesRequest issuesRequest);
|
||||
|
||||
List<IssuesDao> getIssuesByProjectId(@Param("request") IssuesRequest issuesRequest);
|
||||
List<IssuesDao> getIssues(@Param("request") IssuesRequest issuesRequest);
|
||||
|
||||
List<IssuesDao> getRelateIssues(@Param("request") IssuesRequest request);
|
||||
|
||||
Issues getNextNum(String projectId);
|
||||
|
||||
List<IssuesDao> getIssueForSync(String projectId);
|
||||
|
||||
List<PlanReportIssueDTO> selectForPlanReport(String planId);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
|
||||
</select>
|
||||
|
||||
<select id="getIssuesByProjectId" resultType="io.metersphere.base.domain.IssuesDao">
|
||||
<select id="getIssues" resultType="io.metersphere.base.domain.IssuesDao">
|
||||
select issues.id, issues.num, ifnull(issues.title, '') as title, issues.project_id, issues.create_time, issues.update_time,
|
||||
ifnull(issues.description, '') as description, issues.status, issues.platform, issues.custom_fields, issues.reporter,
|
||||
issues.creator,issues.resource_id,issues.platform_status,
|
||||
|
@ -42,6 +42,9 @@
|
|||
from issues
|
||||
where project_id = #{projectId} and platform != 'Local';
|
||||
</select>
|
||||
<select id="selectForPlanReport" resultType="io.metersphere.track.dto.PlanReportIssueDTO">
|
||||
select id,status,platform_status,platform from issues where resource_id = #{planId} and platform_status != 'delete';;
|
||||
</select>
|
||||
|
||||
<sql id="queryWhereCondition">
|
||||
<where>
|
||||
|
@ -57,6 +60,10 @@
|
|||
and issues.project_id = #{request.projectId}
|
||||
</if>
|
||||
|
||||
<if test="request.resourceId != null and request.resourceId != ''">
|
||||
and issues.resource_id = #{request.resourceId}
|
||||
</if>
|
||||
|
||||
<if test="request.testCaseId != null and request.testCaseId != ''">
|
||||
and test_case_issues.test_case_id = #{request.testCaseId}
|
||||
</if>
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
import io.metersphere.base.domain.Project;
|
||||
import io.metersphere.controller.request.ProjectRequest;
|
||||
import io.metersphere.dto.ProjectDTO;
|
||||
import org.apache.ibatis.annotations.MapKey;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ExtProjectMapper {
|
||||
|
||||
|
@ -21,4 +24,7 @@ public interface ExtProjectMapper {
|
|||
List<String> getProjectIds();
|
||||
|
||||
String getMaxSystemId();
|
||||
|
||||
@MapKey("id")
|
||||
Map<String, Project> queryNameByIds(@Param("ids") List<String> ids);
|
||||
}
|
||||
|
|
|
@ -117,7 +117,15 @@
|
|||
<select id="getMaxSystemId" resultType="java.lang.String">
|
||||
SELECT max(system_id) FROM project
|
||||
</select>
|
||||
|
||||
<select id="queryNameByIds" resultType="io.metersphere.base.domain.Project">
|
||||
select id, name, custom_num
|
||||
from project
|
||||
WHERE id IN
|
||||
<foreach collection="ids" item="id" index="index"
|
||||
open="(" close=")" separator=",">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<update id="removeIssuePlatform">
|
||||
update project
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
import io.metersphere.api.dto.automation.TestPlanFailureApiDTO;
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
||||
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
|
||||
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
|
||||
import io.metersphere.base.domain.TestPlanApiCase;
|
||||
import io.metersphere.track.dto.PlanReportCaseDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -25,5 +27,11 @@ public interface ExtTestPlanApiCaseMapper {
|
|||
|
||||
ApiTestCaseWithBLOBs getApiTestCaseById(String testPlanApiCaseId);
|
||||
|
||||
|
||||
List<TestPlanApiCase> selectLegalDataByTestPlanId(String planId);
|
||||
}
|
||||
|
||||
List<PlanReportCaseDTO> selectForPlanReport(String planId);
|
||||
|
||||
List<TestPlanFailureApiDTO> getFailureList(String planId);
|
||||
}
|
||||
|
||||
|
|
|
@ -245,5 +245,22 @@
|
|||
<select id="getStatusByTestPlanId" resultType="java.lang.String">
|
||||
SELECT `status` FROM test_plan_api_case WHERE test_plan_id = #{0}
|
||||
</select>
|
||||
<select id="selectForPlanReport" resultType="io.metersphere.track.dto.PlanReportCaseDTO">
|
||||
select id,status from test_plan_api_case where test_plan_id = #{planId};
|
||||
</select>
|
||||
<select id="getFailureList" resultType="io.metersphere.api.dto.automation.TestPlanFailureApiDTO">
|
||||
select
|
||||
t.id,
|
||||
c.id as case_id, c.project_id, c.name, c.api_definition_id, c.priority, c.create_user_id,
|
||||
c.num,t.create_user,
|
||||
t.status execResult
|
||||
from
|
||||
test_plan_api_case t
|
||||
inner join
|
||||
api_test_case c
|
||||
on t.api_case_id = c.id
|
||||
and t.test_plan_id = #{request.planId} and t.status = 'error'
|
||||
where t.test_plan_id = #{planId};
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
import io.metersphere.track.dto.PlanReportCaseDTO;
|
||||
import io.metersphere.track.dto.TestPlanLoadCaseDTO;
|
||||
import io.metersphere.track.request.testplan.LoadCaseRequest;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
@ -20,4 +21,8 @@ public interface ExtTestPlanLoadCaseMapper {
|
|||
List<String> getStatusByTestPlanId(@Param("planId") String planId);
|
||||
|
||||
List<String> selectTestPlanLoadCaseId(@Param("request") LoadCaseRequest request);
|
||||
|
||||
List<PlanReportCaseDTO> selectForPlanReport(String planId);
|
||||
|
||||
List<TestPlanLoadCaseDTO> getFailureCases(String planId);
|
||||
}
|
||||
|
|
|
@ -175,4 +175,14 @@
|
|||
<select id="getStatusByTestPlanId" resultType="java.lang.String">
|
||||
select status from test_plan_load_case tplc where tplc.test_plan_id = #{planId}
|
||||
</select>
|
||||
<select id="selectForPlanReport" resultType="io.metersphere.track.dto.PlanReportCaseDTO">
|
||||
select id,status from test_plan_load_case where test_plan_id = #{planId};
|
||||
</select>
|
||||
<select id="getFailureCases" resultType="io.metersphere.track.dto.TestPlanLoadCaseDTO">
|
||||
select tplc.id, lt.id as caseId, lt.name, lt.num, lt.project_id,
|
||||
tplc.status ,tplc.create_user
|
||||
from test_plan_load_case tplc
|
||||
inner join load_test lt on tplc.load_case_id = lt.id and tplc.status = 'error'
|
||||
where tplc.test_plan_id = #{planId}
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
import io.metersphere.api.dto.automation.ApiScenarioDTO;
|
||||
import io.metersphere.api.dto.automation.TestPlanFailureScenarioDTO;
|
||||
import io.metersphere.api.dto.automation.TestPlanScenarioRequest;
|
||||
import io.metersphere.base.domain.TestPlanApiScenario;
|
||||
import io.metersphere.track.dto.PlanReportCaseDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -23,4 +25,10 @@ public interface ExtTestPlanScenarioCaseMapper {
|
|||
List<TestPlanApiScenario> selectByIds(@Param("ids")String ids ,@Param("oderId")String oderId );
|
||||
|
||||
List<TestPlanApiScenario> selectLegalDataByTestPlanId(String planId);
|
||||
}
|
||||
|
||||
List<PlanReportCaseDTO> selectForPlanReport(String planId);
|
||||
|
||||
List<TestPlanFailureScenarioDTO> getFailureList(String planId);
|
||||
|
||||
List<Integer> getUnderwaySteps(@Param("ids") List<String> underwayIds);
|
||||
}
|
||||
|
|
|
@ -195,5 +195,28 @@
|
|||
</if>
|
||||
where t.test_plan_id = #{planId}
|
||||
</select>
|
||||
<select id="selectForPlanReport" resultType="io.metersphere.track.dto.PlanReportCaseDTO">
|
||||
select id,last_result as status, report_id, api_scenario_id as caseId from test_plan_api_scenario where test_plan_id = #{planId};
|
||||
</select>
|
||||
<select id="getFailureList" resultType="io.metersphere.api.dto.automation.TestPlanFailureScenarioDTO">
|
||||
select
|
||||
t.id, t.last_result, t.report_id, c.user_id, c.module_path, c.name, c.level,
|
||||
c.status,c.step_total, c.step_total, c.project_id,
|
||||
c.num, c.custom_num
|
||||
from
|
||||
test_plan_api_scenario t
|
||||
inner join
|
||||
api_scenario c
|
||||
on t.api_scenario_id = c.id and c.status != 'Trash'
|
||||
and t.test_plan_id = #{request.planId} and t.last_result = 'Fail'
|
||||
where t.test_plan_id = #{request.planId}
|
||||
</select>
|
||||
<select id="getUnderwaySteps" resultType="java.lang.Integer">
|
||||
select step_total from api_scenario c
|
||||
where c.id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.metersphere.base.mapper.ext;
|
||||
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import io.metersphere.track.dto.PlanReportCaseDTO;
|
||||
import io.metersphere.track.dto.TestCaseReportStatusResultDTO;
|
||||
import io.metersphere.track.dto.TestCaseTestDTO;
|
||||
import io.metersphere.track.dto.TestPlanCaseDTO;
|
||||
|
@ -57,4 +58,8 @@ public interface ExtTestPlanTestCaseMapper {
|
|||
List<String> selectIdsByQuery(@Param("request") BaseQueryRequest query);
|
||||
|
||||
void update(@Param("count") int count, @Param("id") String id, @Param("caseId") String caseId, @Param("issues") String issues);
|
||||
|
||||
List<PlanReportCaseDTO> selectForPlanReport(String planId);
|
||||
|
||||
List<TestPlanCaseDTO> getFailureCases(String planId);
|
||||
}
|
||||
|
|
|
@ -463,6 +463,19 @@
|
|||
<include refid="queryWhereCondition"/>
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
|
||||
</select>
|
||||
<select id="selectForPlanReport" resultType="io.metersphere.track.dto.PlanReportCaseDTO">
|
||||
select id,status from test_plan_test_case where plan_id = #{planId};
|
||||
</select>
|
||||
<select id="getFailureCases" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
|
||||
select tptc.id, tc.id as caseId, tc.name, tc.priority, tc.num, tc.custom_num, tc.project_id,
|
||||
tc.node_id, tc.tags, tptc.actual_result,
|
||||
tptc.update_time, tptc.create_time,
|
||||
tptc.issues_count,
|
||||
tptc.plan_id, tptc.executor
|
||||
from test_plan_test_case tptc
|
||||
inner join test_case tc on tptc.case_id = tc.id and tptc.status = 'Failure'
|
||||
where tptc.plan_id = #{planId}
|
||||
</select>
|
||||
<update id="updateTestCaseStates" parameterType="java.lang.String">
|
||||
update test_plan_test_case
|
||||
<set>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package io.metersphere.commons.utils;
|
||||
|
||||
import io.metersphere.base.domain.Project;
|
||||
import io.metersphere.base.domain.User;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.controller.request.BaseQueryRequest;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import io.metersphere.service.ProjectService;
|
||||
import io.metersphere.service.UserService;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
|
@ -72,4 +74,22 @@ public class ServiceUtils {
|
|||
});
|
||||
return nameMap;
|
||||
}
|
||||
|
||||
public static Map<String, Project> getProjectMap(List<String> ids) {
|
||||
ProjectService projectService = CommonBeanFactory.getBean(ProjectService.class);
|
||||
if (!CollectionUtils.isEmpty(ids)) {
|
||||
Map<String, Project> projectMap = projectService.queryNameByIds(ids);
|
||||
return projectMap;
|
||||
}
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
public static Map<String, String> getProjectNameMap(List<String> ids) {
|
||||
Map<String, Project> projectMap = getProjectMap(ids);
|
||||
HashMap<String, String> nameMap = new HashMap<>();
|
||||
projectMap.forEach((k, v) -> {
|
||||
nameMap.put(k, v.getName());
|
||||
});
|
||||
return nameMap;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package io.metersphere.commons.utils;
|
||||
|
||||
import io.metersphere.commons.constants.TestPlanTestCaseStatus;
|
||||
import io.metersphere.track.dto.PlanReportCaseDTO;
|
||||
import io.metersphere.track.dto.TestCaseReportStatusResultDTO;
|
||||
import io.metersphere.track.dto.TestPlanSimpleReportDTO;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TestPlanUtils {
|
||||
|
||||
|
||||
public static void getStatusResultMap(Map<String, TestCaseReportStatusResultDTO> reportStatusResultMap, String result) {
|
||||
if (StringUtils.isBlank(result)) {
|
||||
result = TestPlanTestCaseStatus.Prepare.name();
|
||||
}
|
||||
TestCaseReportStatusResultDTO statusResult = reportStatusResultMap.get(result);
|
||||
if (statusResult == null) {
|
||||
statusResult = new TestCaseReportStatusResultDTO();
|
||||
statusResult.setStatus(result);
|
||||
statusResult.setCount(0);
|
||||
}
|
||||
statusResult.setCount(statusResult.getCount() + 1);
|
||||
reportStatusResultMap.put(result, statusResult);
|
||||
}
|
||||
|
||||
public static void addToReportStatusResultList(Map<String, TestCaseReportStatusResultDTO> resultMap,
|
||||
List<TestCaseReportStatusResultDTO> reportStatusResultList, String status) {
|
||||
if (resultMap.get(status) != null) {
|
||||
reportStatusResultList.add(resultMap.get(status));
|
||||
} else if (StringUtils.isBlank(status) && resultMap.get(TestPlanTestCaseStatus.Prepare.name()) != null) {
|
||||
reportStatusResultList.add(resultMap.get(TestPlanTestCaseStatus.Prepare.name()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void addToReportCommonStatusResultList(Map<String, TestCaseReportStatusResultDTO> resultMap,
|
||||
List<TestCaseReportStatusResultDTO> statusResult) {
|
||||
addToReportStatusResultList(resultMap, statusResult, TestPlanTestCaseStatus.Pass.name());
|
||||
addToReportStatusResultList(resultMap, statusResult, TestPlanTestCaseStatus.Failure.name());
|
||||
addToReportStatusResultList(resultMap, statusResult, "error");
|
||||
addToReportStatusResultList(resultMap, statusResult, "Fail");
|
||||
addToReportStatusResultList(resultMap, statusResult, "success");
|
||||
addToReportStatusResultList(resultMap, statusResult, "Success");
|
||||
addToReportStatusResultList(resultMap, statusResult, TestPlanTestCaseStatus.Prepare.name());
|
||||
}
|
||||
|
||||
public static void calculatePlanReport(List<PlanReportCaseDTO> planReportCaseDTOS,
|
||||
Map<String, TestCaseReportStatusResultDTO> statusResultMap,
|
||||
TestPlanSimpleReportDTO report, String successStatus) {
|
||||
planReportCaseDTOS.forEach(item -> {
|
||||
report.setCaseCount(report.getCaseCount() + 1);
|
||||
String status = item.getStatus();
|
||||
if (StringUtils.isNotBlank(status) && !StringUtils.equals(TestPlanTestCaseStatus.Underway.name(), status)) {
|
||||
report.setExecuteCount(report.getExecuteCount() + 1);
|
||||
if (StringUtils.equals(successStatus, status)) {
|
||||
report.setPassCount(report.getPassCount() + 1);
|
||||
}
|
||||
}
|
||||
TestPlanUtils.getStatusResultMap(statusResultMap, status);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -40,10 +40,7 @@ import org.springframework.web.multipart.MultipartFile;
|
|||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
|
@ -482,4 +479,8 @@ public class ProjectService {
|
|||
public List<String> getProjectIds() {
|
||||
return extProjectMapper.getProjectIds();
|
||||
}
|
||||
|
||||
public Map<String, Project> queryNameByIds(List<String> ids) {
|
||||
return extProjectMapper.queryNameByIds(ids);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,11 @@ public class IssuesController {
|
|||
return issuesService.getIssues(id);
|
||||
}
|
||||
|
||||
@GetMapping("/plan/get/{planId}")
|
||||
public List<IssuesDao> getIssuesByPlanoId(@PathVariable String planId) {
|
||||
return issuesService.getIssuesByPlanoId(planId);
|
||||
}
|
||||
|
||||
@GetMapping("/auth/{orgId}/{platform}")
|
||||
public void testAuth(@PathVariable String orgId, @PathVariable String platform) {
|
||||
issuesService.testAuth(orgId, platform);
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.track.controller;
|
|||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.api.dto.automation.TestPlanFailureApiDTO;
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
||||
import io.metersphere.api.dto.definition.BatchRunDefinitionRequest;
|
||||
|
@ -32,6 +33,11 @@ public class TestPlanApiCaseController {
|
|||
return PageUtils.setPageInfo(page, testPlanApiCaseService.list(request));
|
||||
}
|
||||
|
||||
@GetMapping("/list/failure/{planId}")
|
||||
public List<TestPlanFailureApiDTO> getFailureList(@PathVariable String planId) {
|
||||
return testPlanApiCaseService.getFailureList(planId);
|
||||
}
|
||||
|
||||
@PostMapping("/selectAllTableRows")
|
||||
public List<TestPlanApiCaseDTO> selectAllTableRows(@RequestBody TestPlanApiCaseBatchRequest request) {
|
||||
return testPlanApiCaseService.selectAllTableRows(request);
|
||||
|
|
|
@ -5,16 +5,14 @@ import com.github.pagehelper.Page;
|
|||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.base.domain.Project;
|
||||
import io.metersphere.base.domain.TestPlan;
|
||||
import io.metersphere.base.domain.TestPlanWithBLOBs;
|
||||
import io.metersphere.commons.constants.OperLogConstants;
|
||||
import io.metersphere.commons.constants.PermissionConstants;
|
||||
import io.metersphere.commons.utils.PageUtils;
|
||||
import io.metersphere.commons.utils.Pager;
|
||||
import io.metersphere.log.annotation.MsAuditLog;
|
||||
import io.metersphere.service.CheckPermissionService;
|
||||
import io.metersphere.track.dto.ApiRunConfigDTO;
|
||||
import io.metersphere.track.dto.TestCaseReportMetricDTO;
|
||||
import io.metersphere.track.dto.TestPlanDTO;
|
||||
import io.metersphere.track.dto.TestPlanDTOWithMetric;
|
||||
import io.metersphere.track.dto.*;
|
||||
import io.metersphere.track.request.testcase.PlanCaseRelevanceRequest;
|
||||
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
|
||||
import io.metersphere.track.request.testplan.AddTestPlanRequest;
|
||||
|
@ -173,4 +171,19 @@ public class TestPlanController {
|
|||
public void exportHtmlReport(@PathVariable String planId, HttpServletResponse response) throws UnsupportedEncodingException {
|
||||
testPlanService.exportPlanReport(planId, response);
|
||||
}
|
||||
|
||||
@GetMapping("/report/{planId}")
|
||||
public TestPlanSimpleReportDTO getReport(@PathVariable String planId){
|
||||
return testPlanService.getReport(planId);
|
||||
}
|
||||
|
||||
@GetMapping("/report/functional/result")
|
||||
public TestCaseReportStatusResultDTO getFunctionalResultReport(@PathVariable String planId){
|
||||
return testPlanService.getFunctionalResultReport(planId);
|
||||
}
|
||||
|
||||
@PostMapping("/edit/report")
|
||||
public void editReport(@RequestBody TestPlanWithBLOBs testPlanWithBLOBs) {
|
||||
testPlanService.editReport(testPlanWithBLOBs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,4 +90,9 @@ public class TestPlanLoadCaseController {
|
|||
public void updateByApi(@RequestBody TestPlanLoadCase testPlanLoadCase) {
|
||||
testPlanLoadCaseService.updateByApi(testPlanLoadCase);
|
||||
}
|
||||
|
||||
@GetMapping("/list/failure/{planId}")
|
||||
public List<TestPlanLoadCaseDTO> getFailureCases(@PathVariable String planId) {
|
||||
return testPlanLoadCaseService.getFailureCases(planId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,11 @@ public class TestPlanScenarioCaseController {
|
|||
return PageUtils.setPageInfo(page, testPlanScenarioCaseService.list(request));
|
||||
}
|
||||
|
||||
@GetMapping("/list/failure/{planId}")
|
||||
public List<TestPlanFailureScenarioDTO> getFailureList(@PathVariable String planId) {
|
||||
return testPlanScenarioCaseService.getFailureList(planId);
|
||||
}
|
||||
|
||||
@PostMapping("/selectAllTableRows")
|
||||
public List<ApiScenarioDTO> selectAllTableRows(@RequestBody TestPlanScenarioCaseBatchRequest request) {
|
||||
return testPlanScenarioCaseService.selectAllTableRows(request);
|
||||
|
|
|
@ -130,4 +130,8 @@ public class TestPlanTestCaseController {
|
|||
return testPlanTestCaseService.deleteTestCase(id);
|
||||
}
|
||||
|
||||
@GetMapping("/list/failure/{planId}")
|
||||
public List<TestPlanCaseDTO> getFailureCases(@PathVariable String planId) {
|
||||
return testPlanTestCaseService.getFailureCases(planId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package io.metersphere.track.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class PlanReportCaseDTO {
|
||||
public String id;
|
||||
public String status;
|
||||
public String reportId;
|
||||
public String caseId;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package io.metersphere.track.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class PlanReportIssueDTO extends PlanReportCaseDTO {
|
||||
private String platformStatus;
|
||||
private String platform;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package io.metersphere.track.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class TestPlanApiResultReportDTO {
|
||||
private List<TestCaseReportStatusResultDTO> apiCaseData;
|
||||
private List<TestCaseReportStatusResultDTO> apiScenarioData;
|
||||
private List<TestCaseReportStatusResultDTO> apiScenarioStepData;
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ public class TestPlanCaseDTO extends TestCaseWithBLOBs {
|
|||
private String projectName;
|
||||
private String actualResult;
|
||||
private String maintainerName;
|
||||
private Boolean isCustomNum;
|
||||
private int issuesCount;
|
||||
|
||||
private List<TestCaseTestDTO> list;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.metersphere.track.dto;
|
||||
|
||||
import io.metersphere.base.domain.TestPlan;
|
||||
import io.metersphere.base.domain.TestPlanWithBLOBs;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
|
@ -8,7 +8,7 @@ import java.util.List;
|
|||
|
||||
@Getter
|
||||
@Setter
|
||||
public class TestPlanDTO extends TestPlan {
|
||||
public class TestPlanDTO extends TestPlanWithBLOBs {
|
||||
private String projectName;
|
||||
private String userName;
|
||||
private List<String> projectIds;
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package io.metersphere.track.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class TestPlanFunctionResultReportDTO {
|
||||
private List<TestCaseReportStatusResultDTO> caseData;
|
||||
private List<TestCaseReportStatusResultDTO> issueData;
|
||||
}
|
||||
|
|
@ -12,4 +12,5 @@ public class TestPlanLoadCaseDTO extends TestPlanLoadCase {
|
|||
private String projectName;
|
||||
private String caseStatus;
|
||||
private String num;
|
||||
private String name;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package io.metersphere.track.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class TestPlanLoadResultReportDTO {
|
||||
private List<TestCaseReportStatusResultDTO> caseData;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package io.metersphere.track.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class TestPlanScenarioStepCountDTO {
|
||||
private int scenarioStepTotal;
|
||||
private int scenarioStepSuccess;
|
||||
private int scenarioStepError;
|
||||
private List<String> underwayIds = new ArrayList<>();
|
||||
private int scenarioStepUnderway;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package io.metersphere.track.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class TestPlanSimpleReportDTO {
|
||||
private Long startTime;
|
||||
private Long endTime;
|
||||
private int caseCount;
|
||||
private int executeCount;
|
||||
private int passCount;
|
||||
private double executeRate;
|
||||
private double passRate;
|
||||
private String summary;
|
||||
private TestPlanFunctionResultReportDTO functionResult;
|
||||
private TestPlanApiResultReportDTO apiResult;
|
||||
private TestPlanLoadResultReportDTO loadResult;
|
||||
}
|
|
@ -73,7 +73,7 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
issuesRequest.setPlatform(IssuesManagePlatform.Jira.toString());
|
||||
List<IssuesDao> issues;
|
||||
if (StringUtils.isNotBlank(issuesRequest.getProjectId())) {
|
||||
issues = extIssuesMapper.getIssuesByProjectId(issuesRequest);
|
||||
issues = extIssuesMapper.getIssues(issuesRequest);
|
||||
} else {
|
||||
issues = extIssuesMapper.getIssuesByCaseId(issuesRequest);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public class LocalPlatform extends LocalAbstractPlatform {
|
|||
String projectId = issuesRequest.getProjectId();
|
||||
issuesRequest.setPlatform(IssuesManagePlatform.Local.toString());
|
||||
if (StringUtils.isNotBlank(projectId)) {
|
||||
return extIssuesMapper.getIssuesByProjectId(issuesRequest);
|
||||
return extIssuesMapper.getIssues(issuesRequest);
|
||||
}
|
||||
return extIssuesMapper.getIssuesByCaseId(issuesRequest);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
issuesRequest.setPlatform(IssuesManagePlatform.Tapd.toString());
|
||||
List<IssuesDao> issues;
|
||||
if (StringUtils.isNotBlank(issuesRequest.getProjectId())) {
|
||||
issues = extIssuesMapper.getIssuesByProjectId(issuesRequest);
|
||||
issues = extIssuesMapper.getIssues(issuesRequest);
|
||||
} else {
|
||||
issues = extIssuesMapper.getIssuesByCaseId(issuesRequest);
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
issuesRequest.setPlatform(IssuesManagePlatform.Zentao.toString());
|
||||
List<IssuesDao> issues;
|
||||
if (StringUtils.isNotBlank(issuesRequest.getProjectId())) {
|
||||
issues = extIssuesMapper.getIssuesByProjectId(issuesRequest);
|
||||
issues = extIssuesMapper.getIssues(issuesRequest);
|
||||
} else {
|
||||
issues = extIssuesMapper.getIssuesByCaseId(issuesRequest);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ public class IssuesRequest extends BaseQueryRequest {
|
|||
*/
|
||||
private String id;
|
||||
private String caseId;
|
||||
private String resourceId;
|
||||
private String platform;
|
||||
private String customFields;
|
||||
private List<String> testCaseIds;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.metersphere.track.request.testplan;
|
||||
|
||||
import io.metersphere.base.domain.TestPlan;
|
||||
import io.metersphere.base.domain.TestPlanWithBLOBs;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
|
@ -8,6 +8,6 @@ import java.util.List;
|
|||
|
||||
@Getter
|
||||
@Setter
|
||||
public class AddTestPlanRequest extends TestPlan {
|
||||
public class AddTestPlanRequest extends TestPlanWithBLOBs {
|
||||
private List<String> projectIds;
|
||||
}
|
||||
|
|
|
@ -7,13 +7,12 @@ import io.metersphere.base.domain.*;
|
|||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.ExtIssuesMapper;
|
||||
import io.metersphere.commons.constants.IssuesManagePlatform;
|
||||
import io.metersphere.commons.constants.IssuesStatus;
|
||||
import io.metersphere.commons.constants.NoticeConstants;
|
||||
import io.metersphere.commons.constants.TestPlanTestCaseStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.user.SessionUser;
|
||||
import io.metersphere.commons.utils.BeanUtils;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.commons.utils.*;
|
||||
import io.metersphere.controller.request.IntegrationRequest;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.log.utils.ReflexObjectUtil;
|
||||
|
@ -26,6 +25,7 @@ import io.metersphere.service.IntegrationService;
|
|||
import io.metersphere.service.IssueTemplateService;
|
||||
import io.metersphere.service.ProjectService;
|
||||
import io.metersphere.service.SystemParameterService;
|
||||
import io.metersphere.track.dto.*;
|
||||
import io.metersphere.track.issue.*;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.issue.domain.zentao.ZentaoBuild;
|
||||
|
@ -46,6 +46,7 @@ import java.util.ArrayList;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -181,16 +182,13 @@ public class IssuesService {
|
|||
}
|
||||
|
||||
public List<IssuesDao> getIssuesByProject(IssuesRequest issueRequest, Project project) {
|
||||
List<IssuesDao> list = new ArrayList<>();
|
||||
List<String> platforms = getPlatforms(project);
|
||||
platforms.add(IssuesManagePlatform.Local.toString());
|
||||
List<AbstractIssuePlatform> platformList = IssueFactory.createPlatforms(platforms, issueRequest);
|
||||
platformList.forEach(platform -> {
|
||||
List<IssuesDao> issue = platform.getIssue(issueRequest);
|
||||
list.addAll(issue);
|
||||
});
|
||||
|
||||
return list;
|
||||
List<IssuesDao> issues;
|
||||
if (StringUtils.isNotBlank(issueRequest.getProjectId())) {
|
||||
issues = extIssuesMapper.getIssues(issueRequest);
|
||||
} else {
|
||||
issues = extIssuesMapper.getIssuesByCaseId(issueRequest);
|
||||
}
|
||||
return issues;
|
||||
}
|
||||
|
||||
public String getPlatformsByCaseId(String caseId) {
|
||||
|
@ -343,7 +341,7 @@ public class IssuesService {
|
|||
|
||||
public List<IssuesDao> list(IssuesRequest request) {
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
List<IssuesDao> issues = extIssuesMapper.getIssuesByProjectId(request);
|
||||
List<IssuesDao> issues = extIssuesMapper.getIssues(request);
|
||||
|
||||
List<String> ids = issues.stream()
|
||||
.map(IssuesDao::getCreator)
|
||||
|
@ -548,4 +546,37 @@ public class IssuesService {
|
|||
AbstractIssuePlatform abstractPlatform = IssueFactory.createPlatform(authUserIssueRequest.getPlatform(), issuesRequest);
|
||||
abstractPlatform.userAuth(authUserIssueRequest);
|
||||
}
|
||||
|
||||
public void calculatePlanReport(String planId, TestPlanSimpleReportDTO report) {
|
||||
List<PlanReportIssueDTO> planReportIssueDTOS = extIssuesMapper.selectForPlanReport(planId);
|
||||
TestPlanFunctionResultReportDTO functionResult = report.getFunctionResult();
|
||||
List<TestCaseReportStatusResultDTO> statusResult = new ArrayList<>();
|
||||
Map<String, TestCaseReportStatusResultDTO> statusResultMap = new HashMap<>();
|
||||
|
||||
planReportIssueDTOS.forEach(item -> {
|
||||
String status = null;
|
||||
// 本地缺陷
|
||||
if (StringUtils.equalsIgnoreCase(item.getPlatform(), IssuesManagePlatform.Local.name())
|
||||
|| StringUtils.isBlank(item.getPlatform())) {
|
||||
status = item.getStatus();
|
||||
} else {
|
||||
status = item.getPlatformStatus();
|
||||
}
|
||||
if (StringUtils.isBlank(status)) {
|
||||
status = IssuesStatus.NEW.toString();
|
||||
}
|
||||
TestPlanUtils.getStatusResultMap(statusResultMap, status);
|
||||
});
|
||||
Set<String> status = statusResultMap.keySet();
|
||||
status.forEach(item -> {
|
||||
TestPlanUtils.addToReportStatusResultList(statusResultMap, statusResult, item);
|
||||
});
|
||||
functionResult.setIssueData(statusResult);
|
||||
}
|
||||
|
||||
public List<IssuesDao> getIssuesByPlanoId(String planId) {
|
||||
IssuesRequest issueRequest = new IssuesRequest();
|
||||
issueRequest.setResourceId(planId);
|
||||
return extIssuesMapper.getIssues(issueRequest);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
package io.metersphere.track.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import io.metersphere.base.domain.TestCaseReport;
|
||||
import io.metersphere.base.domain.TestCaseReportExample;
|
||||
import io.metersphere.base.domain.TestCaseReportTemplate;
|
||||
import io.metersphere.base.domain.TestPlan;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.TestCaseReportMapper;
|
||||
import io.metersphere.base.mapper.TestCaseReportTemplateMapper;
|
||||
import io.metersphere.base.mapper.TestPlanMapper;
|
||||
|
@ -69,7 +66,7 @@ public class TestCaseReportService {
|
|||
TestCaseReportTemplate template = testCaseReportTemplateMapper.selectByPrimaryKey(request.getTemplateId());
|
||||
TestCaseReport report = new TestCaseReport();
|
||||
BeanUtils.copyBean(report, template);
|
||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(request.getPlanId());
|
||||
TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(request.getPlanId());
|
||||
report.setName(testPlan.getName());
|
||||
report.setId(request.getId());
|
||||
report.setCreateUser(SessionUtils.getUserId());
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.api.dto.RunModeDataDTO;
|
||||
import io.metersphere.api.dto.automation.TestPlanFailureApiDTO;
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseDTO;
|
||||
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
|
||||
import io.metersphere.api.dto.definition.BatchRunDefinitionRequest;
|
||||
|
@ -29,15 +30,13 @@ import io.metersphere.base.mapper.ApiTestCaseMapper;
|
|||
import io.metersphere.base.mapper.TestPlanApiCaseMapper;
|
||||
import io.metersphere.base.mapper.TestPlanMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtTestPlanApiCaseMapper;
|
||||
import io.metersphere.commons.constants.APITestStatus;
|
||||
import io.metersphere.commons.constants.ApiRunMode;
|
||||
import io.metersphere.commons.constants.RunModeConstants;
|
||||
import io.metersphere.commons.constants.TriggerMode;
|
||||
import io.metersphere.commons.constants.*;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.*;
|
||||
import io.metersphere.dto.BaseSystemConfigDTO;
|
||||
import io.metersphere.log.vo.OperatingLogDetails;
|
||||
import io.metersphere.service.SystemParameterService;
|
||||
import io.metersphere.track.dto.*;
|
||||
import io.metersphere.track.request.testcase.TestPlanApiCaseBatchRequest;
|
||||
import io.metersphere.track.service.task.ParallelApiExecTask;
|
||||
import io.metersphere.track.service.task.SerialApiExecTask;
|
||||
|
@ -496,4 +495,27 @@ public class TestPlanApiCaseService {
|
|||
public ApiTestCaseWithBLOBs getApiTestCaseById(String testPlanApiCaseId) {
|
||||
return extTestPlanApiCaseMapper.getApiTestCaseById(testPlanApiCaseId);
|
||||
}
|
||||
|
||||
public void calculatePlanReport(String planId, TestPlanSimpleReportDTO report) {
|
||||
List<PlanReportCaseDTO> planReportCaseDTOS = extTestPlanApiCaseMapper.selectForPlanReport(planId);
|
||||
|
||||
TestPlanApiResultReportDTO apiResult = report.getApiResult();
|
||||
List<TestCaseReportStatusResultDTO> statusResult = new ArrayList<>();
|
||||
Map<String, TestCaseReportStatusResultDTO> statusResultMap = new HashMap<>();
|
||||
|
||||
TestPlanUtils.calculatePlanReport(planReportCaseDTOS, statusResultMap, report, "success");
|
||||
|
||||
TestPlanUtils.addToReportCommonStatusResultList(statusResultMap, statusResult);
|
||||
|
||||
apiResult.setApiCaseData(statusResult);
|
||||
}
|
||||
|
||||
public List<TestPlanFailureApiDTO> getFailureList(String planId) {
|
||||
List<TestPlanFailureApiDTO> apiTestCases = extTestPlanApiCaseMapper.getFailureList(planId);
|
||||
if (CollectionUtils.isEmpty(apiTestCases)) {
|
||||
return apiTestCases;
|
||||
}
|
||||
buildUserInfo(apiTestCases);
|
||||
return apiTestCases;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,12 +10,14 @@ import io.metersphere.base.mapper.ext.ExtTestPlanLoadCaseMapper;
|
|||
import io.metersphere.commons.constants.RunModeConstants;
|
||||
import io.metersphere.commons.constants.TestPlanStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.commons.utils.TestPlanUtils;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import io.metersphere.log.vo.OperatingLogDetails;
|
||||
import io.metersphere.performance.request.RunTestPlanRequest;
|
||||
import io.metersphere.performance.service.PerformanceTestService;
|
||||
import io.metersphere.track.dto.TestPlanLoadCaseDTO;
|
||||
import io.metersphere.track.dto.*;
|
||||
import io.metersphere.track.request.testplan.LoadCaseReportBatchRequest;
|
||||
import io.metersphere.track.request.testplan.LoadCaseReportRequest;
|
||||
import io.metersphere.track.request.testplan.LoadCaseRequest;
|
||||
|
@ -23,18 +25,15 @@ import io.metersphere.track.request.testplan.RunBatchTestPlanRequest;
|
|||
import io.metersphere.track.service.utils.ParallelExecTask;
|
||||
import io.metersphere.track.service.utils.SerialExecTask;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
@ -351,4 +350,30 @@ public class TestPlanLoadCaseService {
|
|||
example.createCriteria().andTestPlanIdEqualTo(planId);
|
||||
testPlanLoadCaseMapper.deleteByExample(example);
|
||||
}
|
||||
|
||||
public void calculatePlanReport(String planId, TestPlanSimpleReportDTO report) {
|
||||
List<PlanReportCaseDTO> planReportCaseDTOS = extTestPlanLoadCaseMapper.selectForPlanReport(planId);
|
||||
TestPlanLoadResultReportDTO loadResult = new TestPlanLoadResultReportDTO();
|
||||
report.setLoadResult(loadResult);
|
||||
List<TestCaseReportStatusResultDTO> statusResult = new ArrayList<>();
|
||||
Map<String, TestCaseReportStatusResultDTO> statusResultMap = new HashMap<>();
|
||||
|
||||
TestPlanUtils.calculatePlanReport(planReportCaseDTOS, statusResultMap, report, "success");
|
||||
TestPlanUtils.addToReportCommonStatusResultList(statusResultMap, statusResult);
|
||||
|
||||
loadResult.setCaseData(statusResult);
|
||||
}
|
||||
|
||||
public List<TestPlanLoadCaseDTO> getFailureCases(String planId) {
|
||||
List<TestPlanLoadCaseDTO> failureCases = extTestPlanLoadCaseMapper.getFailureCases(planId);
|
||||
// Map<String, Project> projectMap = ServiceUtils.getProjectMap(
|
||||
// failureCases.stream().map(TestPlanCaseDTO::getProjectId).collect(Collectors.toList()));
|
||||
Map<String, String> userNameMap = ServiceUtils.getUserNameMap(
|
||||
failureCases.stream().map(TestPlanLoadCaseDTO::getCreateUser).collect(Collectors.toList()));
|
||||
failureCases.forEach(item -> {
|
||||
// item.setProjectName(projectMap.get(item.getProjectId()).getName());
|
||||
item.setUserName(userNameMap.get(item.getCreateUser()));
|
||||
});
|
||||
return failureCases;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ public class TestPlanReportService {
|
|||
* saveRequest.performanceIsExecuting 性能案例是否执行中
|
||||
*/
|
||||
public TestPlanReport genTestPlanReport(TestPlanReportSaveRequest saveRequest) {
|
||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(saveRequest.getPlanId());
|
||||
TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(saveRequest.getPlanId());
|
||||
String testPlanReportID = saveRequest.getReportID();
|
||||
TestPlanReport testPlanReport = new TestPlanReport();
|
||||
testPlanReport.setTestPlanId(saveRequest.getPlanId());
|
||||
|
@ -916,7 +916,7 @@ public class TestPlanReportService {
|
|||
if (!report.getIsApiCaseExecuting() && !report.getIsPerformanceExecuting() && !report.getIsScenarioExecuting()) {
|
||||
try {
|
||||
//更新TestPlan状态为完成
|
||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(report.getTestPlanId());
|
||||
TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(report.getTestPlanId());
|
||||
if (testPlan != null) {
|
||||
testPlan.setStatus(TestPlanStatus.Completed.name());
|
||||
testPlanMapper.updateByPrimaryKeySelective(testPlan);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.metersphere.track.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.automation.*;
|
||||
import io.metersphere.api.service.ApiAutomationService;
|
||||
import io.metersphere.api.service.ApiScenarioReportService;
|
||||
|
@ -12,10 +13,12 @@ import io.metersphere.base.mapper.TestPlanMapper;
|
|||
import io.metersphere.base.mapper.ext.ExtTestPlanScenarioCaseMapper;
|
||||
import io.metersphere.commons.constants.ApiRunMode;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.constants.TestPlanTestCaseStatus;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.commons.utils.TestPlanUtils;
|
||||
import io.metersphere.log.vo.OperatingLogDetails;
|
||||
import io.metersphere.service.ProjectService;
|
||||
import io.metersphere.track.dto.RelevanceScenarioRequest;
|
||||
import io.metersphere.track.dto.*;
|
||||
import io.metersphere.track.request.testcase.TestPlanScenarioCaseBatchRequest;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -51,6 +54,15 @@ public class TestPlanScenarioCaseService {
|
|||
request.setProjectId(null);
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
List<ApiScenarioDTO> apiTestCases = extTestPlanScenarioCaseMapper.list(request);
|
||||
if (CollectionUtils.isEmpty(apiTestCases)) {
|
||||
return apiTestCases;
|
||||
}
|
||||
buildProjectInfo(apiTestCases);
|
||||
buildUserInfo(apiTestCases);
|
||||
return apiTestCases;
|
||||
}
|
||||
|
||||
public void buildProjectInfo(List<? extends ApiScenarioDTO> apiTestCases) {
|
||||
List<String> projectIds = apiTestCases.stream()
|
||||
.map(ApiScenarioDTO::getProjectId)
|
||||
.collect(Collectors.toSet())
|
||||
|
@ -67,12 +79,6 @@ public class TestPlanScenarioCaseService {
|
|||
item.setCustomNum(item.getNum().toString());
|
||||
}
|
||||
});
|
||||
|
||||
if (CollectionUtils.isEmpty(apiTestCases)) {
|
||||
return apiTestCases;
|
||||
}
|
||||
buildUserInfo(apiTestCases);
|
||||
return apiTestCases;
|
||||
}
|
||||
|
||||
public void buildUserInfo(List<? extends ApiScenarioDTO> apiTestCases) {
|
||||
|
@ -321,4 +327,80 @@ public class TestPlanScenarioCaseService {
|
|||
}
|
||||
return envMap;
|
||||
}
|
||||
|
||||
public void calculatePlanReport(String planId, TestPlanSimpleReportDTO report) {
|
||||
List<PlanReportCaseDTO> planReportCaseDTOS = extTestPlanScenarioCaseMapper.selectForPlanReport(planId);
|
||||
TestPlanApiResultReportDTO apiResult = report.getApiResult();
|
||||
|
||||
List<TestCaseReportStatusResultDTO> statusResult = new ArrayList<>();
|
||||
Map<String, TestCaseReportStatusResultDTO> statusResultMap = new HashMap<>();
|
||||
TestPlanUtils.calculatePlanReport(planReportCaseDTOS, statusResultMap, report, "Success");
|
||||
TestPlanUtils.addToReportCommonStatusResultList(statusResultMap, statusResult);
|
||||
TestPlanScenarioStepCountDTO stepCount = new TestPlanScenarioStepCountDTO();
|
||||
for (PlanReportCaseDTO item : planReportCaseDTOS) {
|
||||
calculateScenarioResultDTO(item, stepCount);
|
||||
}
|
||||
|
||||
int underwayStepsCounts = getUnderwayStepsCounts(stepCount.getUnderwayIds());
|
||||
|
||||
List<TestCaseReportStatusResultDTO> stepResult = new ArrayList<>();
|
||||
getScenarioCaseReportStatusResultDTO(TestPlanTestCaseStatus.Failure.name(), stepCount.getScenarioStepError(), stepResult);
|
||||
getScenarioCaseReportStatusResultDTO(TestPlanTestCaseStatus.Pass.name(), stepCount.getScenarioStepSuccess(), stepResult);
|
||||
getScenarioCaseReportStatusResultDTO(TestPlanTestCaseStatus.Underway.name(),
|
||||
stepCount.getScenarioStepTotal() - stepCount.getScenarioStepSuccess() - stepCount.getScenarioStepError() + underwayStepsCounts, stepResult);
|
||||
|
||||
apiResult.setApiScenarioData(statusResult);
|
||||
apiResult.setApiScenarioStepData(stepResult);
|
||||
}
|
||||
|
||||
private int getUnderwayStepsCounts(List<String> underwayIds){
|
||||
if (CollectionUtils.isNotEmpty(underwayIds)) {
|
||||
List<Integer> underwayStepsCounts = extTestPlanScenarioCaseMapper.getUnderwaySteps(underwayIds);
|
||||
Optional<Integer> underwayStepCount = underwayStepsCounts.stream().reduce((total, count) -> {
|
||||
if (count != null) {
|
||||
total += count;
|
||||
}
|
||||
return total;
|
||||
});
|
||||
return underwayStepCount.orElse(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void calculateScenarioResultDTO(PlanReportCaseDTO item,
|
||||
TestPlanScenarioStepCountDTO stepCount) {
|
||||
if (StringUtils.isNotBlank(item.getReportId())) {
|
||||
APIScenarioReportResult apiScenarioReportResult = apiScenarioReportService.get(item.getReportId());
|
||||
if (apiScenarioReportResult != null) {
|
||||
String content = apiScenarioReportResult.getContent();
|
||||
if (StringUtils.isNotBlank(content)) {
|
||||
JSONObject jsonObject = JSONObject.parseObject(content);
|
||||
stepCount.setScenarioStepTotal(stepCount.getScenarioStepTotal() + jsonObject.getIntValue("scenarioStepTotal"));
|
||||
stepCount.setScenarioStepSuccess(stepCount.getScenarioStepSuccess() + jsonObject.getIntValue("scenarioStepSuccess"));
|
||||
stepCount.setScenarioStepError(stepCount.getScenarioStepError() + jsonObject.getIntValue("scenarioStepError"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stepCount.getUnderwayIds().add(item.getCaseId());
|
||||
}
|
||||
}
|
||||
|
||||
private void getScenarioCaseReportStatusResultDTO(String status, int count, List<TestCaseReportStatusResultDTO> scenarioCaseList) {
|
||||
if (count > 0) {
|
||||
TestCaseReportStatusResultDTO scenarioCase = new TestCaseReportStatusResultDTO();
|
||||
scenarioCase.setStatus(status);
|
||||
scenarioCase.setCount(count);
|
||||
scenarioCaseList.add(scenarioCase);
|
||||
}
|
||||
}
|
||||
|
||||
public List<TestPlanFailureScenarioDTO> getFailureList(String planId) {
|
||||
List<TestPlanFailureScenarioDTO> apiTestCases = extTestPlanScenarioCaseMapper.getFailureList(planId);
|
||||
if (CollectionUtils.isEmpty(apiTestCases)) {
|
||||
return apiTestCases;
|
||||
}
|
||||
buildProjectInfo(apiTestCases);
|
||||
buildUserInfo(apiTestCases);
|
||||
return apiTestCases;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ public class TestPlanService {
|
|||
}
|
||||
|
||||
public TestPlan getTestPlan(String testPlanId) {
|
||||
return Optional.ofNullable(testPlanMapper.selectByPrimaryKey(testPlanId)).orElse(new TestPlan());
|
||||
return Optional.ofNullable(testPlanMapper.selectByPrimaryKey(testPlanId)).orElse(new TestPlanWithBLOBs());
|
||||
}
|
||||
|
||||
public String editTestPlan(TestPlanDTO testPlan, Boolean isSendMessage) {
|
||||
|
@ -644,7 +644,7 @@ public class TestPlanService {
|
|||
}
|
||||
|
||||
public void editTestPlanStatus(String planId) {
|
||||
TestPlan testPlan = new TestPlan();
|
||||
TestPlanWithBLOBs testPlan = new TestPlanWithBLOBs();
|
||||
testPlan.setId(planId);
|
||||
String status = calcTestPlanStatus(planId);
|
||||
testPlan.setStatus(status);
|
||||
|
@ -1160,14 +1160,14 @@ public class TestPlanService {
|
|||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public TestPlan copy(String planId) {
|
||||
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId);
|
||||
TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(planId);
|
||||
if (testPlan == null) {
|
||||
return null;
|
||||
}
|
||||
String sourcePlanId = testPlan.getId();
|
||||
String targetPlanId = UUID.randomUUID().toString();
|
||||
|
||||
TestPlan targetPlan = new TestPlan();
|
||||
TestPlanWithBLOBs targetPlan = new TestPlanWithBLOBs();
|
||||
targetPlan.setId(targetPlanId);
|
||||
targetPlan.setName(testPlan.getName() + "_COPY");
|
||||
targetPlan.setWorkspaceId(testPlan.getWorkspaceId());
|
||||
|
@ -1308,4 +1308,32 @@ public class TestPlanService {
|
|||
LogUtil.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public TestPlanSimpleReportDTO getReport(String planId) {
|
||||
TestPlanWithBLOBs testPlan = testPlanMapper.selectByPrimaryKey(planId);
|
||||
TestPlanSimpleReportDTO report = new TestPlanSimpleReportDTO();
|
||||
TestPlanFunctionResultReportDTO functionResult = new TestPlanFunctionResultReportDTO();
|
||||
TestPlanApiResultReportDTO apiResult = new TestPlanApiResultReportDTO();
|
||||
report.setFunctionResult(functionResult);
|
||||
report.setApiResult(apiResult);
|
||||
report.setStartTime(testPlan.getActualStartTime());
|
||||
report.setStartTime(testPlan.getActualEndTime());
|
||||
report.setSummary(testPlan.getReportSummary());
|
||||
testPlanTestCaseService.calculatePlanReport(planId, report);
|
||||
issuesService.calculatePlanReport(planId, report);
|
||||
testPlanApiCaseService.calculatePlanReport(planId, report);
|
||||
testPlanScenarioCaseService.calculatePlanReport(planId, report);
|
||||
testPlanLoadCaseService.calculatePlanReport(planId, report);
|
||||
report.setExecuteRate(report.getExecuteCount() * 0.1 / report.getCaseCount());
|
||||
report.setPassRate(report.getPassCount() * 0.1 / report.getCaseCount());
|
||||
return report;
|
||||
}
|
||||
|
||||
public void editReport(TestPlanWithBLOBs testPlanWithBLOBs) {
|
||||
testPlanMapper.updateByPrimaryKeySelective(testPlanWithBLOBs);
|
||||
}
|
||||
|
||||
public TestCaseReportStatusResultDTO getFunctionalResultReport(String planId) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,16 +7,12 @@ import io.metersphere.base.mapper.*;
|
|||
import io.metersphere.base.mapper.ext.ExtTestPlanTestCaseMapper;
|
||||
import io.metersphere.commons.constants.TestPlanTestCaseStatus;
|
||||
import io.metersphere.commons.user.SessionUser;
|
||||
import io.metersphere.commons.utils.BeanUtils;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.commons.utils.*;
|
||||
import io.metersphere.controller.request.member.QueryMemberRequest;
|
||||
import io.metersphere.log.vo.DetailColumn;
|
||||
import io.metersphere.log.vo.OperatingLogDetails;
|
||||
import io.metersphere.service.UserService;
|
||||
import io.metersphere.track.dto.TestCaseTestDTO;
|
||||
import io.metersphere.track.dto.TestPlanCaseDTO;
|
||||
import io.metersphere.track.dto.*;
|
||||
import io.metersphere.track.request.testcase.TestPlanCaseBatchRequest;
|
||||
import io.metersphere.track.request.testcase.TrackCount;
|
||||
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
|
||||
|
@ -369,4 +365,33 @@ public class TestPlanTestCaseService {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void calculatePlanReport(String planId, TestPlanSimpleReportDTO report) {
|
||||
List<PlanReportCaseDTO> planReportCaseDTOS = extTestPlanTestCaseMapper.selectForPlanReport(planId);
|
||||
TestPlanFunctionResultReportDTO functionResult = report.getFunctionResult();
|
||||
List<TestCaseReportStatusResultDTO> statusResult = new ArrayList<>();
|
||||
Map<String, TestCaseReportStatusResultDTO> statusResultMap = new HashMap<>();
|
||||
|
||||
TestPlanUtils.calculatePlanReport(planReportCaseDTOS, statusResultMap, report, TestPlanTestCaseStatus.Pass.name());
|
||||
TestPlanUtils.addToReportCommonStatusResultList(statusResultMap, statusResult);
|
||||
|
||||
TestPlanUtils.addToReportStatusResultList(statusResultMap, statusResult, TestPlanTestCaseStatus.Blocking.name());
|
||||
TestPlanUtils.addToReportStatusResultList(statusResultMap, statusResult, TestPlanTestCaseStatus.Skip.name());
|
||||
TestPlanUtils.addToReportStatusResultList(statusResultMap, statusResult, TestPlanTestCaseStatus.Underway.name());
|
||||
functionResult.setCaseData(statusResult);
|
||||
}
|
||||
|
||||
public List<TestPlanCaseDTO> getFailureCases(String planId) {
|
||||
List<TestPlanCaseDTO> failureCases = extTestPlanTestCaseMapper.getFailureCases(planId);
|
||||
Map<String, Project> projectMap = ServiceUtils.getProjectMap(
|
||||
failureCases.stream().map(TestPlanCaseDTO::getProjectId).collect(Collectors.toList()));
|
||||
Map<String, String> userNameMap = ServiceUtils.getUserNameMap(
|
||||
failureCases.stream().map(TestPlanCaseDTO::getExecutor).collect(Collectors.toList()));
|
||||
failureCases.forEach(item -> {
|
||||
item.setProjectName(projectMap.get(item.getProjectId()).getName());
|
||||
item.setIsCustomNum(projectMap.get(item.getProjectId()).getCustomNum());
|
||||
item.setExecutorName(userNameMap.get(item.getExecutor()));
|
||||
});
|
||||
return failureCases;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,4 +55,4 @@ CREATE TABLE IF NOT EXISTS test_plan_report_resource (
|
|||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
alter table project add azure_devops_id varchar(50) null after zentao_id;
|
||||
alter table custom_field_template modify default_value varchar(100) null ;
|
||||
alter table custom_field_template modify default_value varchar(100) null ;
|
||||
|
|
|
@ -38,4 +38,6 @@ CREATE TABLE `load_test_report_result_realtime`
|
|||
)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE utf8mb4_general_ci;
|
||||
COLLATE utf8mb4_general_ci;
|
||||
|
||||
ALTER TABLE test_plan ADD report_summary TEXT NULL COMMENT '测试计划报告总结';
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
<template>
|
||||
<div>
|
||||
<ms-chart v-if="visible && data.length > 0" :options="options"/>
|
||||
<div v-if="visible && data.length <= 0" style="height: 300px">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import MsChart from "@/business/components/common/chart/MsChart";
|
||||
export default {
|
||||
name: "MsDoughnutPieChart",
|
||||
components: {MsChart},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
options: {
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
right: 50,
|
||||
bottom: '40%',
|
||||
formatter: function (name) {
|
||||
return name;
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: this.name,
|
||||
type: 'pie',
|
||||
left: -150,
|
||||
radius: ['40%', '60%'],
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
// padding: [10, 10, 20, 10],
|
||||
lineHeight: 35,
|
||||
fontSize: 20,
|
||||
// fontWeight: 'bold',
|
||||
position: 'center',
|
||||
color: 'gray',
|
||||
formatter: function (params) {
|
||||
return '';
|
||||
},
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: this.data
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
default: '数据名称'
|
||||
},
|
||||
data: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
data() {
|
||||
this.reload();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.reload();
|
||||
},
|
||||
methods: {
|
||||
reload() {
|
||||
this.setFormatterFunc();
|
||||
this.visible = false;
|
||||
this.$nextTick(() => {
|
||||
this.visible = true;
|
||||
});
|
||||
},
|
||||
setFormatterFunc() {
|
||||
let data = this.data;
|
||||
let count = 0;
|
||||
let title = this.name;
|
||||
|
||||
this.options.series[0].data = data;
|
||||
|
||||
this.data.forEach(item => {
|
||||
count += item.value;
|
||||
});
|
||||
|
||||
this.options.legend.formatter = (name) => {
|
||||
let total = 0;
|
||||
let target = 0;
|
||||
for (let i = 0, l = data.length; i < l; i++) {
|
||||
total += data[i].value;
|
||||
if (data[i].name == name) {
|
||||
target = data[i].value;
|
||||
}
|
||||
}
|
||||
return name + ' | ' + target + ' ' + ((target / total) * 100).toFixed(0) + '%';
|
||||
};
|
||||
|
||||
this.options.series[0].label.formatter = (params) => {
|
||||
return title + '\n' + count;
|
||||
};
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -13,6 +13,7 @@
|
|||
:class="{'ms-select-all-fixed': showSelectAll}"
|
||||
:height="screenHeight"
|
||||
v-loading="tableIsLoading"
|
||||
:highlight-current-row="highlightCurrentRow"
|
||||
ref="table" @row-click="handleRowClick">
|
||||
|
||||
<el-table-column v-if="enableSelection" width="50" type="selection"/>
|
||||
|
@ -194,7 +195,8 @@ export default {
|
|||
},
|
||||
fields: Array,
|
||||
fieldKey: String,
|
||||
customFields: Array
|
||||
customFields: Array,
|
||||
highlightCurrentRow: Boolean,
|
||||
},
|
||||
mounted() {
|
||||
getLabel(this, TEST_CASE_LIST);
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
:plan-id="planId"/>
|
||||
<test-plan-load v-if="activeIndex === 'load'" :redirectCharType="redirectCharType" :clickType="clickType"
|
||||
:plan-id="planId"/>
|
||||
<test-case-statistics-report-view :test-plan="currentPlan" v-if="activeIndex === 'report'"/>
|
||||
<!-- <test-case-statistics-report-view :test-plan="currentPlan" v-if="activeIndex === 'report'"/>-->
|
||||
<test-plan-detail-report :test-plan="currentPlan" v-if="activeIndex === 'report'"/>
|
||||
|
||||
<test-report-template-list @openReport="openReport" ref="testReportTemplateList"/>
|
||||
|
||||
|
@ -49,10 +50,12 @@ import TestCaseStatisticsReportView from "./comonents/report/statistics/TestCase
|
|||
import TestReportTemplateList from "./comonents/TestReportTemplateList";
|
||||
import TestPlanLoad from "@/business/components/track/plan/view/comonents/load/TestPlanLoad";
|
||||
import {getCurrentProjectID} from "@/common/js/utils";
|
||||
import TestPlanDetailReport from "./comonents/report/TestPlanDetailReport";
|
||||
|
||||
export default {
|
||||
name: "TestPlanView",
|
||||
components: {
|
||||
TestPlanDetailReport,
|
||||
TestReportTemplateList,
|
||||
TestCaseStatisticsReportView,
|
||||
TestPlanApi,
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
<template>
|
||||
<div v-loading="result.loading">
|
||||
|
||||
<el-row type="flex" class="head-bar">
|
||||
<el-col :span="12">
|
||||
</el-col>
|
||||
<el-col :span="11" class="head-right">
|
||||
<!-- <el-button :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleExport(report.name)">-->
|
||||
<!-- {{$t('test_track.plan_view.export_report')}}-->
|
||||
<!-- </el-button>-->
|
||||
<el-button :disabled="!isTestManagerOrTestUser" plain size="mini" @click="handleExportHtml(report.name)">
|
||||
{{'导出HTML'}}
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="container" ref="resume" id="app">
|
||||
<el-main>
|
||||
<test-plan-report-content :plan-id="planId"/>
|
||||
</el-main>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {exportPdf} from "@/common/js/utils";
|
||||
import BaseInfoComponent from "./TemplateComponent/BaseInfoComponent";
|
||||
import TestResultChartComponent from "./TemplateComponent/TestResultChartComponent";
|
||||
import TestResultComponent from "./TemplateComponent/TestResultComponent";
|
||||
import RichTextComponent from "./TemplateComponent/RichTextComponent";
|
||||
import TestCaseReportTemplateEdit from "./TestCaseReportTemplateEdit";
|
||||
import TemplateComponent from "./TemplateComponent/TemplateComponent";
|
||||
import html2canvas from "html2canvas";
|
||||
import MsTestCaseReportExport from "../TestCaseReportExport";
|
||||
import TestReportTemplateList from "../TestReportTemplateList";
|
||||
import TestPlanReportContent from "@/business/components/track/plan/view/comonents/report/detail/TestPlanReportContent";
|
||||
|
||||
export default {
|
||||
name: "TestPlanDetailReport",
|
||||
components: {
|
||||
TestPlanReportContent,
|
||||
TestReportTemplateList,
|
||||
MsTestCaseReportExport,
|
||||
TemplateComponent,
|
||||
TestCaseReportTemplateEdit,
|
||||
RichTextComponent, TestResultComponent, TestResultChartComponent, BaseInfoComponent
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
imgUrl: "",
|
||||
previews: [],
|
||||
report: {},
|
||||
metric: {},
|
||||
reportExportVisible: false,
|
||||
isTestManagerOrTestUser: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.isTestManagerOrTestUser = true;
|
||||
},
|
||||
computed: {
|
||||
planId() {
|
||||
return this.testPlan.id;
|
||||
},
|
||||
},
|
||||
props: ['testPlan'],
|
||||
methods: {
|
||||
handleExport(name) {
|
||||
this.result.loading = true;
|
||||
this.reportExportVisible = true;
|
||||
let reset = this.exportReportReset;
|
||||
|
||||
this.$nextTick(function () {
|
||||
setTimeout(() => {
|
||||
html2canvas(document.getElementById('testCaseReportExport'), {
|
||||
scale: 2
|
||||
}).then(function(canvas) {
|
||||
exportPdf(name, [canvas]);
|
||||
reset();
|
||||
});
|
||||
}, 1000);
|
||||
});
|
||||
},
|
||||
handleExportHtml(name) {
|
||||
let config = {
|
||||
url: '/test/plan/report/export/' + this.planId,
|
||||
method: 'get',
|
||||
responseType: 'blob'
|
||||
};
|
||||
this.$download(config, name + '.html');
|
||||
},
|
||||
exportReportReset() {
|
||||
this.reportExportVisible = false;
|
||||
this.result.loading = false;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>cd
|
||||
|
||||
<style scoped>
|
||||
|
||||
.head-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.head-bar .el-button {
|
||||
margin-bottom: 10px;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.el-button+.el-button {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.head-bar {
|
||||
position: fixed;
|
||||
right: 10px;
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,44 @@
|
|||
<template>
|
||||
<test-plan-report-container :title="'接口用例统计'">
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="测试结果" name="first">
|
||||
<api-result :api-result="report.apiResult"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="失败用例" name="second">
|
||||
<api-failure-result :plan-id="planId"/>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- <el-tab-pane label="所有用例" name="fourth">所有用例</el-tab-pane>-->
|
||||
</el-tabs>
|
||||
</test-plan-report-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsFormDivider from "@/business/components/common/components/MsFormDivider";
|
||||
import ApiResult from "@/business/components/track/plan/view/comonents/report/detail/component/ApiResult";
|
||||
import TestPlanReportContainer
|
||||
from "@/business/components/track/plan/view/comonents/report/detail/TestPlanReportContainer";
|
||||
import ApiFailureResult from "@/business/components/track/plan/view/comonents/report/detail/component/ApiFailureResult";
|
||||
export default {
|
||||
name: "TestPlanApiReport",
|
||||
components: {ApiFailureResult, TestPlanReportContainer, ApiResult, MsFormDivider},
|
||||
data() {
|
||||
return {
|
||||
activeName: 'first'
|
||||
};
|
||||
},
|
||||
props: [
|
||||
'report', 'planId'
|
||||
],
|
||||
methods: {
|
||||
handleClick(tab, event) {
|
||||
console.log(tab, event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,49 @@
|
|||
<template>
|
||||
<test-plan-report-container :title="'功能用例统计'">
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="测试结果" name="first">
|
||||
<functional-result :function-result="report.functionResult"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="失败用例" name="second">
|
||||
<functional-failure-result :plan-id="planId"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="缺陷列表" name="third">
|
||||
<functional-issue-list :plan-id="planId"/>
|
||||
</el-tab-pane>
|
||||
<!-- <el-tab-pane label="所有用例" name="fourth">所有用例</el-tab-pane>-->
|
||||
</el-tabs>
|
||||
</test-plan-report-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsFormDivider from "@/business/components/common/components/MsFormDivider";
|
||||
import FunctionalResult from "@/business/components/track/plan/view/comonents/report/detail/component/FunctionalResult";
|
||||
import FunctionalFailureResult
|
||||
from "@/business/components/track/plan/view/comonents/report/detail/component/FunctionalFailureResult";
|
||||
import FunctionalIssueList
|
||||
from "@/business/components/track/plan/view/comonents/report/detail/component/FunctionalIssueList";
|
||||
import TestPlanReportContainer
|
||||
from "@/business/components/track/plan/view/comonents/report/detail/TestPlanReportContainer";
|
||||
export default {
|
||||
name: "TestPlanFunctionalReport",
|
||||
components: {TestPlanReportContainer, FunctionalIssueList, FunctionalFailureResult, FunctionalResult, MsFormDivider},
|
||||
data() {
|
||||
return {
|
||||
activeName: 'first'
|
||||
};
|
||||
},
|
||||
props: [
|
||||
'report','planId'
|
||||
],
|
||||
methods: {
|
||||
handleClick(tab, event) {
|
||||
console.log(tab, event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,49 @@
|
|||
<template>
|
||||
<test-plan-report-container :title="'性能用例数'">
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="测试结果" name="first">
|
||||
<load-result :load-result="report.loadResult"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="失败用例" name="second">
|
||||
<load-failure-result :plan-id="planId"/>
|
||||
</el-tab-pane>
|
||||
<!-- <el-tab-pane label="所有用例" name="fourth">所有用例</el-tab-pane>-->
|
||||
</el-tabs>
|
||||
</test-plan-report-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsFormDivider from "@/business/components/common/components/MsFormDivider";
|
||||
import LoadResult from "@/business/components/track/plan/view/comonents/report/detail/component/LoadResult";
|
||||
import TestPlanReportContainer
|
||||
from "@/business/components/track/plan/view/comonents/report/detail/TestPlanReportContainer";
|
||||
import LoadFailureResult
|
||||
from "@/business/components/track/plan/view/comonents/report/detail/component/LoadFailureResult";
|
||||
|
||||
export default {
|
||||
name: "TestPlanLoadReport",
|
||||
components: {
|
||||
LoadFailureResult,
|
||||
TestPlanReportContainer,
|
||||
LoadResult, MsFormDivider},
|
||||
data() {
|
||||
return {
|
||||
activeName: 'first'
|
||||
};
|
||||
},
|
||||
props: [
|
||||
'report',
|
||||
'planId'
|
||||
],
|
||||
methods: {
|
||||
handleClick(tab, event) {
|
||||
console.log(tab, event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<div>
|
||||
<ms-form-divider :title="title"/>
|
||||
<!-- <el-main>-->
|
||||
<slot/>
|
||||
<!-- </el-main>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsFormDivider from "@/business/components/common/components/MsFormDivider";
|
||||
export default {
|
||||
name: "TestPlanReportContainer",
|
||||
components: {MsFormDivider},
|
||||
props: ['title']
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-main {
|
||||
/*padding: 20px;*/
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,64 @@
|
|||
<template>
|
||||
<el-card>
|
||||
<test-plan-report-header :report="report" :plan-id="planId"/>
|
||||
<test-plan-functional-report v-if="functionalEnable" :plan-id="planId" :report="report"/>
|
||||
<test-plan-api-report v-if="apiEnable" :report="report" :plan-id="planId"/>
|
||||
<test-plan-load-report v-if="loadEnable" :report="report" :plan-id="planId"/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TestPlanReportHeader from "@/business/components/track/plan/view/comonents/report/detail/TestPlanReportHeader";
|
||||
import TestPlanFunctionalReport
|
||||
from "@/business/components/track/plan/view/comonents/report/detail/TestPlanFunctionalReport";
|
||||
import {getTestPlanReport} from "@/network/test-plan";
|
||||
import TestPlanApiReport from "@/business/components/track/plan/view/comonents/report/detail/TestPlanApiReport";
|
||||
import TestPlanLoadReport from "@/business/components/track/plan/view/comonents/report/detail/TestPlanLoadReport";
|
||||
export default {
|
||||
name: "TestPlanReportContent",
|
||||
components: {TestPlanLoadReport, TestPlanApiReport, TestPlanFunctionalReport, TestPlanReportHeader},
|
||||
props: {
|
||||
planId:String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
report: {}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getReport();
|
||||
},
|
||||
computed: {
|
||||
functionalEnable() {
|
||||
return this.report.functionResult.caseData.length > 0;
|
||||
},
|
||||
apiEnable() {
|
||||
return this.report.apiResult.apiCaseData.length > 0 || this.report.apiResult.apiScenarioData.length > 0;
|
||||
},
|
||||
loadEnable() {
|
||||
return this.report.loadResult.caseData.length > 0;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getReport() {
|
||||
this.result = getTestPlanReport(this.planId, (data) => {
|
||||
this.report = data;
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-card {
|
||||
/*width: 95% !important;*/
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
|
||||
/deep/ .el-tabs .el-tabs__header {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
padding-top: 15px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,98 @@
|
|||
<template>
|
||||
<test-plan-report-container :title="'概览'">
|
||||
<el-form class="form-info" v-loading="result.loading">
|
||||
<el-form-item :label="$t('测试时间') + ':'">
|
||||
{{showTime}}
|
||||
</el-form-item>
|
||||
<el-row type="flex" justify="space-between" class="select-time">
|
||||
<el-col :span="8">
|
||||
<el-form-item :label="'测试总数' + ':'">
|
||||
{{report.caseCount}}
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item :label="'执行率' + ':'">
|
||||
{{ (report.executeRate * 100).toFixed(0) + '%'}}
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item :label="'通过率' + ':'">
|
||||
{{ (report.passRate * 100).toFixed(0) + '%'}}
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item :label="'报告总结'">
|
||||
<el-link @click="isEdit = true">
|
||||
编辑
|
||||
</el-link>
|
||||
</el-form-item>
|
||||
<div v-if="!isEdit">
|
||||
{{report.summary}}
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-input
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
placeholder="请输入内容"
|
||||
v-model="report.summary" @blur="saveSummary"/>
|
||||
</div>
|
||||
</el-form>
|
||||
</test-plan-report-container>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsFormDivider from "@/business/components/common/components/MsFormDivider";
|
||||
import {editPlanReport} from "@/network/test-plan";
|
||||
import TestPlanReportContainer
|
||||
from "@/business/components/track/plan/view/comonents/report/detail/TestPlanReportContainer";
|
||||
import {timestampFormatDate} from "@/common/js/filter";
|
||||
export default {
|
||||
name: "TestPlanReportHeader",
|
||||
components: {TestPlanReportContainer, MsFormDivider},
|
||||
props: {
|
||||
planId: String,
|
||||
report: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
result: {},
|
||||
isEdit: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showTime() {
|
||||
let startTime = 'NaN';
|
||||
let endTime = 'NaN';
|
||||
if (this.report.startTime) {
|
||||
startTime = timestampFormatDate(this.report.startTime, false).substring(0, 10);
|
||||
}
|
||||
if (this.report.endTime) {
|
||||
endTime = timestampFormatDate(this.report.endTime, false).substring(0, 10);
|
||||
}
|
||||
return startTime + ' ~ ' + endTime;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
saveSummary() {
|
||||
editPlanReport({
|
||||
id: this.planId,
|
||||
reportSummary: this.report.summary ? this.report.summary : ''
|
||||
});
|
||||
this.isEdit = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-link >>> .el-link--inner {
|
||||
line-height: 40px;
|
||||
font-size: 14px;
|
||||
height: 42.8px;
|
||||
}
|
||||
|
||||
.form-info {
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-row class="scenario-info">
|
||||
<el-col :span="7">
|
||||
|
||||
<ms-table v-loading="result.loading"
|
||||
:show-select-all="false"
|
||||
:screen-height="null"
|
||||
:enable-selection="false"
|
||||
:highlight-current-row="true"
|
||||
@refresh="getScenarioApiCase"
|
||||
@handleRowClick="rowClick"
|
||||
:data="apiCases">
|
||||
|
||||
<ms-table-column
|
||||
:width="80"
|
||||
:label="$t('commons.id')"
|
||||
prop="num">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('commons.name')"
|
||||
prop="name">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="'创建人'"
|
||||
prop="creatorName"/>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.case.priority')"
|
||||
:width="80"
|
||||
prop="priority">
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.priority" ref="priority"/>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:width="80"
|
||||
:label="'执行结果'"
|
||||
prop="lastResult">
|
||||
<status-table-item :value="'Failure'"/>
|
||||
</ms-table-column>
|
||||
</ms-table>
|
||||
</el-col>
|
||||
<el-col :span="17" v-if="apiCases.length > 0">
|
||||
<el-card>
|
||||
<ms-request-result-tail :response="response" ref="debugResult"/>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PriorityTableItem from "../../../../../../common/tableItems/planview/PriorityTableItem";
|
||||
import TypeTableItem from "../../../../../../common/tableItems/planview/TypeTableItem";
|
||||
import MethodTableItem from "../../../../../../common/tableItems/planview/MethodTableItem";
|
||||
import StatusTableItem from "../../../../../../common/tableItems/planview/StatusTableItem";
|
||||
import {getPlanApiFailureCase} from "@/network/test-plan";
|
||||
import MsTable from "@/business/components/common/components/table/MsTable";
|
||||
import MsTableColumn from "@/business/components/common/components/table/MsTableColumn";
|
||||
import {getApiReport} from "@/network/api";
|
||||
import MsRequestResultTail from "@/business/components/api/definition/components/response/RequestResultTail";
|
||||
export default {
|
||||
name: "ApiCaseFailureResult",
|
||||
components: {
|
||||
MsRequestResultTail,
|
||||
MsTableColumn, MsTable, StatusTableItem, MethodTableItem, TypeTableItem, PriorityTableItem},
|
||||
props: {
|
||||
planId: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
apiCases: [],
|
||||
result: {},
|
||||
report: {},
|
||||
response: {}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getScenarioApiCase();
|
||||
},
|
||||
methods: {
|
||||
getScenarioApiCase() {
|
||||
this.result = getPlanApiFailureCase(this.planId, (data) => {
|
||||
this.apiCases = data;
|
||||
if (data && data.length > 0) {
|
||||
this.rowClick(data[0]);
|
||||
}
|
||||
});
|
||||
},
|
||||
rowClick(row) {
|
||||
getApiReport(row.id, (data) => {
|
||||
this.response = JSON.parse(data.content);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -0,0 +1,44 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-tabs type="card">
|
||||
<el-tab-pane label="接口用例">
|
||||
<api-case-failure-result :plan-id="planId"/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="场景用例">
|
||||
<api-scenario-failure-result :plan-id="planId"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PriorityTableItem from "../../../../../../common/tableItems/planview/PriorityTableItem";
|
||||
import TypeTableItem from "../../../../../../common/tableItems/planview/TypeTableItem";
|
||||
import MethodTableItem from "../../../../../../common/tableItems/planview/MethodTableItem";
|
||||
import StatusTableItem from "../../../../../../common/tableItems/planview/StatusTableItem";
|
||||
import ApiScenarioFailureResult
|
||||
from "@/business/components/track/plan/view/comonents/report/detail/component/ApiScenarioFailureResult";
|
||||
import ApiCaseFailureResult
|
||||
from "@/business/components/track/plan/view/comonents/report/detail/component/ApiCaseFailureResult";
|
||||
export default {
|
||||
name: "ApiFailureResult",
|
||||
components: {
|
||||
ApiCaseFailureResult,
|
||||
ApiScenarioFailureResult, StatusTableItem, MethodTableItem, TypeTableItem, PriorityTableItem},
|
||||
props: {
|
||||
planId: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,110 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-row >
|
||||
<el-col :span="12">
|
||||
<ms-doughnut-pie-chart :name="$t('单接口用例')" :data="caseCharData" ref="functionChar"/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<api-scenario-char-result :data="scenarioCharData"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import MsPieChart from "@/business/components/common/components/MsPieChart";
|
||||
import MsDoughnutPieChart from "@/business/components/common/components/MsDoughnutPieChart";
|
||||
import ApiScenarioCharResult
|
||||
from "@/business/components/track/plan/view/comonents/report/detail/component/ApiScenarioCharResult";
|
||||
export default {
|
||||
name: "ApiResult",
|
||||
components: {ApiScenarioCharResult, MsDoughnutPieChart, MsPieChart},
|
||||
data() {
|
||||
return {
|
||||
caseDataMap: new Map([
|
||||
["success", {name: this.$t('test_track.plan_view.pass'), itemStyle: {color: '#67C23A'}}],
|
||||
["Success", {name: this.$t('test_track.plan_view.pass'), itemStyle: {color: '#67C23A'}}],
|
||||
["error", {name: this.$t('test_track.plan_view.failure'), itemStyle: {color: '#F56C6C'}}],
|
||||
["Fail", {name: this.$t('test_track.plan_view.failure'), itemStyle: {color: '#F56C6C'}}],
|
||||
["Prepare", {name: this.$t('api_test.home_page.detail_card.unexecute'), itemStyle: {color: '#909399'}}],
|
||||
]),
|
||||
caseCharData: [],
|
||||
scenarioCharData: [],
|
||||
isShow: true
|
||||
}
|
||||
},
|
||||
props: {
|
||||
apiResult: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
caseData: [],
|
||||
issueData: []
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
apiResult() {
|
||||
this.getCaseCharData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getCaseCharData();
|
||||
},
|
||||
methods: {
|
||||
getCaseCharData() {
|
||||
let caseCharData = [];
|
||||
this.apiResult.apiCaseData.forEach(item => {
|
||||
let data = this.getDataByStatus(item.status);
|
||||
data.value = item.count;
|
||||
caseCharData.push(data);
|
||||
});
|
||||
this.caseCharData = caseCharData;
|
||||
|
||||
let apiScenarioData = [];
|
||||
this.apiResult.apiScenarioData.forEach(item => {
|
||||
let data = this.getDataByStatus(item.status);
|
||||
data.data = [item.count];
|
||||
for (let i = 0; i < this.apiResult.apiScenarioStepData.length; i++) {
|
||||
let stepItem = this.apiResult.apiScenarioStepData[i];
|
||||
if (item.status) {
|
||||
if (item.status === 'Fail' && stepItem.status === 'Failure') {
|
||||
data.data.push(stepItem.count);
|
||||
break;
|
||||
}
|
||||
if (item.status === 'Success' && stepItem.status === 'Pass') {
|
||||
data.data.push(stepItem.count);
|
||||
break;
|
||||
}
|
||||
if (item.status === 'Prepare' && stepItem.status === 'Underway') {
|
||||
data.data.push(stepItem.count);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (stepItem.status === 'Underway') {
|
||||
data.data.push(stepItem.count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
apiScenarioData.push(data);
|
||||
});
|
||||
this.scenarioCharData = apiScenarioData;
|
||||
},
|
||||
getDataByStatus(status) {
|
||||
let tmp = this.caseDataMap.get(status);
|
||||
if (!tmp) {
|
||||
tmp = this.caseDataMap.get('Prepare');
|
||||
}
|
||||
let data = {};
|
||||
Object.assign(data, tmp);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -0,0 +1,172 @@
|
|||
<template>
|
||||
<ms-chart v-if="visible" :options="options"/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsChart from "@/business/components/common/chart/MsChart";
|
||||
let seriesLabel = {
|
||||
show: true,
|
||||
formatter: function (value) {
|
||||
return value.data + '/' + ((value.data / 100) * 100).toFixed(0) + '%';
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "ApiScenarioCharResult",
|
||||
components: {MsChart},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
options: {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
data: [],
|
||||
// orient: 'vertical',
|
||||
// right: 0,
|
||||
// bottom: '40%',
|
||||
},
|
||||
grid: {
|
||||
left: 100
|
||||
},
|
||||
xAxis: {
|
||||
// type: 'value',
|
||||
// // name: 'Days',
|
||||
// axisLabel: {
|
||||
// formatter: '{value}'
|
||||
// }
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
inverse: true,
|
||||
data: ['场景用例数', '步骤用例数'],
|
||||
axisLabel: {
|
||||
formatter: function (value) {
|
||||
},
|
||||
margin: 20,
|
||||
rich: {
|
||||
name: {
|
||||
lineHeight: 30,
|
||||
fontSize: 16,
|
||||
align: 'center'
|
||||
},
|
||||
count: {
|
||||
height: 40,
|
||||
fontSize: 20,
|
||||
align: 'center',
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '未执行',
|
||||
type: 'bar',
|
||||
data: [165, 170],
|
||||
label: seriesLabel,
|
||||
itemStyle: {
|
||||
color: '#909399'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '成功',
|
||||
type: 'bar',
|
||||
label: seriesLabel,
|
||||
data: [150, 105],
|
||||
itemStyle: {
|
||||
color: '#F56C6C'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '失败',
|
||||
type: 'bar',
|
||||
label: seriesLabel,
|
||||
data: [220, 82],
|
||||
itemStyle: {
|
||||
color: '#67C23A'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
default: '数据名称'
|
||||
},
|
||||
data: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
data() {
|
||||
this.reload();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.reload();
|
||||
},
|
||||
methods: {
|
||||
reload() {
|
||||
this.setFormatterFunc();
|
||||
this.visible = false;
|
||||
this.$nextTick(() => {
|
||||
this.visible = true;
|
||||
});
|
||||
},
|
||||
setFormatterFunc() {
|
||||
let data = this.data;
|
||||
let caseCount = 0;
|
||||
let stepCount = 0;
|
||||
this.data.forEach(item => {
|
||||
caseCount += item.data[0];
|
||||
if (item.data[1]) {
|
||||
stepCount += item.data[1];
|
||||
}
|
||||
});
|
||||
|
||||
let formatterFuc = function (value) {
|
||||
let total = 0;
|
||||
if (value.dataIndex == 0) {
|
||||
total = caseCount;
|
||||
} else {
|
||||
total = stepCount;
|
||||
}
|
||||
return value.data + '/' + ((value.data / total) * 100).toFixed(0) + '%';
|
||||
};
|
||||
|
||||
this.data.forEach(item => {
|
||||
item.type = 'bar';
|
||||
item.label = {
|
||||
show: true,
|
||||
formatter: formatterFuc
|
||||
};
|
||||
});
|
||||
|
||||
this.options.series = data;
|
||||
|
||||
this.options.yAxis.axisLabel.formatter = function (value) {
|
||||
if (value === '场景用例数') {
|
||||
return '{name|场景用例数}\n' + '{count| ' + caseCount + '}';
|
||||
} else {
|
||||
return '{name|步骤用例数}\n' + '{count|' + stepCount + '}';
|
||||
}
|
||||
};
|
||||
|
||||
this.options.legend.data = data.map(i => i.name);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,105 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-row class="scenario-info">
|
||||
<el-col :span="8">
|
||||
|
||||
<ms-table v-loading="result.loading"
|
||||
:show-select-all="false"
|
||||
:screen-height="null"
|
||||
:enable-selection="false"
|
||||
:highlight-current-row="true"
|
||||
@refresh="getScenarioApiCase"
|
||||
@handleRowClick="rowClick"
|
||||
:data="scenarioCases">
|
||||
|
||||
<ms-table-column
|
||||
:width="80"
|
||||
:label="$t('commons.id')"
|
||||
prop="customNum">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('commons.name')"
|
||||
prop="name">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="'创建人'"
|
||||
prop="creatorName">
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.case.priority')"
|
||||
:width="80"
|
||||
prop="level">
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.level" ref="priority"/>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
</ms-table-column>
|
||||
<ms-table-column
|
||||
:width="70"
|
||||
:label="'步骤数'"
|
||||
prop="stepTotal">
|
||||
</ms-table-column>
|
||||
<ms-table-column
|
||||
:width="80"
|
||||
:label="'执行结果'"
|
||||
prop="lastResult">
|
||||
<status-table-item :value="'Failure'"/>
|
||||
</ms-table-column>
|
||||
</ms-table>
|
||||
</el-col>
|
||||
<el-col :span="16" v-if="scenarioCases.length > 0">
|
||||
<ms-api-report @refresh="search" :infoDb="true" :report-id="reportId"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PriorityTableItem from "../../../../../../common/tableItems/planview/PriorityTableItem";
|
||||
import TypeTableItem from "../../../../../../common/tableItems/planview/TypeTableItem";
|
||||
import MethodTableItem from "../../../../../../common/tableItems/planview/MethodTableItem";
|
||||
import StatusTableItem from "../../../../../../common/tableItems/planview/StatusTableItem";
|
||||
import {getPlanScenarioFailureCase} from "@/network/test-plan";
|
||||
import MsTable from "@/business/components/common/components/table/MsTable";
|
||||
import MsTableColumn from "@/business/components/common/components/table/MsTableColumn";
|
||||
import MsApiReport from "@/business/components/api/automation/report/ApiReportDetail";
|
||||
export default {
|
||||
name: "ApiScenarioFailureResult",
|
||||
components: {
|
||||
MsApiReport,
|
||||
MsTableColumn, MsTable, StatusTableItem, MethodTableItem, TypeTableItem, PriorityTableItem},
|
||||
props: {
|
||||
planId: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
scenarioCases: [],
|
||||
result: {},
|
||||
report: {},
|
||||
reportId: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getScenarioApiCase();
|
||||
},
|
||||
methods: {
|
||||
getScenarioApiCase() {
|
||||
this.result = getPlanScenarioFailureCase(this.planId, (data) => {
|
||||
this.scenarioCases = data;
|
||||
if (data && data.length > 0) {
|
||||
this.reportId = data[0].reportId;
|
||||
}
|
||||
});
|
||||
},
|
||||
rowClick(row) {
|
||||
this.reportId = row.reportId;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -0,0 +1,99 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<el-table
|
||||
row-key="id"
|
||||
:data="failureTestCases">
|
||||
<el-table-column
|
||||
prop="num"
|
||||
:label="$t('commons.id')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="{row}">
|
||||
{{row.isCustomNum ? row.customNum : row.num }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('commons.name')"
|
||||
show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="priority"
|
||||
column-key="priority"
|
||||
:label="$t('test_track.case.priority')">
|
||||
<template v-slot:default="scope">
|
||||
<priority-table-item :value="scope.row.priority" ref="priority"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- <el-table-column-->
|
||||
<!-- prop="nodePath"-->
|
||||
<!-- :label="$t('test_track.case.module')"-->
|
||||
<!-- show-overflow-tooltip>-->
|
||||
<!-- </el-table-column>-->
|
||||
|
||||
<el-table-column
|
||||
prop="projectName"
|
||||
:label="$t('test_track.case.project_name')"
|
||||
show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="executorName"
|
||||
:label="$t('test_track.plan_view.executor')">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="status"
|
||||
column-key="status"
|
||||
:label="$t('test_track.plan_view.execute_result')">
|
||||
<template v-slot:default="scope">
|
||||
<status-table-item :value="'Failure'"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="updateTime"
|
||||
:label="$t('commons.update_time')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PriorityTableItem from "../../../../../../common/tableItems/planview/PriorityTableItem";
|
||||
import TypeTableItem from "../../../../../../common/tableItems/planview/TypeTableItem";
|
||||
import MethodTableItem from "../../../../../../common/tableItems/planview/MethodTableItem";
|
||||
import StatusTableItem from "../../../../../../common/tableItems/planview/StatusTableItem";
|
||||
import {getPlanFunctionFailureCase} from "@/network/test-plan";
|
||||
export default {
|
||||
name: "FunctionalFailureResult",
|
||||
components: {StatusTableItem, MethodTableItem, TypeTableItem, PriorityTableItem},
|
||||
props: {
|
||||
planId: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
failureTestCases: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getFailureTestCase();
|
||||
},
|
||||
methods: {
|
||||
getFailureTestCase() {
|
||||
getPlanFunctionFailureCase(this.planId, (data) => {
|
||||
this.failureTestCases = data;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,99 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<ms-table
|
||||
v-loading="result.loading"
|
||||
:show-select-all="false"
|
||||
:data="data"
|
||||
:screen-height="null"
|
||||
:enable-selection="false"
|
||||
@refresh="getIssues">
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.id')"
|
||||
prop="id" v-if="false">
|
||||
</ms-table-column>
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.id')"
|
||||
prop="num">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.title')"
|
||||
prop="title">
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.platform_status')"
|
||||
v-if="isThirdPart"
|
||||
prop="platformStatus">
|
||||
<template v-slot="scope">
|
||||
{{ scope.row.platformStatus ? scope.row.platformStatus : '--'}}
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
v-else
|
||||
:label="$t('test_track.issue.status')"
|
||||
prop="status">
|
||||
<template v-slot="scope">
|
||||
<span>{{ issueStatusMap[scope.row.status] ? issueStatusMap[scope.row.status] : scope.row.status }}</span>
|
||||
</template>
|
||||
</ms-table-column>
|
||||
|
||||
<ms-table-column
|
||||
:label="$t('test_track.issue.platform')"
|
||||
prop="platform">
|
||||
</ms-table-column>
|
||||
|
||||
<issue-description-table-item/>
|
||||
</ms-table>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MsTable from "@/business/components/common/components/table/MsTable";
|
||||
import MsTableColumn from "@/business/components/common/components/table/MsTableColumn";
|
||||
import IssueDescriptionTableItem from "@/business/components/track/issue/IssueDescriptionTableItem";
|
||||
import {ISSUE_STATUS_MAP} from "@/common/js/table-constants";
|
||||
import {getIssuesByPlanId} from "@/network/Issue";
|
||||
import {getIssueTemplate} from "@/network/custom-field-template";
|
||||
export default {
|
||||
name: "FunctionalIssueList",
|
||||
components: {IssueDescriptionTableItem, MsTableColumn, MsTable},
|
||||
data() {
|
||||
return {
|
||||
data: [],
|
||||
result: {},
|
||||
isThirdPart: false
|
||||
}
|
||||
},
|
||||
props: ['planId'],
|
||||
computed: {
|
||||
issueStatusMap() {
|
||||
return ISSUE_STATUS_MAP;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
getIssueTemplate()
|
||||
.then((template) => {
|
||||
if (template.platform === 'metersphere') {
|
||||
this.isThirdPart = false;
|
||||
} else {
|
||||
this.isThirdPart = true;
|
||||
}
|
||||
});
|
||||
this.getIssues();
|
||||
},
|
||||
methods: {
|
||||
getIssues() {
|
||||
this.result = getIssuesByPlanId(this.planId, (data) => {
|
||||
this.data = data;
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -0,0 +1,103 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-row >
|
||||
<el-col :span="12">
|
||||
<ms-doughnut-pie-chart :name="$t('功能用例数')" :data="caseCharData" ref="functionChar"/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<ms-doughnut-pie-chart :name="$t('缺陷数')" :data="issueCharData"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import MsPieChart from "@/business/components/common/components/MsPieChart";
|
||||
import MsDoughnutPieChart from "@/business/components/common/components/MsDoughnutPieChart";
|
||||
export default {
|
||||
name: "FunctionalResult",
|
||||
components: {MsDoughnutPieChart, MsPieChart},
|
||||
data() {
|
||||
return {
|
||||
caseDataMap: new Map([
|
||||
["Pass", {name: this.$t('test_track.plan_view.pass'), itemStyle: {color: '#67C23A'}}],
|
||||
["Failure", {name: this.$t('test_track.plan_view.failure'), itemStyle: {color: '#F56C6C'}}],
|
||||
["Blocking", {name: this.$t('test_track.plan_view.blocking'), itemStyle: {color: '#E6A23C'}}],
|
||||
["Skip", {name: this.$t('test_track.plan_view.skip'), itemStyle: {color: '#909399'}}],
|
||||
["Underway", {name: this.$t('test_track.plan.plan_status_running'), itemStyle: {color: 'lightskyblue'}}],
|
||||
["Prepare", {name: this.$t('test_track.plan.plan_status_prepare'), itemStyle: {color: '#DEDE10'}}]
|
||||
]),
|
||||
issueDataMap: new Map([
|
||||
["resolved", {name: this.$t('已解决'), itemStyle: {color: '#67C23A'}}],
|
||||
["new", {name: this.$t('新建'), itemStyle: {color: '#F56C6C'}}],
|
||||
["closed", {name: this.$t('已关闭'), itemStyle: {color: '#909399'}}],
|
||||
]),
|
||||
caseCharData: [],
|
||||
issueCharData: [],
|
||||
isShow: true
|
||||
}
|
||||
},
|
||||
props: {
|
||||
functionResult: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
caseData: [],
|
||||
issueData: []
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
functionResult() {
|
||||
this.getCaseCharData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getCaseCharData();
|
||||
},
|
||||
methods: {
|
||||
getCaseCharData() {
|
||||
let caseCharData = [];
|
||||
this.functionResult.caseData.forEach(item => {
|
||||
let data = this.caseDataMap.get(item.status);
|
||||
data.value = item.count;
|
||||
caseCharData.push(data);
|
||||
});
|
||||
this.caseCharData = caseCharData;
|
||||
|
||||
let issueCharData = [];
|
||||
let colors = ['#F56C6C', '#67C23A', '#E6A23C', '#909399', 'lightskyblue', '#DEDE10'];
|
||||
let usedSet = new Set();
|
||||
|
||||
this.functionResult.issueData.forEach(item => {
|
||||
let status = item.status;
|
||||
let data = this.issueDataMap.get(status);
|
||||
if (!data) {
|
||||
data = {name: status, itemStyle: {color: null}};
|
||||
// if (status === 'new' || status === '新' | status === '待办' | status === 'active') {
|
||||
// data.color = '#F56C6C';
|
||||
// }
|
||||
if (!data.itemStyle.color) {
|
||||
for (let i = 0; i < colors.length; i++) {
|
||||
let color = colors[i];
|
||||
if (!usedSet.has(color)) {
|
||||
data.itemStyle.color = color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
usedSet.add(data.itemStyle.color);
|
||||
}
|
||||
data.value = item.count;
|
||||
issueCharData.push(data);
|
||||
});
|
||||
this.issueCharData = issueCharData;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -0,0 +1,70 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<el-table
|
||||
row-key="id"
|
||||
:data="failureTestCases">
|
||||
<el-table-column
|
||||
prop="num"
|
||||
:label="$t('commons.id')"
|
||||
show-overflow-tooltip>
|
||||
<template v-slot:default="{row}">
|
||||
{{row.isCustomNum ? row.customNum : row.num }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('commons.name')"
|
||||
show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="userName"
|
||||
:label="$t('commons.create_user')">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="status"
|
||||
column-key="status"
|
||||
:label="$t('test_track.plan_view.execute_result')">
|
||||
<template v-slot:default="scope">
|
||||
<status-table-item :value="'Failure'"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TypeTableItem from "../../../../../../common/tableItems/planview/TypeTableItem";
|
||||
import MethodTableItem from "../../../../../../common/tableItems/planview/MethodTableItem";
|
||||
import StatusTableItem from "../../../../../../common/tableItems/planview/StatusTableItem";
|
||||
import {getPlanLoadFailureCase} from "@/network/test-plan";
|
||||
export default {
|
||||
name: "LoadFailureResult",
|
||||
components: {StatusTableItem, MethodTableItem, TypeTableItem},
|
||||
props: {
|
||||
planId: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
failureTestCases: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getFailureTestCase();
|
||||
},
|
||||
methods: {
|
||||
getFailureTestCase() {
|
||||
getPlanLoadFailureCase(this.planId, (data) => {
|
||||
this.failureTestCases = data;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,67 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-row >
|
||||
<el-col :span="12">
|
||||
<ms-doughnut-pie-chart :name="$t('性能测试用例数')" :data="caseCharData" ref="functionChar"/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import MsPieChart from "@/business/components/common/components/MsPieChart";
|
||||
import MsDoughnutPieChart from "@/business/components/common/components/MsDoughnutPieChart";
|
||||
export default {
|
||||
name: "loadResult",
|
||||
components: {MsDoughnutPieChart, MsPieChart},
|
||||
data() {
|
||||
return {
|
||||
caseDataMap: new Map([
|
||||
["success", {name: this.$t('test_track.plan_view.pass'), itemStyle: {color: '#67C23A'}}],
|
||||
["error", {name: this.$t('test_track.plan_view.failure'), itemStyle: {color: '#F56C6C'}}],
|
||||
["Prepare", {name: this.$t('api_test.home_page.detail_card.unexecute'), itemStyle: {color: '#909399'}}],
|
||||
]),
|
||||
caseCharData: [],
|
||||
isShow: true
|
||||
}
|
||||
},
|
||||
props: {
|
||||
loadResult: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
caseData: [],
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
loadResult() {
|
||||
this.getCaseCharData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getCaseCharData();
|
||||
},
|
||||
methods: {
|
||||
getCaseCharData() {
|
||||
let caseCharData = [];
|
||||
this.loadResult.caseData.forEach(item => {
|
||||
let data = this.caseDataMap.get(item.status);
|
||||
if (!data) {
|
||||
data = this.caseDataMap.get('Prepare');
|
||||
}
|
||||
data.value = item.count;
|
||||
caseCharData.push(data);
|
||||
});
|
||||
this.caseCharData = caseCharData;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -229,7 +229,7 @@
|
|||
},
|
||||
}
|
||||
}
|
||||
</script>cd
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ const options = function (value, array) {
|
|||
return value;
|
||||
};
|
||||
|
||||
const timestampFormatDate = function (timestamp, showMs) {
|
||||
export const timestampFormatDate = function (timestamp, showMs) {
|
||||
if (!timestamp) {
|
||||
return timestamp
|
||||
}
|
||||
|
|
|
@ -32,6 +32,17 @@ export function getIssuesByCaseId(caseId, page) {
|
|||
}
|
||||
}
|
||||
|
||||
export function getIssuesByPlanId(planId, callback) {
|
||||
if (planId) {
|
||||
return get('/issues/plan/get/' + planId, (response) => {
|
||||
if (callback) {
|
||||
callback(response.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
export function buildPlatformIssue(data) {
|
||||
data.customFields = JSON.stringify(data.customFields);
|
||||
return post("issues/get/platform/issue", data).then(response => {
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
import {post} from "@/common/js/ajax";
|
||||
import {success} from "@/common/js/message";
|
||||
import {baseGet} from "@/network/base-network";
|
||||
|
||||
export function apiCaseBatchRun(condition) {
|
||||
return post('/api/testcase/batch/run', condition, () => {
|
||||
success("执行成功,请稍后刷新查看");
|
||||
});
|
||||
}
|
||||
|
||||
export function getScenarioReport(reportId, callback) {
|
||||
return reportId ? baseGet('/api/scenario/report/get/' + reportId, callback) : {};
|
||||
}
|
||||
|
||||
export function getApiReport(reportId, callback) {
|
||||
return reportId ? baseGet('/api/definition/report/getReport/' + reportId, callback) : {};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import {get} from "@/common/js/ajax";
|
||||
|
||||
export function baseGet(url, callback) {
|
||||
return get(url, (response) => {
|
||||
if (callback) {
|
||||
callback(response.data);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
import {post, get} from "@/common/js/ajax";
|
||||
import {success} from "@/common/js/message";
|
||||
import i18n from "@/i18n/i18n";
|
||||
import {baseGet} from "@/network/base-network";
|
||||
|
||||
export function getTestPlanReport(planId, callback) {
|
||||
if (planId) {
|
||||
return get('/test/plan/report/' + planId, (response) => {
|
||||
if (callback) {
|
||||
callback(response.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function editPlanReport(param) {
|
||||
return post('/test/plan/edit/report', param, () => {
|
||||
success(i18n.t('commons.save_success'));
|
||||
});
|
||||
}
|
||||
|
||||
export function getPlanFunctionFailureCase(planId, callback) {
|
||||
return planId ? baseGet('/test/plan/case/list/failure/' + planId, callback) : {};
|
||||
}
|
||||
|
||||
export function getPlanScenarioFailureCase(planId, callback) {
|
||||
return planId ? baseGet('/test/plan/scenario/case/list/failure/' + planId, callback) : {};
|
||||
}
|
||||
|
||||
export function getPlanApiFailureCase(planId, callback) {
|
||||
return planId ? baseGet('/test/plan/api/case/list/failure/' + planId, callback) : {};
|
||||
}
|
||||
|
||||
export function getPlanLoadFailureCase(planId, callback) {
|
||||
return planId ? baseGet('/test/plan/load/case/list/failure/' + planId, callback) : {};
|
||||
}
|
Loading…
Reference in New Issue