Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Captain.B 2020-03-30 17:39:21 +08:00
commit 43cefe0ed0
23 changed files with 1056 additions and 246 deletions

View File

@ -7,12 +7,18 @@ public class TestPlan implements Serializable {
private String projectId;
private String workspaceId;
private String name;
private String description;
private String status;
private String stage;
private String principal;
private String testCaseMatchRule;
private String executorMatchRule;
@ -41,6 +47,14 @@ public class TestPlan implements Serializable {
this.projectId = projectId == null ? null : projectId.trim();
}
public String getWorkspaceId() {
return workspaceId;
}
public void setWorkspaceId(String workspaceId) {
this.workspaceId = workspaceId == null ? null : workspaceId.trim();
}
public String getName() {
return name;
}
@ -65,6 +79,22 @@ public class TestPlan implements Serializable {
this.status = status == null ? null : status.trim();
}
public String getStage() {
return stage;
}
public void setStage(String stage) {
this.stage = stage == null ? null : stage.trim();
}
public String getPrincipal() {
return principal;
}
public void setPrincipal(String principal) {
this.principal = principal == null ? null : principal.trim();
}
public String getTestCaseMatchRule() {
return testCaseMatchRule;
}

View File

@ -244,6 +244,76 @@ public class TestPlanExample {
return (Criteria) this;
}
public Criteria andWorkspaceIdIsNull() {
addCriterion("workspace_id is null");
return (Criteria) this;
}
public Criteria andWorkspaceIdIsNotNull() {
addCriterion("workspace_id is not null");
return (Criteria) this;
}
public Criteria andWorkspaceIdEqualTo(String value) {
addCriterion("workspace_id =", value, "workspaceId");
return (Criteria) this;
}
public Criteria andWorkspaceIdNotEqualTo(String value) {
addCriterion("workspace_id <>", value, "workspaceId");
return (Criteria) this;
}
public Criteria andWorkspaceIdGreaterThan(String value) {
addCriterion("workspace_id >", value, "workspaceId");
return (Criteria) this;
}
public Criteria andWorkspaceIdGreaterThanOrEqualTo(String value) {
addCriterion("workspace_id >=", value, "workspaceId");
return (Criteria) this;
}
public Criteria andWorkspaceIdLessThan(String value) {
addCriterion("workspace_id <", value, "workspaceId");
return (Criteria) this;
}
public Criteria andWorkspaceIdLessThanOrEqualTo(String value) {
addCriterion("workspace_id <=", value, "workspaceId");
return (Criteria) this;
}
public Criteria andWorkspaceIdLike(String value) {
addCriterion("workspace_id like", value, "workspaceId");
return (Criteria) this;
}
public Criteria andWorkspaceIdNotLike(String value) {
addCriterion("workspace_id not like", value, "workspaceId");
return (Criteria) this;
}
public Criteria andWorkspaceIdIn(List<String> values) {
addCriterion("workspace_id in", values, "workspaceId");
return (Criteria) this;
}
public Criteria andWorkspaceIdNotIn(List<String> values) {
addCriterion("workspace_id not in", values, "workspaceId");
return (Criteria) this;
}
public Criteria andWorkspaceIdBetween(String value1, String value2) {
addCriterion("workspace_id between", value1, value2, "workspaceId");
return (Criteria) this;
}
public Criteria andWorkspaceIdNotBetween(String value1, String value2) {
addCriterion("workspace_id not between", value1, value2, "workspaceId");
return (Criteria) this;
}
public Criteria andNameIsNull() {
addCriterion("name is null");
return (Criteria) this;
@ -454,6 +524,146 @@ public class TestPlanExample {
return (Criteria) this;
}
public Criteria andStageIsNull() {
addCriterion("stage is null");
return (Criteria) this;
}
public Criteria andStageIsNotNull() {
addCriterion("stage is not null");
return (Criteria) this;
}
public Criteria andStageEqualTo(String value) {
addCriterion("stage =", value, "stage");
return (Criteria) this;
}
public Criteria andStageNotEqualTo(String value) {
addCriterion("stage <>", value, "stage");
return (Criteria) this;
}
public Criteria andStageGreaterThan(String value) {
addCriterion("stage >", value, "stage");
return (Criteria) this;
}
public Criteria andStageGreaterThanOrEqualTo(String value) {
addCriterion("stage >=", value, "stage");
return (Criteria) this;
}
public Criteria andStageLessThan(String value) {
addCriterion("stage <", value, "stage");
return (Criteria) this;
}
public Criteria andStageLessThanOrEqualTo(String value) {
addCriterion("stage <=", value, "stage");
return (Criteria) this;
}
public Criteria andStageLike(String value) {
addCriterion("stage like", value, "stage");
return (Criteria) this;
}
public Criteria andStageNotLike(String value) {
addCriterion("stage not like", value, "stage");
return (Criteria) this;
}
public Criteria andStageIn(List<String> values) {
addCriterion("stage in", values, "stage");
return (Criteria) this;
}
public Criteria andStageNotIn(List<String> values) {
addCriterion("stage not in", values, "stage");
return (Criteria) this;
}
public Criteria andStageBetween(String value1, String value2) {
addCriterion("stage between", value1, value2, "stage");
return (Criteria) this;
}
public Criteria andStageNotBetween(String value1, String value2) {
addCriterion("stage not between", value1, value2, "stage");
return (Criteria) this;
}
public Criteria andPrincipalIsNull() {
addCriterion("principal is null");
return (Criteria) this;
}
public Criteria andPrincipalIsNotNull() {
addCriterion("principal is not null");
return (Criteria) this;
}
public Criteria andPrincipalEqualTo(String value) {
addCriterion("principal =", value, "principal");
return (Criteria) this;
}
public Criteria andPrincipalNotEqualTo(String value) {
addCriterion("principal <>", value, "principal");
return (Criteria) this;
}
public Criteria andPrincipalGreaterThan(String value) {
addCriterion("principal >", value, "principal");
return (Criteria) this;
}
public Criteria andPrincipalGreaterThanOrEqualTo(String value) {
addCriterion("principal >=", value, "principal");
return (Criteria) this;
}
public Criteria andPrincipalLessThan(String value) {
addCriterion("principal <", value, "principal");
return (Criteria) this;
}
public Criteria andPrincipalLessThanOrEqualTo(String value) {
addCriterion("principal <=", value, "principal");
return (Criteria) this;
}
public Criteria andPrincipalLike(String value) {
addCriterion("principal like", value, "principal");
return (Criteria) this;
}
public Criteria andPrincipalNotLike(String value) {
addCriterion("principal not like", value, "principal");
return (Criteria) this;
}
public Criteria andPrincipalIn(List<String> values) {
addCriterion("principal in", values, "principal");
return (Criteria) this;
}
public Criteria andPrincipalNotIn(List<String> values) {
addCriterion("principal not in", values, "principal");
return (Criteria) this;
}
public Criteria andPrincipalBetween(String value1, String value2) {
addCriterion("principal between", value1, value2, "principal");
return (Criteria) this;
}
public Criteria andPrincipalNotBetween(String value1, String value2) {
addCriterion("principal not between", value1, value2, "principal");
return (Criteria) this;
}
public Criteria andTestCaseMatchRuleIsNull() {
addCriterion("test_case_match_rule is null");
return (Criteria) this;

View File

@ -4,9 +4,12 @@
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.TestPlan">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
<result column="workspace_id" jdbcType="VARCHAR" property="workspaceId" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="description" jdbcType="VARCHAR" property="description" />
<result column="status" jdbcType="VARCHAR" property="status" />
<result column="stage" jdbcType="VARCHAR" property="stage" />
<result column="principal" jdbcType="VARCHAR" property="principal" />
<result column="test_case_match_rule" jdbcType="VARCHAR" property="testCaseMatchRule" />
<result column="executor_match_rule" jdbcType="VARCHAR" property="executorMatchRule" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
@ -74,8 +77,8 @@
</where>
</sql>
<sql id="Base_Column_List">
id, project_id, name, description, status, test_case_match_rule, executor_match_rule,
create_time, update_time
id, project_id, workspace_id, name, description, status, stage, principal, test_case_match_rule,
executor_match_rule, create_time, update_time
</sql>
<sql id="Blob_Column_List">
tags
@ -129,12 +132,14 @@
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.base.domain.TestPlan">
insert into test_plan (id, project_id, name,
description, status, test_case_match_rule,
insert into test_plan (id, project_id, workspace_id,
name, description, status,
stage, principal, test_case_match_rule,
executor_match_rule, create_time, update_time,
tags)
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
#{description,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{testCaseMatchRule,jdbcType=VARCHAR},
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{workspaceId,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},
#{tags,jdbcType=LONGVARCHAR})
</insert>
@ -147,6 +152,9 @@
<if test="projectId != null">
project_id,
</if>
<if test="workspaceId != null">
workspace_id,
</if>
<if test="name != null">
name,
</if>
@ -156,6 +164,12 @@
<if test="status != null">
status,
</if>
<if test="stage != null">
stage,
</if>
<if test="principal != null">
principal,
</if>
<if test="testCaseMatchRule != null">
test_case_match_rule,
</if>
@ -179,6 +193,9 @@
<if test="projectId != null">
#{projectId,jdbcType=VARCHAR},
</if>
<if test="workspaceId != null">
#{workspaceId,jdbcType=VARCHAR},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
@ -188,6 +205,12 @@
<if test="status != null">
#{status,jdbcType=VARCHAR},
</if>
<if test="stage != null">
#{stage,jdbcType=VARCHAR},
</if>
<if test="principal != null">
#{principal,jdbcType=VARCHAR},
</if>
<if test="testCaseMatchRule != null">
#{testCaseMatchRule,jdbcType=VARCHAR},
</if>
@ -220,6 +243,9 @@
<if test="record.projectId != null">
project_id = #{record.projectId,jdbcType=VARCHAR},
</if>
<if test="record.workspaceId != null">
workspace_id = #{record.workspaceId,jdbcType=VARCHAR},
</if>
<if test="record.name != null">
name = #{record.name,jdbcType=VARCHAR},
</if>
@ -229,6 +255,12 @@
<if test="record.status != null">
status = #{record.status,jdbcType=VARCHAR},
</if>
<if test="record.stage != null">
stage = #{record.stage,jdbcType=VARCHAR},
</if>
<if test="record.principal != null">
principal = #{record.principal,jdbcType=VARCHAR},
</if>
<if test="record.testCaseMatchRule != null">
test_case_match_rule = #{record.testCaseMatchRule,jdbcType=VARCHAR},
</if>
@ -253,9 +285,12 @@
update test_plan
set id = #{record.id,jdbcType=VARCHAR},
project_id = #{record.projectId,jdbcType=VARCHAR},
workspace_id = #{record.workspaceId,jdbcType=VARCHAR},
name = #{record.name,jdbcType=VARCHAR},
description = #{record.description,jdbcType=VARCHAR},
status = #{record.status,jdbcType=VARCHAR},
stage = #{record.stage,jdbcType=VARCHAR},
principal = #{record.principal,jdbcType=VARCHAR},
test_case_match_rule = #{record.testCaseMatchRule,jdbcType=VARCHAR},
executor_match_rule = #{record.executorMatchRule,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
@ -269,9 +304,12 @@
update test_plan
set id = #{record.id,jdbcType=VARCHAR},
project_id = #{record.projectId,jdbcType=VARCHAR},
workspace_id = #{record.workspaceId,jdbcType=VARCHAR},
name = #{record.name,jdbcType=VARCHAR},
description = #{record.description,jdbcType=VARCHAR},
status = #{record.status,jdbcType=VARCHAR},
stage = #{record.stage,jdbcType=VARCHAR},
principal = #{record.principal,jdbcType=VARCHAR},
test_case_match_rule = #{record.testCaseMatchRule,jdbcType=VARCHAR},
executor_match_rule = #{record.executorMatchRule,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
@ -286,6 +324,9 @@
<if test="projectId != null">
project_id = #{projectId,jdbcType=VARCHAR},
</if>
<if test="workspaceId != null">
workspace_id = #{workspaceId,jdbcType=VARCHAR},
</if>
<if test="name != null">
name = #{name,jdbcType=VARCHAR},
</if>
@ -295,6 +336,12 @@
<if test="status != null">
status = #{status,jdbcType=VARCHAR},
</if>
<if test="stage != null">
stage = #{stage,jdbcType=VARCHAR},
</if>
<if test="principal != null">
principal = #{principal,jdbcType=VARCHAR},
</if>
<if test="testCaseMatchRule != null">
test_case_match_rule = #{testCaseMatchRule,jdbcType=VARCHAR},
</if>
@ -316,9 +363,12 @@
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.TestPlan">
update test_plan
set project_id = #{projectId,jdbcType=VARCHAR},
workspace_id = #{workspaceId,jdbcType=VARCHAR},
name = #{name,jdbcType=VARCHAR},
description = #{description,jdbcType=VARCHAR},
status = #{status,jdbcType=VARCHAR},
stage = #{stage,jdbcType=VARCHAR},
principal = #{principal,jdbcType=VARCHAR},
test_case_match_rule = #{testCaseMatchRule,jdbcType=VARCHAR},
executor_match_rule = #{executorMatchRule,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
@ -329,9 +379,12 @@
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.TestPlan">
update test_plan
set project_id = #{projectId,jdbcType=VARCHAR},
workspace_id = #{workspaceId,jdbcType=VARCHAR},
name = #{name,jdbcType=VARCHAR},
description = #{description,jdbcType=VARCHAR},
status = #{status,jdbcType=VARCHAR},
stage = #{stage,jdbcType=VARCHAR},
principal = #{principal,jdbcType=VARCHAR},
test_case_match_rule = #{testCaseMatchRule,jdbcType=VARCHAR},
executor_match_rule = #{executorMatchRule,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},

View File

@ -0,0 +1,11 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.controller.request.testcase.QueryTestPlanRequest;
import io.metersphere.dto.TestPlanDTO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface ExtTestPlanMapper {
List<TestPlanDTO> list(@Param("request") QueryTestPlanRequest params);
}

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="io.metersphere.base.mapper.ext.ExtTestPlanMapper">
<resultMap id="BaseResultMap" type="io.metersphere.dto.TestPlanDTO"
extends="io.metersphere.base.mapper.TestPlanMapper.BaseResultMap">
<result column="project_name" property="projectName"/>
</resultMap>
<select id="list" resultMap="BaseResultMap" parameterType="io.metersphere.controller.request.testcase.QueryTestPlanRequest">
select test_plan.*, project.name as project_name
from test_plan
left join project on test_plan.project_id = project.id
<where>
<if test="request.name != null">
and test_plan.name like CONCAT('%', #{request.name},'%')
</if>
<if test="request.workspaceId != null">
AND project.workspace_id = #{request.workspaceId}
</if>
<if test="request.projectId != null">
AND project.id = #{request.projectId}
</if>
<if test="request.id != null">
AND test_plan.id = #{request.id}
</if>
</where>
<if test="request.recent">
order by test_plan.update_time desc
</if>
</select>
</mapper>

View File

@ -0,0 +1,5 @@
package io.metersphere.commons.constants;
public enum TestPlanStatus {
Prepare, Running, Completed
}

View File

@ -0,0 +1,53 @@
package io.metersphere.controller;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.base.domain.TestCase;
import io.metersphere.base.domain.TestCaseWithBLOBs;
import io.metersphere.base.domain.TestPlan;
import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager;
import io.metersphere.controller.request.testcase.QueryTestPlanRequest;
import io.metersphere.dto.TestPlanDTO;
import io.metersphere.service.TestCaseService;
import io.metersphere.service.TestPlanService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@RequestMapping("/test/plan")
@RestController
public class TestPlanController {
@Resource
TestPlanService testPlanService;
@PostMapping("/list/{goPage}/{pageSize}")
public Pager<List<TestPlanDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestPlanRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, testPlanService.listTestPlan(request));
}
@PostMapping("/get/{testPlanId}")
public List<TestPlan> getTestPlan(@PathVariable String testPlanId){
return testPlanService.getTestPlan(testPlanId);
}
@PostMapping("/add")
public void addTestPlan(@RequestBody TestPlan testPlan){
testPlanService.addTestPlan(testPlan);
}
@PostMapping("/edit")
public void editTestPlan(@RequestBody TestPlan testPlan){
testPlanService.editTestPlan(testPlan);
}
@PostMapping("/delete/{testPlanId}")
public int deleteTestPlan(@PathVariable String testPlanId){
return testPlanService.deleteTestPlan(testPlanId);
}
}

View File

@ -0,0 +1,28 @@
package io.metersphere.controller.request.testcase;
import io.metersphere.base.domain.TestCase;
import io.metersphere.base.domain.TestPlan;
import java.util.List;
public class QueryTestPlanRequest extends TestPlan {
private String workspaceId;
private boolean recent = false;
public boolean isRecent() {
return recent;
}
public void setRecent(boolean recent) {
this.recent = recent;
}
public String getWorkspaceId() {
return workspaceId;
}
public void setWorkspaceId(String workspaceId) {
this.workspaceId = workspaceId;
}
}

View File

@ -0,0 +1,15 @@
package io.metersphere.dto;
import io.metersphere.base.domain.TestPlan;
public class TestPlanDTO extends TestPlan {
private String projectName;
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
}

View File

@ -32,24 +32,25 @@ public class JtlResolver {
return null;
}
private static RequestStatisticsDTO getOneRpsResult(Map<String, List<Metric>> map){
RequestStatisticsDTO statisticsDTO = new RequestStatisticsDTO();
public static RequestStatisticsDTO getRequestStatistics(String jtlString){
List<Metric> total = resolver(jtlString);
Map<String, List<Metric>> map = total.stream().collect(Collectors.groupingBy(Metric::getLabel));
List<RequestStatistics> requestStatisticsList = new ArrayList<>();
Iterator<Map.Entry<String, List<Metric>>> iterator = map.entrySet().iterator();
List<Integer> allelapse = new ArrayList<>();
DecimalFormat df = new DecimalFormat("0.00");
int totalAverage = 0;
float allBytes = 0f;
while (iterator.hasNext()) {
Map.Entry<String, List<Metric>> entry = iterator.next();
String label = entry.getKey();
List<Metric> list = entry.getValue();
List<String> timestampList = list.stream().map(Metric::getTimestamp).collect(Collectors.toList());
int index=0;
int sumElapsed=0;
int failSize = 0;
// 以list为单位 total bytes
float totalBytes = 0f;
List<Integer> elapsedList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
try {
Metric row = list.get(i);
@ -64,24 +65,25 @@ public class JtlResolver {
}
String bytes = row.getBytes();
totalBytes += Float.parseFloat(bytes);
allBytes += Float.parseFloat(bytes);
index++;
}catch (Exception e){
System.out.println("exception i:"+i);
}
}
Collections.sort(elapsedList);
int tp90 = elapsedList.size()*90/100;
int tp95 = elapsedList.size()*95/100;
int tp99 = elapsedList.size()*99/100;
long l = Long.valueOf(timestampList.get(timestampList.size()-1)) - Long.valueOf(timestampList.get(0));
list.sort(Comparator.comparing(t0 -> Long.valueOf(t0.getTimestamp())));
long time = Long.parseLong(list.get(list.size()-1).getTimestamp()) - Long.parseLong(list.get(0).getTimestamp()) + Long.parseLong(list.get(list.size()-1).getElapsed());
RequestStatistics requestStatistics = new RequestStatistics();
requestStatistics.setRequestLabel(label);
requestStatistics.setSamples(index);
String s = df.format((float)sumElapsed/index);
requestStatistics.setAverage(s+"");
@ -92,23 +94,27 @@ public class JtlResolver {
* 3从序列A中找到第C个请求它的响应时间即为TP90的值
* 其余相似的指标还有TP95, TP99
*/
// todo tp90
requestStatistics.setTp90(elapsedList.get(tp90)+"");
requestStatistics.setTp95(elapsedList.get(tp95)+"");
requestStatistics.setTp99(elapsedList.get(tp99)+"");
double avgHits = (double)list.size() / (time * 1.0 / 1000);
requestStatistics.setAvgHits(df.format(avgHits));
requestStatistics.setMin(elapsedList.get(0)+"");
requestStatistics.setMax(elapsedList.get(index-1)+"");
requestStatistics.setErrors(String.format("%.2f",failSize*100.0/index)+"%");
requestStatistics.setErrors(df.format(failSize * 100.0 / index)+"%");
requestStatistics.setKo(failSize);
/**
* 所有的相同请求的bytes总和 / 1024 / 请求持续运行的时间=sum(bytes)/1024/total time
* total time = 最大时间戳 - 最小时间戳 + 最后请求的响应时间
*/
// todo Avg Bandwidth(KBytes/s) 请求之间时间戳间隔l 可能为0
requestStatistics.setKbPerSec(String.format("%.2f",totalBytes*1.0/1024/(l*1.0/1000)));
requestStatistics.setKbPerSec(df.format(totalBytes * 1.0 / 1024 / (time * 1.0 / 1000)));
requestStatisticsList.add(requestStatistics);
}
Collections.sort(allelapse);
Collections.sort(allelapse);
int totalTP90 = allelapse.size()*90/100;
int totalTP95 = allelapse.size()*95/100;
int totalTP99 = allelapse.size()*99/100;
@ -118,11 +124,13 @@ public class JtlResolver {
int allSamples = requestStatisticsList.stream().mapToInt(RequestStatistics::getSamples).sum();
int failSize = requestStatisticsList.stream().mapToInt(RequestStatistics::getKo).sum();
double errors = (double)failSize / allSamples * 100;
String totalerrors = df.format(errors);
double average = (double)totalAverage / allSamples;
String totalaverage = df.format(average);
RequestStatisticsDTO statisticsDTO = new RequestStatisticsDTO();
statisticsDTO.setRequestStatisticsList(requestStatisticsList);
statisticsDTO.setTotalLabel("Total");
statisticsDTO.setTotalSamples(String.valueOf(allSamples));
@ -133,16 +141,14 @@ public class JtlResolver {
statisticsDTO.setTotalTP90(String.valueOf(allelapse.get(totalTP90)));
statisticsDTO.setTotalTP95(String.valueOf(allelapse.get(totalTP95)));
statisticsDTO.setTotalTP99(String.valueOf(allelapse.get(totalTP99)));
// todo
// statisticsDTO.setTotalAvgBandwidth();
return statisticsDTO;
}
// report - Aggregate Report
public static RequestStatisticsDTO getRequestStatistics(String jtlString) {
List<Metric> totalLines = resolver(jtlString);
Map<String, List<Metric>> map = totalLines.stream().collect(Collectors.groupingBy(Metric::getLabel));
return getOneRpsResult(map);
total.sort(Comparator.comparing(t0 -> Long.valueOf(t0.getTimestamp())));
long ms = Long.valueOf(total.get(total.size()-1).getTimestamp()) - Long.valueOf(total.get(0).getTimestamp()) + Long.parseLong(total.get(total.size()-1).getElapsed());
double avgThroughput = (double)total.size() / (ms * 1.0 / 1000);
statisticsDTO.setTotalAvgHits(df.format(avgThroughput));
statisticsDTO.setTotalAvgBandwidth(df.format(allBytes * 1.0 / 1024 / (ms * 1.0 / 1000)));
return statisticsDTO;
}
// report - Errors
@ -259,8 +265,8 @@ public class JtlResolver {
Long timestamp1 = Long.valueOf(total.get(0).getTimestamp());
Long timestamp2 = Long.valueOf(total.get(total.size()-1).getTimestamp());
long seconds = (timestamp2 - timestamp1) / 1000;
double avgThroughput = (double)total.size() / seconds;
long time = timestamp2 - timestamp1 + Long.parseLong(total.get(total.size()-1).getElapsed());
double avgThroughput = (double)total.size() / (time * 1.0 / 1000);
testOverview.setAvgThroughput(df.format(avgThroughput));
List<Metric> falseList = total.stream().filter(metric -> StringUtils.equals("false", metric.getSuccess())).collect(Collectors.toList());
@ -270,7 +276,7 @@ public class JtlResolver {
double avg = totalElapsed * 1.0 / total.size() / 1000; // s
testOverview.setAvgResponseTime(df.format(avg));
double bandwidth = totalBytes * 1.0 / 1024 / seconds;
double bandwidth = totalBytes * 1.0 / time;
testOverview.setAvgBandwidth(df.format(bandwidth));
return testOverview;

View File

@ -12,7 +12,7 @@ public class RequestStatistics {
private String average;
/**平均点击率*/
private Double avgHits;
private String avgHits;
/**90% Line*/
private String tp90;
@ -62,11 +62,11 @@ public class RequestStatistics {
this.average = average;
}
public Double getAvgHits() {
public String getAvgHits() {
return avgHits;
}
public void setAvgHits(Double avgHits) {
public void setAvgHits(String avgHits) {
this.avgHits = avgHits;
}

View File

@ -28,6 +28,8 @@ public class RequestStatisticsDTO extends RequestStatistics {
private String totalAvgBandwidth;
private String totalAvgHits;
public List<RequestStatistics> getRequestStatisticsList() {
return requestStatisticsList;
}
@ -115,4 +117,12 @@ public class RequestStatisticsDTO extends RequestStatistics {
public void setTotalAvgBandwidth(String totalAvgBandwidth) {
this.totalAvgBandwidth = totalAvgBandwidth;
}
public String getTotalAvgHits() {
return totalAvgHits;
}
public void setTotalAvgHits(String totalAvgHits) {
this.totalAvgHits = totalAvgHits;
}
}

View File

@ -0,0 +1,57 @@
package io.metersphere.service;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.TestCaseMapper;
import io.metersphere.base.mapper.TestPlanMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
import io.metersphere.commons.constants.TestPlanStatus;
import io.metersphere.controller.request.testcase.QueryTestCaseRequest;
import io.metersphere.controller.request.testcase.QueryTestPlanRequest;
import io.metersphere.dto.TestPlanDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;
@Service
@Transactional(rollbackFor = Exception.class)
public class TestPlanService {
@Resource
TestPlanMapper testPlanMapper;
@Resource
ExtTestPlanMapper extTestPlanMapper;
public void addTestPlan(TestPlan testPlan) {
testPlan.setId(UUID.randomUUID().toString());
testPlan.setStatus(TestPlanStatus.Prepare.name());
testPlan.setCreateTime(System.currentTimeMillis());
testPlan.setUpdateTime(System.currentTimeMillis());
testPlanMapper.insert(testPlan);
}
public List<TestPlan> getTestPlan(String testPlanId) {
TestPlanExample testPlanExample = new TestPlanExample();
testPlanExample.createCriteria().andIdEqualTo(testPlanId);
return testPlanMapper.selectByExampleWithBLOBs(testPlanExample);
}
public int editTestPlan(TestPlan testPlan) {
testPlan.setUpdateTime(System.currentTimeMillis());
return testPlanMapper.updateByPrimaryKeySelective(testPlan);
}
public int deleteTestPlan(String testPalnId) {
return testPlanMapper.deleteByPrimaryKey(testPalnId);
}
public List<TestPlanDTO> listTestPlan(QueryTestPlanRequest request) {
return extTestPlanMapper.list(request);
}
}

View File

@ -224,22 +224,23 @@ CREATE TABLE IF NOT EXISTS `fuc_test_report` (
-- funcional end
-- track start
CREATE TABLE IF NOT EXISTS `test_plan` (
`id` varchar(50) NOT NULL COMMENT 'Test Plan ID',
`project_id` varchar(50) NOT NULL COMMENT 'Project ID this plan belongs to',
`workspace_id` varchar(50) NOT NULL COMMENT 'Workspace ID this plan belongs to',
`name` varchar(64) NOT NULL COMMENT 'Plan name',
`description` varchar(255) DEFAULT NULL COMMENT 'Plan description',
`status` varchar(20) NOT NULL COMMENT 'Plan status',
`stage` varchar(30) NOT NULL COMMENT 'Plan stage',
`principal` varchar(50) NOT NULL COMMENT 'Plan principal',
`test_case_match_rule` varchar(255) DEFAULT NULL COMMENT 'Test case match rule',
`executor_match_rule` varchar(255) DEFAULT NULL COMMENT 'Executor match rule)',
`tags` text COMMENT 'Test plan tags (JSON format)',
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp',
PRIMARY KEY (`id`),
FOREIGN KEY (`project_id`) references project(`id`)
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp'
PRIMARY KEY (`id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
@ -253,9 +254,7 @@ CREATE TABLE IF NOT EXISTS `test_case_node` (
`p_id` int(13) DEFAULT NULL COMMENT 'Parent node ID',
`level` int(10) DEFAULT 1 COMMENT 'Node level',
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp',
FOREIGN KEY (`p_id`) references test_case_node(`id`) ON DELETE CASCADE,
FOREIGN KEY (`project_id`) references project(`id`)
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp'
)
AUTO_INCREMENT = 1
ENGINE = InnoDB
@ -276,10 +275,8 @@ CREATE TABLE IF NOT EXISTS `test_case` (
`remark` text DEFAULT NULL COMMENT 'Test case remark',
`steps` text DEFAULT NULL COMMENT 'Test case steps (JSON format)',
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp',
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp'
PRIMARY KEY (`id`),
FOREIGN KEY (`project_id`) references project(`id`),
FOREIGN KEY (`node_id`) references test_case_node(`id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
@ -295,9 +292,7 @@ CREATE TABLE IF NOT EXISTS `test_plan_test_case` (
`results` longtext COMMENT 'Test case result',
`remark` varchar(255) DEFAULT NULL COMMENT 'Test case remark',
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp',
FOREIGN KEY (`plan_id`) references test_plan(`id`),
FOREIGN KEY (`case_id`) references test_case(`id`)
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp'
)
AUTO_INCREMENT = 1
ENGINE = InnoDB

View File

@ -58,11 +58,11 @@
/>
</el-table-column>
<!-- <el-table-column-->
<!-- prop="avgHits"-->
<!-- label="Avg Hits/s"-->
<!-- width="150"-->
<!-- />-->
<el-table-column
prop="avgHits"
label="Avg Hits/s"
width="100"
/>
<el-table-column
prop="kbPerSec"
@ -101,6 +101,8 @@
sums[6] = this.totalInfo.totalTP90;
sums[7] = this.totalInfo.totalTP95;
sums[8] = this.totalInfo.totalTP99;
sums[9] = this.totalInfo.totalAvgHits;
sums[10] = this.totalInfo.totalAvgBandwidth;
return sums;
}
},

View File

@ -25,8 +25,8 @@
</el-aside>
<test-case-list
@opentestCaseEditDialog="opentestCaseEditDialog"
@testCaseEdit="opentestCaseEditDialog"
@openTestCaseEditDialog="openTestCaseEditDialog"
@testCaseEdit="openTestCaseEditDialog"
ref="testCaseList"></test-case-list>
</el-container>
@ -110,10 +110,10 @@
getCaseByNodeIds(data) {
this.$refs.testCaseList.initTableData(data);
},
opentestCaseEditDialog(data) {
openTestCaseEditDialog(data) {
this.setNodePathOption(this.$refs.nodeTree.treeNodes);
this.setMaintainerOptions();
this.$refs.testCaseEditDialog.opentestCaseEditDialog(data);
this.$refs.testCaseEditDialog.openTestCaseEditDialog(data);
},
setNodePathOption(nodes) {
let moduleOptions = [];

View File

@ -181,7 +181,7 @@
<script>
export default {
name: "CreateCaseDialog",
name: "TestCaseEdit",
data() {
return {
dialogFormVisible: false,
@ -218,7 +218,7 @@
projectId: null
},
methods: {
opentestCaseEditDialog(testCase) {
openTestCaseEditDialog(testCase) {
this.resetForm();
this.operationType = 'add';
if(testCase){
@ -262,7 +262,6 @@
param.projectId = this.projectId;
this.$post('/test/case/' + this.operationType, param, () => {
this.$message.success(this.$t('commons.save_success'));
this.resetForm();
this.dialogFormVisible = false;
this.$emit("refresh");
});

View File

@ -10,13 +10,13 @@
<el-col :span="1" :offset="8">
<el-button icon="el-icon-circle-plus-outline" size="small" round
@click="$emit('opentestCaseEditDialog')" >{{$t('commons.create')}}</el-button>
@click="$emit('openTestCaseEditDialog')" >{{$t('commons.create')}}</el-button>
</el-col>
<el-col :span="1" >
<el-button
icon="el-icon-refresh" size="small" round
@click="initTableData(null)">{{$t('commons.refresh')}}</el-button>
@click="initTableData()">{{$t('commons.refresh')}}</el-button>
</el-col>
<el-col :span="5">
@ -138,7 +138,7 @@
},
created: function () {
this.projectId = this.$route.params.projectId;
this.initTableData(null);
this.initTableData();
},
methods: {
initTableData(nodeIds) {
@ -155,18 +155,18 @@
});
},
search() {
this.initTableData(null);
this.initTableData();
},
buildPagePath(path) {
return path + "/" + this.currentPage + "/" + this.pageSize;
},
handleSizeChange(size) {
this.pageSize = size;
this.initTableData(null);
this.initTableData();
},
handleCurrentChange(current) {
this.currentPage = current;
this.initTableData(null);
this.initTableData();
},
handleSelectionChange(val) {
this.multipleSelection = val;
@ -185,9 +185,9 @@
});
},
_handleDelete(testCase) {
let testCaseId = testCase.id
let testCaseId = testCase.id;
this.$post('/test/case/delete/' + testCaseId, {}, () => {
this.initTableData(null);
this.initTableData();
this.$message({
message: this.$t('commons.delete_success'),
type: 'success'

View File

@ -1,196 +1,41 @@
<template>
<div class="testplan-container" v-loading="result.loading">
<div class="main-content">
<el-card>
<div slot="header">
<el-row type="flex" justify="space-between" align="middle">
<span class="title">{{$t('commons.test')}}</span>
<span class="search">
<el-input type="text" size="small" :placeholder="$t('load_test.search_by_name')"
prefix-icon="el-icon-search"
maxlength="60"
v-model="condition" @change="search" clearable/>
</span>
</el-row>
</div>
<el-table :data="tableData" class="test-content">
<el-table-column
prop="name"
:label="$t('commons.name')"
width="150"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="description"
:label="$t('commons.description')"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="projectName"
:label="$t('load_test.project_name')"
width="150"
show-overflow-tooltip>
</el-table-column>
<el-table-column
width="250"
:label="$t('commons.create_time')">
<template slot-scope="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column
width="250"
:label="$t('commons.update_time')">
<template slot-scope="scope">
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column
width="150"
:label="$t('commons.operating')">
<template slot-scope="scope">
<el-button @click="handleEdit(scope.row)" type="primary" icon="el-icon-edit" size="mini" circle/>
<el-button @click="handleDelete(scope.row)" type="danger" icon="el-icon-delete" size="mini" circle/>
</template>
</el-table-column>
</el-table>
<div>
<el-row>
<el-col :span="22" :offset="1">
<div class="table-page">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage"
:page-sizes="[5, 10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</el-col>
</el-row>
</div>
</el-card>
</div>
<test-plan-list
@openTestPlanEditDialog="openTestPlanEditDialog"
@testPlanEdit="openTestPlanEditDialog"
ref="testPlanList"></test-plan-list>
<test-plan-edit
ref="testPlanEditDialog"
@refresh="refreshTestPlanList"></test-plan-edit>
</div>
</template>
<script>
import TestPlanList from './components/TestPlanList';
import TestPlanEdit from './components/TestPlanEdit';
export default {
name: "TrackTestPlan",
name: "TestPlan",
components: {TestPlanList, TestPlanEdit},
data() {
return {
result: {},
queryPath: "/testplan/list",
deletePath: "/testplan/delete",
condition: "",
projectId: null,
tableData: [],
multipleSelection: [],
currentPage: 1,
pageSize: 5,
total: 0,
loading: false,
testId: null,
}
},
watch: {
'$route'(to) {
this.projectId = to.params.projectId;
this.initTableData();
}
},
created: function () {
this.projectId = this.$route.params.projectId;
this.initTableData();
},
methods: {
initTableData() {
let param = {
name: this.condition,
};
if (this.projectId !== 'all') {
param.projectId = this.projectId;
openTestPlanEditDialog(data) {
this.$refs.testPlanEditDialog.openTestPlanEditDialog(data);
},
refreshTestPlanList() {
this.$refs.testPlanList.initTableData();
}
this.result = this.$post(this.buildPagePath(this.queryPath), param, response => {
let data = response.data;
this.total = data.itemCount;
this.tableData = data.listObject;
});
},
search() {
this.initTableData();
},
buildPagePath(path) {
return path + "/" + this.currentPage + "/" + this.pageSize;
},
handleSizeChange(size) {
this.pageSize = size;
this.initTableData();
},
handleCurrentChange(current) {
this.currentPage = current;
this.initTableData();
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
handleEdit(testPlan) {
this.$router.push({
path: '/performance/plan/edit/' + testPlan.id,
})
},
handleDelete(testPlan) {
this.$alert(this.$t('load_test.delete_confirm') + testPlan.name + "", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
this._handleDelete(testPlan);
}
}
});
},
_handleDelete(testPlan) {
let data = {
id: testPlan.id
};
this.result = this.$post(this.deletePath, data, () => {
this.$message({
message: this.$t('commons.delete_success'),
type: 'success'
});
this.initTableData();
});
},
}
}
</script>
<style scoped>
.testplan-container {
padding: 15px;
width: 100%;
height: 100%;
box-sizing: border-box;
}
.main-content {
margin: 0 auto;
width: 100%;
max-width: 1200px;
}
.test-content {
width: 100%;
}
.table-page {
padding-top: 20px;
margin-right: -9px;
float: right;
}
</style>

View File

@ -0,0 +1,195 @@
<template>
<div>
<el-dialog :title="$t('test_track.create_plan')"
:visible.sync="dialogFormVisible"
width="65%">
<el-form :model="form" :rules="rules" ref="planFrom">
<el-row>
<el-col :span="8" :offset="1">
<el-form-item
:placeholder="$t('test_track.input_name')"
:label="$t('test_track.plan_name')"
:label-width="formLabelWidth"
prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-col>
<el-col :span="11" :offset="2">
<el-form-item :label="$t('test_track.plan_project')" :label-width="formLabelWidth" prop="projectId">
<el-select
v-model="form.projectId"
:placeholder="$t('test_track.input_plan_project')"
filterable>
<el-option
v-for="item in projects"
:key="item.id"
:label="item.path"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="10" :offset="1">
<el-form-item :label="$t('test_track.plan_principal')" :label-width="formLabelWidth" prop="principal">
<el-select v-model="form.principal" :placeholder="$t('test_track.input_plan_principal')" filterable>
<el-option
v-for="item in principalOptions"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('test_track.plan_stage')" :label-width="formLabelWidth" prop="stage">
<el-select v-model="form.stage" clearable :placeholder="$t('test_track.input_plan_stage')">
<el-option :label="$t('test_track.smoke_test')" value="smoke"></el-option>
<el-option :label="$t('test_track.functional_test')" value="functional"></el-option>
<el-option :label="$t('test_track.integration_testing')" value="integration"></el-option>
<el-option :label="$t('test_track.system_test')" value="system"></el-option>
<el-option :label="$t('test_track.version_validation')" value="version"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" justify="left" style="margin-top: 10px;">
<el-col :span="19" :offset="1">
<el-form-item :label="$t('commons.description')" :label-width="formLabelWidth" prop="description">
<el-input v-model="form.description"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
:rows="2"
:placeholder="$t('commons.input_content')"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button
@click="dialogFormVisible = false">
{{$t('test_track.cancel')}}
</el-button>
<el-button
type="primary"
@click="savePlan">
{{$t('test_track.confirm')}}
</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {WORKSPACE_ID} from '../../../../../common/constants';
export default {
name: "TestPlanEdit",
data() {
return {
dialogFormVisible: false,
form: {
name: '',
projectId: '',
principal: '',
stage: '',
description: ''
},
rules:{
name :[{required: true, message: this.$t('test_track.input_name'), trigger: 'blur'}],
projectId :[{required: true, message: this.$t('test_track.input_plan_project'), trigger: 'change'}],
principal :[{required: true, message: this.$t('test_track.input_plan_principal'), trigger: 'change'}],
stage :[{required: true, message: this.$t('test_track.input_plan_stage'), trigger: 'change'}]
},
formLabelWidth: "120px",
operationType: '',
projects: [],
principalOptions: []
};
},
methods: {
openTestPlanEditDialog(testPlan) {
this.resetForm();
this.getProjects();
this.setPrincipalOptions();
this.operationType = 'add';
if(testPlan){
//
this.operationType = 'edit';
let tmp = {};
Object.assign(tmp, testPlan);
Object.assign(this.form, tmp);
}
this.dialogFormVisible = true;
},
savePlan(){
this.$refs['planFrom'].validate((valid) => {
if (valid) {
let param = {};
Object.assign(param, this.form);
param.workspaceId = localStorage.getItem(WORKSPACE_ID);
this.$post('/test/plan/' + this.operationType, param, () => {
this.$message.success(this.$t('commons.save_success'));
this.dialogFormVisible = false;
this.$emit("refresh");
});
} else {
return false;
}
});
},
getProjects() {
this.$get("/project/listAll", (response) => {
if (response.success) {
this.projects = response.data;
} else {
this.$message()({
type: 'warning',
message: response.message
});
}
});
},
setPrincipalOptions() {
let workspaceId = localStorage.getItem(WORKSPACE_ID);
this.$post('/user/ws/member/list/all', {workspaceId:workspaceId}, response => {
this.principalOptions = response.data;
});
},
resetForm() {
//
if (this.$refs['planFrom']) {
this.$refs['planFrom'].validate((valid) => {
this.$refs['planFrom'].resetFields();
this.form.name = '';
this.form.projectId = '';
this.form.principal = '';
this.form.stage = '';
this.form.description = '';
return true;
});
}
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,230 @@
<template>
<div class="testplan-container">
<el-main class="main-content">
<el-card>
<div slot="header">
<el-row type="flex" justify="space-between" align="middle">
<el-col :span="5">
<span class="title">{{$t('test_track.test_plan')}}</span>
</el-col>
<el-col :span="1" :offset="8">
<el-button icon="el-icon-circle-plus-outline" size="small" round
@click="$emit('openTestPlanEditDialog')" >{{$t('commons.create')}}</el-button>
</el-col>
<el-col :span="1" >
<el-button
icon="el-icon-refresh" size="small" round
@click="initTableData()">{{$t('commons.refresh')}}</el-button>
</el-col>
<el-col :span="5">
<span class="search">
<el-input type="text" size="small" :placeholder="$t('load_test.search_by_name')"
prefix-icon="el-icon-search"
maxlength="60"
v-model="condition" @change="search" clearable/>
</span>
</el-col>
</el-row>
</div>
<el-table
:data="tableData"
class="test-content">
<el-table-column
prop="name"
:label="$t('commons.name')"
width="130"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="principal"
:label="$t('test_track.plan_principal')"
width="130"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="status"
:label="$t('test_track.plan_status')"
width="130"
show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.status == 'Prepare'">{{$t('test_track.plan_status_prepare')}}</span>
<span v-if="scope.row.status == 'Running'">{{$t('test_track.plan_status_running')}}</span>
<span v-if="scope.row.status == 'Completed'">{{$t('test_track.plan_status_completed')}}</span>
</template>
</el-table-column>
<el-table-column
prop="stage"
:label="$t('test_track.plan_stage')"
width="130"
show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.stage == 'smoke'">{{$t('test_track.smoke_test')}}</span>
<span v-if="scope.row.stage == 'functional'">{{$t('test_track.functional_test')}}</span>
<span v-if="scope.row.stage == 'integration'">{{$t('test_track.integration_testing')}}</span>
<span v-if="scope.row.stage == 'system'">{{$t('test_track.system_test')}}</span>
<span v-if="scope.row.stage == 'version'">{{$t('test_track.version_validation')}}</span>
</template>
</el-table-column>
<el-table-column
prop="projectId"
:label="$t('test_track.plan_project')"
width="160"
show-overflow-tooltip>
</el-table-column>
<el-table-column
width="160"
:label="$t('commons.create_time')">
<template slot-scope="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column
width="160"
:label="$t('commons.update_time')">
<template slot-scope="scope">
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column
width="160"
:label="$t('commons.operating')">
<template slot-scope="scope">
<el-button @click="handleEdit(scope.row)" type="primary" icon="el-icon-edit" size="mini" circle/>
<el-button @click="handleDelete(scope.row)" type="danger" icon="el-icon-delete" size="mini" circle/>
</template>
</el-table-column>
</el-table>
<div>
<el-row>
<el-col :span="22" :offset="1">
<div class="table-page">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage"
:page-sizes="[5, 10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</el-col>
</el-row>
</div>
</el-card>
</el-main>
</div>
</template>
<script>
export default {
name: "TestPlanList",
data() {
return {
result: {},
queryPath: "/test/plan/list",
deletePath: "/test/plan/delete",
condition: "",
tableData: [],
multipleSelection: [],
currentPage: 1,
pageSize: 5,
total: 0,
loadingRequire: {project: true, testCase: true},
testId: null,
}
},
created: function () {
this.projectId = this.$route.params.projectId;
this.initTableData();
},
methods: {
initTableData(nodeIds) {
let param = {
name: this.condition,
};
param.nodeIds = nodeIds;
this.$post(this.buildPagePath(this.queryPath), param, response => {
this.loadingRequire.testCase = false;
let data = response.data;
this.total = data.itemCount;
this.tableData = data.listObject;
});
},
search() {
this.initTableData();
},
buildPagePath(path) {
return path + "/" + this.currentPage + "/" + this.pageSize;
},
handleSizeChange(size) {
this.pageSize = size;
this.initTableData();
},
handleCurrentChange(current) {
this.currentPage = current;
this.initTableData();
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
handleEdit(testPlan) {
this.$emit('testPlanEdit', testPlan);
},
handleDelete(testPlan) {
this.$alert(this.$t('load_test.delete_confirm') + testPlan.name + "", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
this._handleDelete(testPlan);
}
}
});
},
_handleDelete(testPlan) {
let testPlanId = testPlan.id;
this.$post('/test/plan/delete/' + testPlanId, {}, () => {
this.initTableData();
this.$message({
message: this.$t('commons.delete_success'),
type: 'success'
});
});
}
}
}
</script>
<style scoped>
.testplan-container {
padding: 15px;
width: 100%;
height: 100%;
box-sizing: border-box;
}
.main-content {
margin: 0 auto;
width: 100%;
max-width: 1200px;
}
.test-content {
width: 100%;
}
.table-page {
padding-top: 20px;
margin-right: -9px;
float: right;
}
</style>

View File

@ -176,7 +176,6 @@ export default {
'case_list': 'Test Case List',
'create_case': 'Create Case',
'test_plan': 'Test Plan',
'create_plan': 'Create Plan',
'no_project': 'There is no project in this workspace, please create the project first',
'priority': 'Priority',
'type': 'Type',
@ -205,7 +204,24 @@ export default {
'rename': 'rename',
'add_submodule': 'Add submodule',
'add_module': 'Add module',
'module_name': 'Module name'
'module_name': 'Module name',
'create_plan': 'Create test plan',
'plan_name': 'Test plan name',
'plan_project': 'Related projects',
'plan_stage': 'Testing phase',
'plan_status': 'The current state',
'smoke_test': 'Smoke test',
'functional_test': 'Functional test',
'integration_testing': 'Integration testing',
'system_test': 'System test',
'version_validation': 'Version validation',
'plan_principal': 'principal',
'input_plan_principal': 'Please select principal',
'input_plan_project': 'Please select project',
'input_plan_stage': 'Please select stage',
'plan_status_prepare': ' Not started',
'plan_status_running': 'Starting',
'plan_status_completed': 'Completed',
},
i18n: {
'home': 'Home'

View File

@ -176,7 +176,6 @@ export default {
'case_list': '用例列表',
'create_case': '创建用例',
'test_plan': '测试计划',
'create_plan': '创建计划',
'no_project': '该工作空间下无项目,请先创建项目',
'priority': '优先级',
'type': '类型',
@ -205,7 +204,25 @@ export default {
'rename': '重命名',
'add_submodule': '添加子模块',
'add_module': '添加模块',
'module_name': '模块名称'
'module_name': '模块名称',
'create_plan': '新建测试计划',
'plan_name': '计划名称',
'plan_project': '所属项目',
'plan_stage': '测试阶段',
'plan_status': '当前状态',
'smoke_test': '冒烟测试',
'functional_test': '功能测试',
'integration_testing': '集成测试',
'system_test': '系统测试',
'version_validation': '版本验证',
'plan_principal': '负责人',
'input_plan_principal': '请选择负责人',
'input_plan_project': '请选择所属项目',
'input_plan_stage': '请选择测试阶段',
'plan_status_prepare': '未开始',
'plan_status_running': '进行中',
'plan_status_completed': '已完成'
},
i18n: {
'home': '首页'