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

This commit is contained in:
wenyann 2020-05-29 11:05:57 +08:00
commit 353338b7c2
35 changed files with 823 additions and 139 deletions

View File

@ -7,7 +7,9 @@ import io.metersphere.api.dto.DeleteAPITestRequest;
import io.metersphere.api.dto.QueryAPITestRequest; import io.metersphere.api.dto.QueryAPITestRequest;
import io.metersphere.api.dto.SaveAPITestRequest; import io.metersphere.api.dto.SaveAPITestRequest;
import io.metersphere.api.service.APITestService; import io.metersphere.api.service.APITestService;
import io.metersphere.base.domain.ApiTest;
import io.metersphere.base.domain.ApiTestWithBLOBs; import io.metersphere.base.domain.ApiTestWithBLOBs;
import io.metersphere.base.domain.LoadTest;
import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.Pager;
@ -44,6 +46,11 @@ public class APITestController {
return PageUtils.setPageInfo(page, apiTestService.list(request)); return PageUtils.setPageInfo(page, apiTestService.list(request));
} }
@GetMapping("/list/{projectId}")
public List<ApiTest> list(@PathVariable String projectId) {
return apiTestService.getApiTestByProjectId(projectId);
}
@PostMapping(value = "/create", consumes = {"multipart/form-data"}) @PostMapping(value = "/create", consumes = {"multipart/form-data"})
public void create(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> files) { public void create(@RequestPart("request") SaveAPITestRequest request, @RequestPart(value = "files") List<MultipartFile> files) {
apiTestService.create(request, files); apiTestService.create(request, files);

View File

@ -167,4 +167,7 @@ public class APITestService {
} }
} }
public List<ApiTest> getApiTestByProjectId(String projectId) {
return extApiTestMapper.getApiTestByProjectId(projectId);
}
} }

View File

@ -29,5 +29,7 @@ public class TestCase implements Serializable {
private Long updateTime; private Long updateTime;
private String testId;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@ -923,6 +923,76 @@ public class TestCaseExample {
addCriterion("update_time not between", value1, value2, "updateTime"); addCriterion("update_time not between", value1, value2, "updateTime");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andTestIdIsNull() {
addCriterion("test_id is null");
return (Criteria) this;
}
public Criteria andTestIdIsNotNull() {
addCriterion("test_id is not null");
return (Criteria) this;
}
public Criteria andTestIdEqualTo(String value) {
addCriterion("test_id =", value, "testId");
return (Criteria) this;
}
public Criteria andTestIdNotEqualTo(String value) {
addCriterion("test_id <>", value, "testId");
return (Criteria) this;
}
public Criteria andTestIdGreaterThan(String value) {
addCriterion("test_id >", value, "testId");
return (Criteria) this;
}
public Criteria andTestIdGreaterThanOrEqualTo(String value) {
addCriterion("test_id >=", value, "testId");
return (Criteria) this;
}
public Criteria andTestIdLessThan(String value) {
addCriterion("test_id <", value, "testId");
return (Criteria) this;
}
public Criteria andTestIdLessThanOrEqualTo(String value) {
addCriterion("test_id <=", value, "testId");
return (Criteria) this;
}
public Criteria andTestIdLike(String value) {
addCriterion("test_id like", value, "testId");
return (Criteria) this;
}
public Criteria andTestIdNotLike(String value) {
addCriterion("test_id not like", value, "testId");
return (Criteria) this;
}
public Criteria andTestIdIn(List<String> values) {
addCriterion("test_id in", values, "testId");
return (Criteria) this;
}
public Criteria andTestIdNotIn(List<String> values) {
addCriterion("test_id not in", values, "testId");
return (Criteria) this;
}
public Criteria andTestIdBetween(String value1, String value2) {
addCriterion("test_id between", value1, value2, "testId");
return (Criteria) this;
}
public Criteria andTestIdNotBetween(String value1, String value2) {
addCriterion("test_id not between", value1, value2, "testId");
return (Criteria) this;
}
} }
public static class Criteria extends GeneratedCriteria { public static class Criteria extends GeneratedCriteria {

View File

@ -21,5 +21,7 @@ public class TestPlanTestCase implements Serializable {
private Long updateTime; private Long updateTime;
private String reportId;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@ -643,6 +643,76 @@ public class TestPlanTestCaseExample {
addCriterion("update_time not between", value1, value2, "updateTime"); addCriterion("update_time not between", value1, value2, "updateTime");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andReportIdIsNull() {
addCriterion("report_id is null");
return (Criteria) this;
}
public Criteria andReportIdIsNotNull() {
addCriterion("report_id is not null");
return (Criteria) this;
}
public Criteria andReportIdEqualTo(String value) {
addCriterion("report_id =", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdNotEqualTo(String value) {
addCriterion("report_id <>", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdGreaterThan(String value) {
addCriterion("report_id >", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdGreaterThanOrEqualTo(String value) {
addCriterion("report_id >=", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdLessThan(String value) {
addCriterion("report_id <", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdLessThanOrEqualTo(String value) {
addCriterion("report_id <=", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdLike(String value) {
addCriterion("report_id like", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdNotLike(String value) {
addCriterion("report_id not like", value, "reportId");
return (Criteria) this;
}
public Criteria andReportIdIn(List<String> values) {
addCriterion("report_id in", values, "reportId");
return (Criteria) this;
}
public Criteria andReportIdNotIn(List<String> values) {
addCriterion("report_id not in", values, "reportId");
return (Criteria) this;
}
public Criteria andReportIdBetween(String value1, String value2) {
addCriterion("report_id between", value1, value2, "reportId");
return (Criteria) this;
}
public Criteria andReportIdNotBetween(String value1, String value2) {
addCriterion("report_id not between", value1, value2, "reportId");
return (Criteria) this;
}
} }
public static class Criteria extends GeneratedCriteria { public static class Criteria extends GeneratedCriteria {

View File

@ -14,6 +14,7 @@
<result column="prerequisite" jdbcType="VARCHAR" property="prerequisite" /> <result column="prerequisite" jdbcType="VARCHAR" property="prerequisite" />
<result column="create_time" jdbcType="BIGINT" property="createTime" /> <result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" /> <result column="update_time" jdbcType="BIGINT" property="updateTime" />
<result column="test_id" jdbcType="VARCHAR" property="testId" />
</resultMap> </resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestCaseWithBLOBs"> <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestCaseWithBLOBs">
<result column="remark" jdbcType="LONGVARCHAR" property="remark" /> <result column="remark" jdbcType="LONGVARCHAR" property="remark" />
@ -79,7 +80,7 @@
</sql> </sql>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id, node_id, node_path, project_id, name, type, maintainer, priority, method, prerequisite, id, node_id, node_path, project_id, name, type, maintainer, priority, method, prerequisite,
create_time, update_time create_time, update_time, test_id
</sql> </sql>
<sql id="Blob_Column_List"> <sql id="Blob_Column_List">
remark, steps remark, steps
@ -137,12 +138,14 @@
project_id, name, type, project_id, name, type,
maintainer, priority, method, maintainer, priority, method,
prerequisite, create_time, update_time, prerequisite, create_time, update_time,
remark, steps) test_id, remark, steps
)
values (#{id,jdbcType=VARCHAR}, #{nodeId,jdbcType=VARCHAR}, #{nodePath,jdbcType=VARCHAR}, values (#{id,jdbcType=VARCHAR}, #{nodeId,jdbcType=VARCHAR}, #{nodePath,jdbcType=VARCHAR},
#{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR},
#{maintainer,jdbcType=VARCHAR}, #{priority,jdbcType=VARCHAR}, #{method,jdbcType=VARCHAR}, #{maintainer,jdbcType=VARCHAR}, #{priority,jdbcType=VARCHAR}, #{method,jdbcType=VARCHAR},
#{prerequisite,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{prerequisite,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
#{remark,jdbcType=LONGVARCHAR}, #{steps,jdbcType=LONGVARCHAR}) #{testId,jdbcType=VARCHAR}, #{remark,jdbcType=LONGVARCHAR}, #{steps,jdbcType=LONGVARCHAR}
)
</insert> </insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestCaseWithBLOBs"> <insert id="insertSelective" parameterType="io.metersphere.base.domain.TestCaseWithBLOBs">
insert into test_case insert into test_case
@ -183,6 +186,9 @@
<if test="updateTime != null"> <if test="updateTime != null">
update_time, update_time,
</if> </if>
<if test="testId != null">
test_id,
</if>
<if test="remark != null"> <if test="remark != null">
remark, remark,
</if> </if>
@ -227,6 +233,9 @@
<if test="updateTime != null"> <if test="updateTime != null">
#{updateTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
</if> </if>
<if test="testId != null">
#{testId,jdbcType=VARCHAR},
</if>
<if test="remark != null"> <if test="remark != null">
#{remark,jdbcType=LONGVARCHAR}, #{remark,jdbcType=LONGVARCHAR},
</if> </if>
@ -280,6 +289,9 @@
<if test="record.updateTime != null"> <if test="record.updateTime != null">
update_time = #{record.updateTime,jdbcType=BIGINT}, update_time = #{record.updateTime,jdbcType=BIGINT},
</if> </if>
<if test="record.testId != null">
test_id = #{record.testId,jdbcType=VARCHAR},
</if>
<if test="record.remark != null"> <if test="record.remark != null">
remark = #{record.remark,jdbcType=LONGVARCHAR}, remark = #{record.remark,jdbcType=LONGVARCHAR},
</if> </if>
@ -305,6 +317,7 @@
prerequisite = #{record.prerequisite,jdbcType=VARCHAR}, prerequisite = #{record.prerequisite,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT}, create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT}, update_time = #{record.updateTime,jdbcType=BIGINT},
test_id = #{record.testId,jdbcType=VARCHAR},
remark = #{record.remark,jdbcType=LONGVARCHAR}, remark = #{record.remark,jdbcType=LONGVARCHAR},
steps = #{record.steps,jdbcType=LONGVARCHAR} steps = #{record.steps,jdbcType=LONGVARCHAR}
<if test="_parameter != null"> <if test="_parameter != null">
@ -324,7 +337,8 @@
method = #{record.method,jdbcType=VARCHAR}, method = #{record.method,jdbcType=VARCHAR},
prerequisite = #{record.prerequisite,jdbcType=VARCHAR}, prerequisite = #{record.prerequisite,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT}, create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT} update_time = #{record.updateTime,jdbcType=BIGINT},
test_id = #{record.testId,jdbcType=VARCHAR}
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" /> <include refid="Update_By_Example_Where_Clause" />
</if> </if>
@ -365,6 +379,9 @@
<if test="updateTime != null"> <if test="updateTime != null">
update_time = #{updateTime,jdbcType=BIGINT}, update_time = #{updateTime,jdbcType=BIGINT},
</if> </if>
<if test="testId != null">
test_id = #{testId,jdbcType=VARCHAR},
</if>
<if test="remark != null"> <if test="remark != null">
remark = #{remark,jdbcType=LONGVARCHAR}, remark = #{remark,jdbcType=LONGVARCHAR},
</if> </if>
@ -387,6 +404,7 @@
prerequisite = #{prerequisite,jdbcType=VARCHAR}, prerequisite = #{prerequisite,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT}, create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT}, update_time = #{updateTime,jdbcType=BIGINT},
test_id = #{testId,jdbcType=VARCHAR},
remark = #{remark,jdbcType=LONGVARCHAR}, remark = #{remark,jdbcType=LONGVARCHAR},
steps = #{steps,jdbcType=LONGVARCHAR} steps = #{steps,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
@ -403,7 +421,8 @@
method = #{method,jdbcType=VARCHAR}, method = #{method,jdbcType=VARCHAR},
prerequisite = #{prerequisite,jdbcType=VARCHAR}, prerequisite = #{prerequisite,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT}, create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT} update_time = #{updateTime,jdbcType=BIGINT},
test_id = #{testId,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</update> </update>
</mapper> </mapper>

View File

@ -10,6 +10,7 @@
<result column="remark" jdbcType="VARCHAR" property="remark" /> <result column="remark" jdbcType="VARCHAR" property="remark" />
<result column="create_time" jdbcType="BIGINT" property="createTime" /> <result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" /> <result column="update_time" jdbcType="BIGINT" property="updateTime" />
<result column="report_id" jdbcType="VARCHAR" property="reportId" />
</resultMap> </resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestPlanTestCaseWithBLOBs"> <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestPlanTestCaseWithBLOBs">
<result column="results" jdbcType="LONGVARCHAR" property="results" /> <result column="results" jdbcType="LONGVARCHAR" property="results" />
@ -74,7 +75,7 @@
</where> </where>
</sql> </sql>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id, plan_id, case_id, executor, status, remark, create_time, update_time id, plan_id, case_id, executor, status, remark, create_time, update_time, report_id
</sql> </sql>
<sql id="Blob_Column_List"> <sql id="Blob_Column_List">
results, issues results, issues
@ -130,12 +131,12 @@
<insert id="insert" parameterType="io.metersphere.base.domain.TestPlanTestCaseWithBLOBs"> <insert id="insert" parameterType="io.metersphere.base.domain.TestPlanTestCaseWithBLOBs">
insert into test_plan_test_case (id, plan_id, case_id, insert into test_plan_test_case (id, plan_id, case_id,
executor, status, remark, executor, status, remark,
create_time, update_time, results, create_time, update_time, report_id,
issues) results, issues)
values (#{id,jdbcType=VARCHAR}, #{planId,jdbcType=VARCHAR}, #{caseId,jdbcType=VARCHAR}, values (#{id,jdbcType=VARCHAR}, #{planId,jdbcType=VARCHAR}, #{caseId,jdbcType=VARCHAR},
#{executor,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{remark,jdbcType=VARCHAR}, #{executor,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{remark,jdbcType=VARCHAR},
#{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{results,jdbcType=LONGVARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{reportId,jdbcType=VARCHAR},
#{issues,jdbcType=LONGVARCHAR}) #{results,jdbcType=LONGVARCHAR}, #{issues,jdbcType=LONGVARCHAR})
</insert> </insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlanTestCaseWithBLOBs"> <insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlanTestCaseWithBLOBs">
insert into test_plan_test_case insert into test_plan_test_case
@ -164,6 +165,9 @@
<if test="updateTime != null"> <if test="updateTime != null">
update_time, update_time,
</if> </if>
<if test="reportId != null">
report_id,
</if>
<if test="results != null"> <if test="results != null">
results, results,
</if> </if>
@ -196,6 +200,9 @@
<if test="updateTime != null"> <if test="updateTime != null">
#{updateTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
</if> </if>
<if test="reportId != null">
#{reportId,jdbcType=VARCHAR},
</if>
<if test="results != null"> <if test="results != null">
#{results,jdbcType=LONGVARCHAR}, #{results,jdbcType=LONGVARCHAR},
</if> </if>
@ -237,6 +244,9 @@
<if test="record.updateTime != null"> <if test="record.updateTime != null">
update_time = #{record.updateTime,jdbcType=BIGINT}, update_time = #{record.updateTime,jdbcType=BIGINT},
</if> </if>
<if test="record.reportId != null">
report_id = #{record.reportId,jdbcType=VARCHAR},
</if>
<if test="record.results != null"> <if test="record.results != null">
results = #{record.results,jdbcType=LONGVARCHAR}, results = #{record.results,jdbcType=LONGVARCHAR},
</if> </if>
@ -258,6 +268,7 @@
remark = #{record.remark,jdbcType=VARCHAR}, remark = #{record.remark,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT}, create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT}, update_time = #{record.updateTime,jdbcType=BIGINT},
report_id = #{record.reportId,jdbcType=VARCHAR},
results = #{record.results,jdbcType=LONGVARCHAR}, results = #{record.results,jdbcType=LONGVARCHAR},
issues = #{record.issues,jdbcType=LONGVARCHAR} issues = #{record.issues,jdbcType=LONGVARCHAR}
<if test="_parameter != null"> <if test="_parameter != null">
@ -273,7 +284,8 @@
status = #{record.status,jdbcType=VARCHAR}, status = #{record.status,jdbcType=VARCHAR},
remark = #{record.remark,jdbcType=VARCHAR}, remark = #{record.remark,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT}, create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT} update_time = #{record.updateTime,jdbcType=BIGINT},
report_id = #{record.reportId,jdbcType=VARCHAR}
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" /> <include refid="Update_By_Example_Where_Clause" />
</if> </if>
@ -302,6 +314,9 @@
<if test="updateTime != null"> <if test="updateTime != null">
update_time = #{updateTime,jdbcType=BIGINT}, update_time = #{updateTime,jdbcType=BIGINT},
</if> </if>
<if test="reportId != null">
report_id = #{reportId,jdbcType=VARCHAR},
</if>
<if test="results != null"> <if test="results != null">
results = #{results,jdbcType=LONGVARCHAR}, results = #{results,jdbcType=LONGVARCHAR},
</if> </if>
@ -320,6 +335,7 @@
remark = #{remark,jdbcType=VARCHAR}, remark = #{remark,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT}, create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT}, update_time = #{updateTime,jdbcType=BIGINT},
report_id = #{reportId,jdbcType=VARCHAR},
results = #{results,jdbcType=LONGVARCHAR}, results = #{results,jdbcType=LONGVARCHAR},
issues = #{issues,jdbcType=LONGVARCHAR} issues = #{issues,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
@ -332,7 +348,8 @@
status = #{status,jdbcType=VARCHAR}, status = #{status,jdbcType=VARCHAR},
remark = #{remark,jdbcType=VARCHAR}, remark = #{remark,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT}, create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT} update_time = #{updateTime,jdbcType=BIGINT},
report_id = #{reportId,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</update> </update>
</mapper> </mapper>

View File

@ -2,6 +2,7 @@ package io.metersphere.base.mapper.ext;
import io.metersphere.api.dto.APITestResult; import io.metersphere.api.dto.APITestResult;
import io.metersphere.api.dto.QueryAPITestRequest; import io.metersphere.api.dto.QueryAPITestRequest;
import io.metersphere.base.domain.ApiTest;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@ -10,4 +11,6 @@ public interface ExtApiTestMapper {
List<APITestResult> list(@Param("request") QueryAPITestRequest request); List<APITestResult> list(@Param("request") QueryAPITestRequest request);
Long countByProjectId(String projectId); Long countByProjectId(String projectId);
List<ApiTest> getApiTestByProjectId(String projectId);
} }

View File

@ -30,8 +30,13 @@
order by api_test.update_time desc order by api_test.update_time desc
</select> </select>
<select id="countByProjectId" resultType="java.lang.Long"> <select id="countByProjectId" resultType="java.lang.Long">
select count(id) from api_test select count(id) from api_test
where project_id = #{projectId}; where project_id = #{projectId}
</select>
<select id="getApiTestByProjectId" resultType="io.metersphere.base.domain.ApiTest">
select id,name
from api_test
where project_id = #{projectId}
</select> </select>
</mapper> </mapper>

View File

@ -1,5 +1,6 @@
package io.metersphere.base.mapper.ext; package io.metersphere.base.mapper.ext;
import io.metersphere.base.domain.LoadTest;
import io.metersphere.track.request.testplan.QueryTestPlanRequest; import io.metersphere.track.request.testplan.QueryTestPlanRequest;
import io.metersphere.dto.LoadTestDTO; import io.metersphere.dto.LoadTestDTO;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -10,4 +11,6 @@ public interface ExtLoadTestMapper {
List<LoadTestDTO> list(@Param("request") QueryTestPlanRequest params); List<LoadTestDTO> list(@Param("request") QueryTestPlanRequest params);
Long countByProjectId(String projectId); Long countByProjectId(String projectId);
List<LoadTest> getLoadTestByProjectId(String projectId);
} }

View File

@ -31,5 +31,10 @@
select count(id) from load_test select count(id) from load_test
where project_id = #{projectId}; where project_id = #{projectId};
</select> </select>
<select id="getLoadTestByProjectId" resultType="io.metersphere.base.domain.LoadTest">
select id,name
from load_test
where project_id = #{projectId};
</select>
</mapper> </mapper>

View File

@ -3,6 +3,7 @@ package io.metersphere.performance.controller;
import com.github.pagehelper.Page; import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import io.metersphere.base.domain.FileMetadata; import io.metersphere.base.domain.FileMetadata;
import io.metersphere.base.domain.LoadTest;
import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.Pager;
@ -48,6 +49,11 @@ public class PerformanceTestController {
return PageUtils.setPageInfo(page, performanceTestService.list(request)); return PageUtils.setPageInfo(page, performanceTestService.list(request));
} }
@GetMapping("/list/{projectId}")
public List<LoadTest> list(@PathVariable String projectId) {
return performanceTestService.getLoadTestByProjectId(projectId);
}
@PostMapping(value = "/save", consumes = {"multipart/form-data"}) @PostMapping(value = "/save", consumes = {"multipart/form-data"})
public String save( public String save(
@RequestPart("request") SaveTestPlanRequest request, @RequestPart("request") SaveTestPlanRequest request,

View File

@ -280,4 +280,7 @@ public class PerformanceTestService {
return extLoadTestReportMapper.selectDashboardTests(workspaceId, startTimestamp); return extLoadTestReportMapper.selectDashboardTests(workspaceId, startTimestamp);
} }
public List<LoadTest> getLoadTestByProjectId(String projectId) {
return extLoadTestMapper.getLoadTestByProjectId(projectId);
}
} }

View File

@ -196,6 +196,15 @@ public class UserService {
if (!roles.isEmpty()) { if (!roles.isEmpty()) {
insertUserRole(roles, user.getId()); insertUserRole(roles, user.getId());
} }
String email = user.getEmail();
User u = userMapper.selectByPrimaryKey(userId);
if (!StringUtils.equals(email, u.getEmail())) {
UserExample userExample = new UserExample();
userExample.createCriteria().andEmailEqualTo(email);
if (userMapper.countByExample(userExample) > 0) {
MSException.throwException(Translator.get("user_email_already_exists"));
}
}
user.setUpdateTime(System.currentTimeMillis()); user.setUpdateTime(System.currentTimeMillis());
userMapper.updateByPrimaryKeySelective(user); userMapper.updateByPrimaryKeySelective(user);
} }

View File

@ -15,4 +15,5 @@ public class TestPlanCaseDTO extends TestCaseWithBLOBs {
private String planName; private String planName;
private String caseId; private String caseId;
private String issues; private String issues;
private String reportId;
} }

View File

@ -286,6 +286,7 @@ CREATE TABLE IF NOT EXISTS `test_case_node` (
CREATE TABLE IF NOT EXISTS `test_case` ( CREATE TABLE IF NOT EXISTS `test_case` (
`id` varchar(50) NOT NULL COMMENT 'Test case ID', `id` varchar(50) NOT NULL COMMENT 'Test case ID',
`node_id` varchar(50) NOT NULL COMMENT 'Node ID this case belongs to', `node_id` varchar(50) NOT NULL COMMENT 'Node ID this case belongs to',
`test_id` varchar(50) DEFAULT NULL COMMENT 'Test ID relation to',
`node_path` varchar(50) NOT NULL COMMENT 'Node path this case belongs to', `node_path` varchar(50) NOT NULL COMMENT 'Node path this case belongs to',
`project_id` varchar(50) NOT NULL COMMENT 'Project ID this test belongs to', `project_id` varchar(50) NOT NULL COMMENT 'Project ID this test belongs to',
`name` varchar(64) NOT NULL COMMENT 'Case name', `name` varchar(64) NOT NULL COMMENT 'Case name',
@ -309,6 +310,7 @@ CREATE TABLE IF NOT EXISTS `test_plan_test_case` (
`id` varchar(50) NOT NULL COMMENT 'ID', `id` varchar(50) NOT NULL COMMENT 'ID',
`plan_id` varchar(50) NOT NULL COMMENT 'Plan ID relation to', `plan_id` varchar(50) NOT NULL COMMENT 'Plan ID relation to',
`case_id` varchar(50) NOT NULL COMMENT 'Case ID relation to', `case_id` varchar(50) NOT NULL COMMENT 'Case ID relation to',
`report_id` varchar(50) DEFAULT NULL COMMENT 'Test report ID relation to',
`executor` varchar(64) NOT NULL COMMENT 'Test case executor', `executor` varchar(64) NOT NULL COMMENT 'Test case executor',
`status` varchar(15) NULL COMMENT 'Test case status', `status` varchar(15) NULL COMMENT 'Test case status',
`results` longtext COMMENT 'Test case result', `results` longtext COMMENT 'Test case result',

View File

@ -59,8 +59,8 @@
<!--要生成的数据库表 --> <!--要生成的数据库表 -->
<table tableName="load_test_report"/> <table tableName="test_plan_test_case"/>
<table tableName="load_test"/> <table tableName="test_case"/>
</context> </context>
</generatorConfiguration> </generatorConfiguration>

View File

@ -543,6 +543,7 @@ class JMXGenerator {
} }
replace(str) { replace(str) {
if (!str) return str;
return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&apos;").replace(/"/g, "&quot;"); return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/'/g, "&apos;").replace(/"/g, "&quot;");
} }

View File

@ -37,16 +37,17 @@
<el-tabs v-model="active" type="border-card" :stretch="true"> <el-tabs v-model="active" type="border-card" :stretch="true">
<el-tab-pane :label="$t('report.test_overview')"> <el-tab-pane :label="$t('report.test_overview')">
<ms-report-test-overview :id="reportId" :status="status"/> <!-- <ms-report-test-overview :id="reportId" :status="status"/>-->
<ms-report-test-overview :report="report"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('report.test_request_statistics')"> <el-tab-pane :label="$t('report.test_request_statistics')">
<ms-report-request-statistics :id="reportId" :status="status"/> <ms-report-request-statistics :report="report"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('report.test_error_log')"> <el-tab-pane :label="$t('report.test_error_log')">
<ms-report-error-log :id="reportId" :status="status"/> <ms-report-error-log :report="report"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('report.test_log_details')"> <el-tab-pane :label="$t('report.test_log_details')">
<ms-report-log-details :id="reportId" :status="status"/> <ms-report-log-details :report="report"/>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
@ -89,6 +90,7 @@
minutes: '0', minutes: '0',
seconds: '0', seconds: '0',
title: 'Logging', title: 'Logging',
report: {}
} }
}, },
methods: { methods: {
@ -108,8 +110,9 @@
}, },
initReportTimeInfo() { initReportTimeInfo() {
if (this.reportId) { if (this.reportId) {
this.result = this.$get("/performance/report/content/report_time/" + this.reportId, res => { this.result = this.$get("/performance/report/content/report_time/" + this.reportId)
let data = res.data; .then(res => {
let data = res.data.data;
if (data) { if (data) {
this.startTime = data.startTime; this.startTime = data.startTime;
this.endTime = data.endTime; this.endTime = data.endTime;
@ -117,55 +120,90 @@
this.minutes = Math.floor(duration / 60); this.minutes = Math.floor(duration / 60);
this.seconds = duration % 60; this.seconds = duration % 60;
} }
}).catch(() => {
this.clearData();
}) })
} }
}, },
}, checkReportStatus(status) {
mounted() { switch (status) {
this.reportId = this.$route.path.split('/')[4];
this.result = this.$get("/performance/report/" + this.reportId, res => {
let data = res.data;
this.status = data.status;
switch (data.status) {
case 'Error': case 'Error':
this.$warning(this.$t('report.generation_error')); this.$warning(this.$t('report.generation_error'));
break; break;
case 'Starting': case 'Starting':
this.$warning("测试处于开始状态,请稍后查看报告!");
break;
case 'Reporting': case 'Reporting':
this.$info(this.$t('report.being_generated')); this.$info(this.$t('report.being_generated'));
break; break;
case 'Running': case 'Running':
this.$warning("测试处于运行状态,请稍后查看报告!");
break; break;
case 'Completed':
default: default:
break; break;
} }
},
clearData() {
this.startTime = '0';
this.endTime = '0';
this.minutes = '0';
this.seconds = '0';
}
},
created() {
this.reportId = this.$route.path.split('/')[4];
this.result = this.$get("/performance/report/" + this.reportId, res => {
let data = res.data;
this.status = data.status;
this.$set(this.report, "id", this.reportId);
this.$set(this.report, "status", data.status);
this.checkReportStatus(data.status);
if (this.status === "Completed") {
this.initReportTimeInfo();
}
}) })
this.initBreadcrumb(); this.initBreadcrumb();
this.initReportTimeInfo();
}, },
watch: { watch: {
'$route'(to) { '$route'(to) {
let reportId = to.path.split('/')[4]; if (to.name === "perReportView") {
if (reportId) { let reportId = to.path.split('/')[4];
this.$get("/performance/report/test/pro/info/" + reportId, response => { this.reportId = reportId;
let data = response.data; if (reportId) {
if (data) { this.$get("/performance/report/test/pro/info/" + reportId, response => {
this.reportName = data.name; let data = response.data;
this.testName = data.testName; if (data) {
this.projectName = data.projectName; this.status = data.status;
} this.reportName = data.name;
}); this.testName = data.testName;
this.result = this.$get("/performance/report/content/report_time/" + this.reportId, res => { this.projectName = data.projectName;
let data = res.data;
if (data) { this.$set(this.report, "id", reportId);
this.startTime = data.startTime; this.$set(this.report, "status", data.status);
this.endTime = data.endTime;
let duration = data.duration; this.checkReportStatus(data.status);
this.minutes = Math.floor(duration / 60); if (this.status === "Completed") {
this.seconds = duration % 60; this.result = this.$get("/performance/report/content/report_time/" + this.reportId).then(res => {
} let data = res.data.data;
}) if (data) {
window.location.reload(); this.startTime = data.startTime;
this.endTime = data.endTime;
let duration = data.duration;
this.minutes = Math.floor(duration / 60);
this.seconds = duration % 60;
}
}).catch(() => {
this.clearData();
})
} else {
this.clearData();
}
}
});
}
} }
} }
} }

View File

@ -131,27 +131,40 @@
data() { data() {
return { return {
tableData: [], tableData: [],
errorTop5: [] errorTop5: [],
id: ''
} }
}, },
methods: { methods: {
initTableData() { initTableData() {
this.$get("/performance/report/content/errors/" + this.id, res => { this.$get("/performance/report/content/errors/" + this.id).then(res => {
this.tableData = res.data; this.tableData = res.data.data;
}).catch(() => {
this.tableData = [];
}) })
this.$get("/performance/report/content/errors_top5/" + this.id, res => { this.$get("/performance/report/content/errors_top5/" + this.id).then(res => {
this.errorTop5 = res.data; this.errorTop5 = res.data.data;
}).catch(() => {
this.errorTop5 = [];
}) })
} }
}, },
watch: { watch: {
status() { report: {
if ("Completed" === this.status) { handler(val){
this.initTableData() let status = val.status;
} this.id = val.id;
if (status === "Completed") {
this.initTableData();
} else {
this.tableData = [];
this.errorTop5 = [];
}
},
deep:true
} }
}, },
props: ['id','status'] props: ['report']
} }
</script> </script>

View File

@ -12,17 +12,19 @@
<script> <script>
export default { export default {
name: "LogDetails", name: "LogDetails",
props: ['id', 'status'],
data() { data() {
return { return {
logContent: null, logContent: null,
result: {}, result: {},
id: ''
} }
}, },
methods: { methods: {
initTableData() { initTableData() {
this.result = this.$get("/performance/report/log/" + this.id, res => { this.result = this.$get("/performance/report/log/" + this.id).then(res => {
this.logContent = res.data; this.logContent = res.data.data;
}).catch(() => {
this.logContent = null;
}) })
}, },
downloadLogFile(item) { downloadLogFile(item) {
@ -50,12 +52,20 @@
} }
}, },
watch: { watch: {
status() { report: {
if ("Completed" === this.status) { handler(val){
this.initTableData() let status = val.status;
} this.id = val.id;
if (status === "Completed") {
this.initTableData();
} else {
this.logContent = null;
}
},
deep:true
} }
}, },
props: ['report']
} }
</script> </script>

View File

@ -95,13 +95,16 @@
name: "RequestStatistics", name: "RequestStatistics",
data() { data() {
return { return {
tableData: [] tableData: [],
id: ''
} }
}, },
methods: { methods: {
initTableData() { initTableData() {
this.$get("/performance/report/content/" + this.id, res => { this.$get("/performance/report/content/" + this.id).then(res => {
this.tableData = res.data; this.tableData = res.data.data;
}).catch(() => {
this.tableData = [];
}) })
}, },
getSummaries(param) { getSummaries(param) {
@ -154,13 +157,20 @@
} }
}, },
watch: { watch: {
status() { report: {
if ("Completed" === this.status) { handler(val){
this.initTableData() let status = val.status;
} this.id = val.id;
if (status === "Completed") {
this.initTableData();
} else {
this.tableData = [];
}
},
deep:true
} }
}, },
props: ['id', 'status'] props: ['report']
} }
</script> </script>

View File

@ -80,22 +80,31 @@
responseTime90: "0", responseTime90: "0",
avgBandwidth: "0", avgBandwidth: "0",
loadOption: {}, loadOption: {},
resOption: {} resOption: {},
id: ''
} }
}, },
methods: { methods: {
initTableData() { initTableData() {
this.$get("/performance/report/content/testoverview/" + this.id, res => { this.$get("/performance/report/content/testoverview/" + this.id).then(res => {
let data = res.data; let data = res.data.data;
this.maxUsers = data.maxUsers; this.maxUsers = data.maxUsers;
this.avgThroughput = data.avgThroughput; this.avgThroughput = data.avgThroughput;
this.errors = data.errors; this.errors = data.errors;
this.avgResponseTime = data.avgResponseTime; this.avgResponseTime = data.avgResponseTime;
this.responseTime90 = data.responseTime90; this.responseTime90 = data.responseTime90;
this.avgBandwidth = data.avgBandwidth; this.avgBandwidth = data.avgBandwidth;
}).catch(() => {
this.maxUsers = '0';
this.avgThroughput = '0';
this.errors = '0';
this.avgResponseTime = '0';
this.responseTime90 = '0';
this.avgBandwidth = '0';
this.$warning("报告生成错误!")
}) })
this.$get("/performance/report/content/load_chart/" + this.id, res => { this.$get("/performance/report/content/load_chart/" + this.id).then(res => {
let data = res.data; let data = res.data.data;
let yAxisList = data.filter(m => m.yAxis2 === -1).map(m => m.yAxis); let yAxisList = data.filter(m => m.yAxis2 === -1).map(m => m.yAxis);
let yAxis2List = data.filter(m => m.yAxis === -1).map(m => m.yAxis2); let yAxis2List = data.filter(m => m.yAxis === -1).map(m => m.yAxis2);
let yAxisListMax = this._getChartMax(yAxisList); let yAxisListMax = this._getChartMax(yAxisList);
@ -166,9 +175,11 @@
setting["series"].splice(0, 0, {name: item, yAxisIndex: '1'}) setting["series"].splice(0, 0, {name: item, yAxisIndex: '1'})
}) })
this.loadOption = this.generateOption(loadOption, data, setting); this.loadOption = this.generateOption(loadOption, data, setting);
}).catch(() => {
this.loadOption = {};
}) })
this.$get("/performance/report/content/res_chart/" + this.id, res => { this.$get("/performance/report/content/res_chart/" + this.id).then(res => {
let data = res.data; let data = res.data.data;
let yAxisList = data.filter(m => m.yAxis2 === -1).map(m => m.yAxis); let yAxisList = data.filter(m => m.yAxis2 === -1).map(m => m.yAxis);
let yAxis2List = data.filter(m => m.yAxis === -1).map(m => m.yAxis2); let yAxis2List = data.filter(m => m.yAxis === -1).map(m => m.yAxis2);
let yAxisListMax = this._getChartMax(yAxisList); let yAxisListMax = this._getChartMax(yAxisList);
@ -246,6 +257,8 @@
}) })
this.resOption = this.generateOption(resOption, data, setting); this.resOption = this.generateOption(resOption, data, setting);
}).catch(() => {
this.resOption = {};
}) })
}, },
generateOption(option, data, setting) { generateOption(option, data, setting) {
@ -310,13 +323,27 @@
} }
}, },
watch: { watch: {
status() { report: {
if ("Completed" === this.status) { handler(val){
this.initTableData() let status = val.status;
} this.id = val.id;
if (status === "Completed") {
this.initTableData();
} else {
this.maxUsers = '0';
this.avgThroughput = '0';
this.errors = '0';
this.avgResponseTime = '0';
this.responseTime90 = '0';
this.avgBandwidth = '0';
this.loadOption = {};
this.resOption = {};
}
},
deep:true
} }
}, },
props: ['id', 'status'] props: ['report']
} }
</script> </script>

View File

@ -83,7 +83,7 @@
<el-option <el-option
v-for="item in form.allroles" v-for="item in form.allroles"
:key="item.id" :key="item.id"
:label="item.name" :label="$t('role.' + item.id)"
:value="item.id"> :value="item.id">
</el-option> </el-option>
</el-select> </el-select>

View File

@ -131,7 +131,7 @@
<el-option <el-option
v-for="item in memberForm.allroles" v-for="item in memberForm.allroles"
:key="item.id" :key="item.id"
:label="item.name" :label="$t('role.' + item.id)"
:value="item.id"> :value="item.id">
</el-option> </el-option>
</el-select> </el-select>

View File

@ -134,7 +134,7 @@
<el-option <el-option
v-for="item in memberForm.roles" v-for="item in memberForm.roles"
:key="item.id" :key="item.id"
:label="item.name" :label="$t('role.' + item.id)"
:value="item.id"> :value="item.id">
</el-option> </el-option>
</el-select> </el-select>
@ -170,7 +170,7 @@
<el-option <el-option
v-for="item in memberForm.allroles" v-for="item in memberForm.allroles"
:key="item.id" :key="item.id"
:label="item.name" :label="$t('role.' + item.id)"
:value="item.id"> :value="item.id">
</el-option> </el-option>
</el-select> </el-select>

View File

@ -84,7 +84,7 @@
<el-option <el-option
v-for="item in form.allroles" v-for="item in form.allroles"
:key="item.id" :key="item.id"
:label="item.name" :label="$t('role.' + item.id)"
:value="item.id"> :value="item.id">
</el-option> </el-option>
</el-select> </el-select>

View File

@ -64,7 +64,7 @@
<el-row> <el-row>
<el-col :span="10" :offset="1"> <el-col :span="10" :offset="1">
<el-form-item :label="$t('test_track.case.type')" :label-width="formLabelWidth" prop="type"> <el-form-item :label="$t('test_track.case.type')" :label-width="formLabelWidth" prop="type">
<el-select :disabled="readOnly" v-model="form.type" :placeholder="$t('test_track.case.input_type')"> <el-select @change="typeChange" :disabled="readOnly" v-model="form.type" :placeholder="$t('test_track.case.input_type')">
<el-option :label="$t('commons.functional')" value="functional"></el-option> <el-option :label="$t('commons.functional')" value="functional"></el-option>
<el-option :label="$t('commons.performance')" value="performance"></el-option> <el-option :label="$t('commons.performance')" value="performance"></el-option>
<el-option :label="$t('commons.api')" value="api"></el-option> <el-option :label="$t('commons.api')" value="api"></el-option>
@ -74,8 +74,27 @@
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="$t('test_track.case.method')" :label-width="formLabelWidth" prop="method"> <el-form-item :label="$t('test_track.case.method')" :label-width="formLabelWidth" prop="method">
<el-select :disabled="readOnly" v-model="form.method" :placeholder="$t('test_track.case.input_method')"> <el-select :disabled="readOnly" v-model="form.method" :placeholder="$t('test_track.case.input_method')">
<el-option :label="$t('test_track.case.manual')" value="manual"></el-option> <el-option
<el-option :label="$t('test_track.case.auto')" value="auto"></el-option> v-for="item in methodOptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="form.method && form.method == 'auto'">
<el-col :span="10" :offset="1">
<el-form-item :label="'关联测试'" :label-width="formLabelWidth" prop="testId">
<el-select filterable :disabled="readOnly" v-model="form.testId" :placeholder="$t('test_track.case.input_type')">
<el-option
v-for="item in testOptions"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -96,11 +115,11 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row style="margin-bottom: 10px"> <el-row v-if="form.method && form.method != 'auto'" style="margin-bottom: 10px">
<el-col :offset="2">{{$t('test_track.case.steps')}}:</el-col> <el-col :offset="2">{{$t('test_track.case.steps')}}:</el-col>
</el-row> </el-row>
<el-row type="flex" justify="center"> <el-row v-if="form.method && form.method != 'auto'" type="flex" justify="center">
<el-col :span="20"> <el-col :span="20">
<el-table <el-table
:data="form.steps" :data="form.steps"
@ -213,6 +232,7 @@
type: '', type: '',
method: '', method: '',
prerequisite: '', prerequisite: '',
testId: '',
steps: [{ steps: [{
num: 1 , num: 1 ,
desc: '', desc: '',
@ -222,6 +242,8 @@
}, },
moduleOptions: [], moduleOptions: [],
maintainerOptions: [], maintainerOptions: [],
methodOptions: [],
testOptions: [],
workspaceId: '', workspaceId: '',
rules:{ rules:{
name :[ name :[
@ -232,6 +254,7 @@
maintainer :[{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}], maintainer :[{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
priority :[{required: true, message: this.$t('test_track.case.input_priority'), trigger: 'change'}], priority :[{required: true, message: this.$t('test_track.case.input_priority'), trigger: 'change'}],
type :[{required: true, message: this.$t('test_track.case.input_type'), trigger: 'change'}], type :[{required: true, message: this.$t('test_track.case.input_type'), trigger: 'change'}],
testId :[{required: true, message: '请选择测试', trigger: 'change'}],
method :[{required: true, message: this.$t('test_track.case.input_method'), trigger: 'change'}], method :[{required: true, message: this.$t('test_track.case.input_method'), trigger: 'change'}],
prerequisite :[{ max: 300, message: this.$t('test_track.length_less_than') + '300', trigger: 'blur'}], prerequisite :[{ max: 300, message: this.$t('test_track.length_less_than') + '300', trigger: 'blur'}],
remark :[{ max: 300, message: this.$t('test_track.length_less_than') + '300', trigger: 'blur'}] remark :[{ max: 300, message: this.$t('test_track.length_less_than') + '300', trigger: 'blur'}]
@ -258,11 +281,13 @@
}, },
mounted() { mounted() {
this.getSelectOptions(); this.getSelectOptions();
},
watch: {
}, },
methods: { methods: {
open(testCase) { open(testCase) {
this.resetForm(); this.resetForm();
this.getSelectOptions();
this.operationType = 'add'; this.operationType = 'add';
if(testCase){ if(testCase){
// //
@ -290,6 +315,8 @@
this.form.method = 'manual'; this.form.method = 'manual';
this.form.maintainer = user.id; this.form.maintainer = user.id;
} }
this.getSelectOptions();
this.dialogFormVisible = true; this.dialogFormVisible = true;
}, },
handleAddStep(index, data) { handleAddStep(index, data) {
@ -315,49 +342,62 @@
saveCase(){ saveCase(){
this.$refs['caseFrom'].validate((valid) => { this.$refs['caseFrom'].validate((valid) => {
if (valid) { if (valid) {
let param = {}; let param = this.buildParam();
Object.assign(param, this.form); if (this.validate(param)) {
this.result = this.$post('/test/case/' + this.operationType, param, () => {
for (let i = 0; i < param.steps.length; i++){ this.$success(this.$t('commons.save_success'));
if ((param.steps[i].desc && param.steps[i].desc.length > 300) || if (this.operationType == 'add' && this.isCreateContinue) {
(param.steps[i].result && param.steps[i].result.length > 300)) { this.form.name = '';
this.$warning(this.$t('test_track.case.step_desc') + "," return;
+ this.$t('test_track.case.expected_results') + this.$t('test_track.length_less_than') + '300'); }
return; this.dialogFormVisible = false;
} this.$emit("refresh");
});
} }
param.steps = JSON.stringify(this.form.steps);
param.nodeId = this.form.module;
this.moduleOptions.forEach(item => {
if(this.form.module === item.id){
param.nodePath = item.path;
}
});
if (this.currentProject) {
param.projectId = this.currentProject.id;
}
param.name = param.name.trim();
if (param.name == '') {
this.$warning(this.$t('test_track.case.input_name'));
return;
}
this.result = this.$post('/test/case/' + this.operationType, param, () => {
this.$success(this.$t('commons.save_success'));
if (this.operationType == 'add' && this.isCreateContinue) {
this.form.name = '';
return;
}
this.dialogFormVisible = false;
this.$emit("refresh");
});
} else { } else {
return false; return false;
} }
}); });
}, },
buildParam() {
let param = {};
Object.assign(param, this.form);
param.steps = JSON.stringify(this.form.steps);
param.nodeId = this.form.module;
this.moduleOptions.forEach(item => {
if(this.form.module === item.id){
param.nodePath = item.path;
}
});
if (this.currentProject) {
param.projectId = this.currentProject.id;
}
param.name = param.name.trim();
if (param.method != 'auto') {
param.testId = null;
}
return param;
},
validate(param) {
for (let i = 0; i < param.steps.length; i++){
if ((param.steps[i].desc && param.steps[i].desc.length > 300) ||
(param.steps[i].result && param.steps[i].result.length > 300)) {
this.$warning(this.$t('test_track.case.step_desc') + ","
+ this.$t('test_track.case.expected_results') + this.$t('test_track.length_less_than') + '300');
return false;
}
}
if (param.name == '') {
this.$warning(this.$t('test_track.case.input_name'));
return false;
}
return true;
},
typeChange() {
this.form.testId = '';
this.getMethodOptions();
this.getTestOptions()
},
getModuleOptions() { getModuleOptions() {
let moduleOptions = []; let moduleOptions = [];
this.treeNodes.forEach(node => { this.treeNodes.forEach(node => {
@ -371,9 +411,30 @@
this.maintainerOptions = response.data; this.maintainerOptions = response.data;
}); });
}, },
getTestOptions() {
this.testOptions = [];
if (this.currentProject && this.form.type != '' && this.form.type != 'functional') {
this.$get('/' + this.form.type + '/list/' + this.currentProject.id, response => {
this.testOptions = response.data;
});
}
},
getMethodOptions() {
if (!this.form.type || this.form.type != 'functional') {
this.methodOptions = [
{value: 'auto', label: this.$t('test_track.case.auto')},
{value: 'manual', label: this.$t('test_track.case.manual')}
];
} else {
this.form.method = 'manual';
this.methodOptions = [{value: 'manual', label: this.$t('test_track.case.manual')}]
}
},
getSelectOptions() { getSelectOptions() {
this.getModuleOptions(); this.getModuleOptions();
this.getMaintainerOptions(); this.getMaintainerOptions();
this.getTestOptions();
this.getMethodOptions();
}, },
buildNodePath(node, option, moduleOptions) { buildNodePath(node, option, moduleOptions) {
// //
@ -399,6 +460,7 @@
this.form.priority = ''; this.form.priority = '';
this.form.prerequisite = ''; this.form.prerequisite = '';
this.form.remark = ''; this.form.remark = '';
this.form.testId = '';
this.form.steps = [{ this.form.steps = [{
num: 1 , num: 1 ,
desc: '', desc: '',

View File

@ -85,7 +85,22 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row v-if="testCase.method == 'auto' && testCase.testId">
<el-col class="test-detail" :span="20" :offset="1">
<el-tabs type="border-card">
<el-tab-pane :label="$t('test_track.plan_view.test_detail')">
<api-test-detail v-if="testCase.type == 'api'" @runTest="apiTestRun" :id="testCase.testId" v-show="testCase.type == 'api'" ref="apiTestDetail"/>
<edit-performance-test-plan v-if="testCase.type == 'performance'"/>
</el-tab-pane>
<el-tab-pane :label="$t('test_track.plan_view.test_result')">
<api-test-result :report-id="testCase.reportId" v-if=" testCase.type == 'api'" ref="apiTestResult"/>
<performance-report-view v-if="testCase.type == 'performance'"/>
</el-tab-pane>
</el-tabs>
</el-col>
</el-row>
<el-row v-if="testCase.method && testCase.method != 'auto'">
<el-col :span="20" :offset="1"> <el-col :span="20" :offset="1">
<div> <div>
<span class="cast_label">{{$t('test_track.case.steps')}}</span> <span class="cast_label">{{$t('test_track.case.steps')}}</span>
@ -184,10 +199,20 @@
<script> <script>
import TestPlanTestCaseStatusButton from '../../common/TestPlanTestCaseStatusButton'; import TestPlanTestCaseStatusButton from '../../common/TestPlanTestCaseStatusButton';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'; import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import MsApiTestConfig from "../../../../api/test/ApiTestConfig";
import MsApiReportView from "../../../../api/report/ApiReportView";
import EditPerformanceTestPlan from "../../../../performance/test/EditPerformanceTestPlan";
import PerformanceReportView from "../../../../performance/report/PerformanceReportView";
import ApiTestDetail from "./test/ApiTestDetail";
import ApiTestResult from "./test/ApiTestResult";
export default { export default {
name: "TestPlanTestCaseEdit", name: "TestPlanTestCaseEdit",
components: {TestPlanTestCaseStatusButton}, components: {
ApiTestResult,
ApiTestDetail,
PerformanceReportView,
EditPerformanceTestPlan, MsApiReportView, MsApiTestConfig, TestPlanTestCaseStatusButton},
data() { data() {
return { return {
result: {}, result: {},
@ -196,6 +221,7 @@
index: 0, index: 0,
testCases: [], testCases: [],
editor: ClassicEditor, editor: ClassicEditor,
test: {}
}; };
}, },
props: { props: {
@ -276,6 +302,27 @@
this.showDialog = true; this.showDialog = true;
this.initData(testCase); this.initData(testCase);
}, },
initTest() {
this.$nextTick(() => {
if (this.testCase.method == 'auto') {
if (this.$refs.apiTestDetail && this.testCase.type == 'api') {
this.$refs.apiTestDetail.init();
}
// else if(testCase.type == 'api') {
// this.$refs.apiTestDetail.init();
// }
}
});
},
apiTestRun(reportId) {
this.testCase.reportId = reportId;
this.saveReport(reportId);
},
saveReport(reportId) {
this.$post('/test/plan/case/edit', {id: this.testCase.id, reportId: reportId});
},
updateTestCases(testCase) { updateTestCases(testCase) {
this.testCases.forEach(item => { this.testCases.forEach(item => {
if (testCase.id === item.id) { if (testCase.id === item.id) {
@ -290,10 +337,19 @@
if (this.testCases[i].id === testCase.id) { if (this.testCases[i].id === testCase.id) {
this.index = i; this.index = i;
this.getTestCase(i); this.getTestCase(i);
this.getRelatedTest();
this.initTest();
} }
} }
}); });
}, },
getRelatedTest() {
if (this.testCase.method == 'auto' && this.testCase.testId) {
this.$get('/' + this.testCase.type + '/get/' + this.testCase.testId, response => {
this.test = response.data;
});
}
},
issuesChange() { issuesChange() {
if (this.testCase.issues.hasIssues) { if (this.testCase.issues.hasIssues) {
let desc = this.addPLabel('[' + this.$t('test_track.plan_view.operate_step') + ']'); let desc = this.addPLabel('[' + this.$t('test_track.plan_view.operate_step') + ']');
@ -343,7 +399,7 @@
text-align: right; text-align: right;
} }
.el-col { .el-col:not(.test-detail){
line-height: 50px; line-height: 50px;
} }

View File

@ -0,0 +1,101 @@
<template>
<el-card>
<el-container class="test-container">
<el-header>
<el-row type="flex" align="middle">
<el-input :disabled="true" class="test-name" v-model="test.name" maxlength="60" :placeholder="$t('api_test.input_name')"
show-word-limit>
<el-select :disabled="true" class="test-project" v-model="project.name" slot="prepend"
:placeholder="$t('api_test.select_project')">
</el-select>
</el-input>
<el-button type="primary" plain @click="runTest">
{{$t('api_test.run')}}
</el-button>
</el-row>
</el-header>
<ms-api-scenario-config :scenarios="test.scenarioDefinition" ref="config"/>
</el-container>
</el-card>
</template>
<script>
import {Test} from "../../../../../api/test/model/ScenarioModel"
import MsApiScenarioConfig from "../../../../../api/test/components/ApiScenarioConfig";
import MsContainer from "../../../../../common/components/MsContainer";
import MsMainContainer from "../../../../../common/components/MsMainContainer";
export default {
name: "ApiTestDetail",
components: {MsMainContainer, MsContainer, MsApiScenarioConfig},
props: ["id"],
data() {
return {
result: {},
test: new Test(),
project: {}
}
},
methods: {
init() {
this.project = {};
if (this.id) {
this.getTest(this.id);
} else {
this.test = new Test();
if (this.$refs.config) {
this.$refs.config.reset();
}
}
},
getTest(id) {
this.result = this.$get("/api/get/" + id, response => {
if (response.data) {
let item = response.data;
this.test = new Test({
id: item.id,
projectId: item.projectId,
name: item.name,
status: item.status,
scenarioDefinition: JSON.parse(item.scenarioDefinition),
});
this.getProject(item.projectId);
this.$refs.config.reset();
}
});
},
getProject(projectId) {
this.$get("/project/get/" + projectId, response => {
this.project = response.data;
});
},
runTest() {
this.result = this.$post("/api/run", {id: this.test.id}, (response) => {
this.$success(this.$t('api_test.running'));
this.$emit('runTest', response.data)
});
}
}
}
</script>
<style scoped>
.test-container {
height: calc(100vh - 150px);
min-height: 600px;
padding: 15px;
}
.test-name {
width: 600px;
margin-left: -20px;
margin-right: 20px;
}
.test-project {
min-width: 150px;
}
</style>

View File

@ -0,0 +1,136 @@
<template>
<ms-container>
<ms-main-container>
<span v-if="!reportId">尚未执行</span>
<el-card v-if="reportId">
<section class="report-container" v-loading="loading">
<header class="report-header">
<span>{{report.projectName}} / </span>
<span class="time">{{report.createTime | timestampFormatDate}}</span>
</header>
<main>
<ms-metric-chart v-if="content" :content="content"/>
<el-tabs v-model="activeName">
<el-tab-pane :label="$t('api_report.total')" name="total">
<ms-scenario-results :scenarios="content.scenarios"/>
</el-tab-pane>
<el-tab-pane name="fail">
<template slot="label">
<span class="fail">{{$t('api_report.fail')}}</span>
</template>
<ms-scenario-results :scenarios="fails"/>
</el-tab-pane>
</el-tabs>
</main>
</section>
</el-card>
</ms-main-container>
</ms-container>
</template>
<script>
import MsScenarioResult from "../../../../../api/report/components/ScenarioResult";
import MsMetricChart from "../../../../../api/report/components/MetricChart";
import MsScenarioResults from "../../../../../api/report/components/ScenarioResults";
import MsRequestResult from "../../../../../api/report/components/RequestResult";
import MsContainer from "../../../../../common/components/MsContainer";
import MsMainContainer from "../../../../../common/components/MsMainContainer";
export default {
name: "ApiTestResult",
components: {MsMainContainer, MsContainer, MsRequestResult, MsScenarioResults, MsMetricChart, MsScenarioResult},
data() {
return {
activeName: "total",
content: {},
report: {},
loading: true,
fails: [],
}
},
props:['reportId'],
watch: {
reportId() {
this.init();
}
},
mounted() {
this.init();
},
methods: {
init() {
this.loading = true;
this.report = {};
this.content = {};
this.fails = [];
this.getReport();
},
getReport() {
if (this.reportId) {
let url = "/api/report/get/" + this.reportId;
this.$get(url, response => {
this.report = response.data || {};
if (this.report.status == 'Completed') {
this.content = JSON.parse(this.report.content);
this.getFails();
this.loading = false;
} else {
setTimeout(this.getReport, 2000)
}
});
}
},
getFails() {
this.fails = [];
this.content.scenarios.forEach((scenario) => {
let failScenario = Object.assign({}, scenario);
if (scenario.error > 0) {
this.fails.push(failScenario);
failScenario.requestResults = [];
scenario.requestResults.forEach((request) => {
if (!request.success) {
let failRequest = Object.assign({}, request);
failScenario.requestResults.push(failRequest);
}
});
}
});
}
}
}
</script>
<style>
.report-container .el-tabs__header {
margin-bottom: 1px;
}
</style>
<style scoped>
.report-container {
height: calc(100vh - 150px);
min-height: 600px;
overflow-y: auto;
}
.report-header {
font-size: 15px;
}
.report-header a {
text-decoration: none;
}
.report-header .time {
color: #909399;
margin-left: 10px;
}
.report-container .fail {
color: #F56C6C;
}
.report-container .is-active .fail {
color: inherit;
}
</style>

View File

@ -489,6 +489,7 @@ export default {
result_statistics_chart: "Result statistics chart", result_statistics_chart: "Result statistics chart",
create_template: "Create template", create_template: "Create template",
report_template: "Report template", report_template: "Report template",
test_detail: "Test detail",
} }
}, },
test_resource_pool: { test_resource_pool: {

View File

@ -486,6 +486,7 @@ export default {
result_statistics_chart: "测试结果统计图", result_statistics_chart: "测试结果统计图",
create_template: "新建模版", create_template: "新建模版",
report_template: "测试报告模版", report_template: "测试报告模版",
test_detail: "测试详情",
} }
}, },
test_resource_pool: { test_resource_pool: {

View File

@ -488,6 +488,7 @@ export default {
result_statistics_chart: "測試結果統計圖", result_statistics_chart: "測試結果統計圖",
create_template: "新建模版", create_template: "新建模版",
report_template: "測試報告模版", report_template: "測試報告模版",
test_detail: "測試詳情",
} }
}, },
test_resource_pool: { test_resource_pool: {