克隆测试用例

This commit is contained in:
chenjianxing 2020-04-24 13:56:32 +08:00
parent bccc1e3b1c
commit 6e3ec26fc0
12 changed files with 93 additions and 41 deletions

View File

@ -8,6 +8,7 @@ import com.github.pagehelper.PageHelper;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*; import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtTestCaseMapper; import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.controller.request.testcase.QueryTestCaseRequest; import io.metersphere.controller.request.testcase.QueryTestCaseRequest;
import io.metersphere.excel.domain.ExcelErrData; import io.metersphere.excel.domain.ExcelErrData;
@ -16,6 +17,7 @@ import io.metersphere.excel.domain.TestCaseExcelData;
import io.metersphere.excel.listener.EasyExcelListener; import io.metersphere.excel.listener.EasyExcelListener;
import io.metersphere.excel.listener.TestCaseDataListener; import io.metersphere.excel.listener.TestCaseDataListener;
import io.metersphere.excel.utils.EasyExcelUtil; import io.metersphere.excel.utils.EasyExcelUtil;
import io.metersphere.i18n.Translator;
import io.metersphere.user.SessionUser; import io.metersphere.user.SessionUser;
import io.metersphere.user.SessionUtils; import io.metersphere.user.SessionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -62,6 +64,15 @@ public class TestCaseService {
UserMapper userMapper; UserMapper userMapper;
public void addTestCase(TestCaseWithBLOBs testCase) { public void addTestCase(TestCaseWithBLOBs testCase) {
testCase.setName(testCase.getName());
TestCaseExample testCaseExample = new TestCaseExample();
testCaseExample.createCriteria()
.andProjectIdEqualTo(testCase.getProjectId())
.andNameEqualTo(testCase.getName());
List<TestCase> testCases = testCaseMapper.selectByExample(testCaseExample);
if (testCases.size() > 0) {
MSException.throwException(Translator.get("test_case_exist") + testCase.getName());
}
testCase.setId(UUID.randomUUID().toString()); testCase.setId(UUID.randomUUID().toString());
testCase.setCreateTime(System.currentTimeMillis()); testCase.setCreateTime(System.currentTimeMillis());
testCase.setUpdateTime(System.currentTimeMillis()); testCase.setUpdateTime(System.currentTimeMillis());

View File

@ -0,0 +1 @@
test_case_exist=

View File

@ -1,3 +1,4 @@
test_case_exist=A test case already exists under this project:
error_lang_invalid=Invalid language parameter error_lang_invalid=Invalid language parameter
load_test_already_exists=Duplicate load test name load_test_already_exists=Duplicate load test name
project_name_is_null=Project name cannot be null project_name_is_null=Project name cannot be null

View File

@ -1,24 +1,25 @@
error_lang_invalid=语言参数错误 test_case_exist=\u8BE5\u9879\u76EE\u4E0B\u5DF2\u5B58\u5728\u7528\u4F8B\uFF1A
load_test_already_exists=测试名称不能重复 error_lang_invalid=\u8BED\u8A00\u53C2\u6570\u9519\u8BEF
project_name_is_null=项目名称不能为空 load_test_already_exists=\u6D4B\u8BD5\u540D\u79F0\u4E0D\u80FD\u91CD\u590D
project_name_already_exists=项目名称已存在 project_name_is_null=\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
workspace_name_is_null=工作空间名不能为空 project_name_already_exists=\u9879\u76EE\u540D\u79F0\u5DF2\u5B58\u5728
workspace_name_already_exists=工作空间名已存在 workspace_name_is_null=\u5DE5\u4F5C\u7A7A\u95F4\u540D\u4E0D\u80FD\u4E3A\u7A7A
workspace_does_not_belong_to_user=当前工作空间不属于当前用户 workspace_name_already_exists=\u5DE5\u4F5C\u7A7A\u95F4\u540D\u5DF2\u5B58\u5728
organization_does_not_belong_to_user=当前组织不属于当前用户 workspace_does_not_belong_to_user=\u5F53\u524D\u5DE5\u4F5C\u7A7A\u95F4\u4E0D\u5C5E\u4E8E\u5F53\u524D\u7528\u6237
file_cannot_be_null=文件不能为空! organization_does_not_belong_to_user=\u5F53\u524D\u7EC4\u7EC7\u4E0D\u5C5E\u4E8E\u5F53\u524D\u7528\u6237
edit_load_test_not_found=无法编辑测试,未找到测试: file_cannot_be_null=\u6587\u4EF6\u4E0D\u80FD\u4E3A\u7A7A\uFF01
run_load_test_not_found=无法运行测试,未找到测试: edit_load_test_not_found=\u65E0\u6CD5\u7F16\u8F91\u6D4B\u8BD5\uFF0C\u672A\u627E\u5230\u6D4B\u8BD5\uFF1A
run_load_test_file_not_found=无法运行测试无法获取测试文件元信息测试ID run_load_test_not_found=\u65E0\u6CD5\u8FD0\u884C\u6D4B\u8BD5\uFF0C\u672A\u627E\u5230\u6D4B\u8BD5\uFF1A
run_load_test_file_content_not_found=无法运行测试无法获取测试文件内容测试ID run_load_test_file_not_found=\u65E0\u6CD5\u8FD0\u884C\u6D4B\u8BD5\uFF0C\u65E0\u6CD5\u83B7\u53D6\u6D4B\u8BD5\u6587\u4EF6\u5143\u4FE1\u606F\uFF0C\u6D4B\u8BD5ID\uFF1A
run_load_test_file_init_error=无法运行测试初始化运行环境失败测试ID run_load_test_file_content_not_found=\u65E0\u6CD5\u8FD0\u884C\u6D4B\u8BD5\uFF0C\u65E0\u6CD5\u83B7\u53D6\u6D4B\u8BD5\u6587\u4EF6\u5185\u5BB9\uFF0C\u6D4B\u8BD5ID\uFF1A
load_test_is_running=测试正在运行, 请等待 run_load_test_file_init_error=\u65E0\u6CD5\u8FD0\u884C\u6D4B\u8BD5\uFF0C\u521D\u59CB\u5316\u8FD0\u884C\u73AF\u5883\u5931\u8D25\uFF0C\u6D4B\u8BD5ID\uFF1A
node_deep_limit=节点深度不超过5层 load_test_is_running=\u6D4B\u8BD5\u6B63\u5728\u8FD0\u884C, \u8BF7\u7B49\u5F85
no_nodes_message=没有节点信息 node_deep_limit=\u8282\u70B9\u6DF1\u5EA6\u4E0D\u8D85\u8FC75\u5C42\uFF01
duplicate_node_ip=节点 IP 重复 no_nodes_message=\u6CA1\u6709\u8282\u70B9\u4FE1\u606F
only_one_k8s=只能添加一个 K8s duplicate_node_ip=\u8282\u70B9 IP \u91CD\u590D
organization_id_is_null=组织 ID 不能为空 only_one_k8s=\u53EA\u80FD\u6DFB\u52A0\u4E00\u4E2A K8s
max_thread_insufficient=并发用户数超额 organization_id_is_null=\u7EC4\u7EC7 ID \u4E0D\u80FD\u4E3A\u7A7A
cannot_edit_load_test_running=不能修改正在运行的测试 max_thread_insufficient=\u5E76\u53D1\u7528\u6237\u6570\u8D85\u989D
test_not_found=测试不存在: cannot_edit_load_test_running=\u4E0D\u80FD\u4FEE\u6539\u6B63\u5728\u8FD0\u884C\u7684\u6D4B\u8BD5
test_not_running=测试未运行 test_not_found=\u6D4B\u8BD5\u4E0D\u5B58\u5728:
test_not_running=\u6D4B\u8BD5\u672A\u8FD0\u884C

View File

@ -1,9 +1,10 @@
<template> <template>
<span> <span>
<ms-table-operator-button icon="el-icon-edit" <slot name="front"></slot>
:exec="editClick" @click.stop="editClickStop"/> <ms-table-operator-button :tip="$t('commons.edit')" icon="el-icon-edit" @exec="editClick" @click.stop="editClickStop"/>
<ms-table-operator-button icon="el-icon-delete" type="danger" <slot name="middle"></slot>
:exec="deleteClick" @click.stop="deleteClickStop"/> <ms-table-operator-button :tip="$t('commons.delete')" icon="el-icon-delete" type="danger" @exec="deleteClick" @click.stop="deleteClickStop"/>
<slot name="behind"></slot>
</span> </span>
</template> </template>

View File

@ -1,14 +1,17 @@
<template> <template>
<el-button @click="exec" <ms-tip-button @click="exec"
@click.stop="clickStop" :type="type" @clickStop="clickStop"
:icon="icon" size="mini" circle></el-button> :type="type"
:tip="tip"
:icon="icon" size="mini" circle/>
</template> </template>
<script> <script>
import MsTableButton from "./MsTableButton"; import MsTableButton from "./MsTableButton";
import MsTipButton from "./MsTipButton";
export default { export default {
name: "MsTableOperatorButton", name: "MsTableOperatorButton",
components: {MsTableButton}, components: {MsTipButton, MsTableButton},
props: { props: {
icon: { icon: {
type: String, type: String,
@ -18,11 +21,14 @@
type: String, type: String,
default: 'primary' default: 'primary'
}, },
exec: { tip: {
type: Function type: String
} }
}, },
methods: { methods: {
exec() {
this.$emit('exec');
},
clickStop() { clickStop() {
this.$emit('clickStop'); this.$emit('clickStop');
} }

View File

@ -5,6 +5,7 @@
placement="bottom" placement="bottom"
:effect="effect"> :effect="effect">
<el-button @click="exec()" <el-button @click="exec()"
@click.stop="clickStop"
circle circle
:type="type" :type="type"
:icon="icon" :icon="icon"
@ -42,6 +43,9 @@
methods: { methods: {
exec() { exec() {
this.$emit('click'); this.$emit('click');
},
clickStop() {
this.$emit('clickStop');
} }
} }
} }

View File

@ -23,6 +23,7 @@
:selectNodeIds="selectNodeIds" :selectNodeIds="selectNodeIds"
:selectNodeNames="selectNodeNames" :selectNodeNames="selectNodeNames"
@testCaseEdit="editTestCase" @testCaseEdit="editTestCase"
@testCaseCopy="copyTestCase"
@testCaseDetail="showTestCaseDetail" @testCaseDetail="showTestCaseDetail"
@refresh="refresh" @refresh="refresh"
ref="testCaseList"> ref="testCaseList">
@ -142,6 +143,13 @@
this.testCaseReadOnly = false; this.testCaseReadOnly = false;
this.$refs.testCaseEditDialog.open(testCase); this.$refs.testCaseEditDialog.open(testCase);
}, },
copyTestCase(testCase) {
this.testCaseReadOnly = false;
let item = {};
Object.assign(item, testCase);
item.name = '';
this.$refs.testCaseEditDialog.open(item);
},
showTestCaseDetail(testCase) { showTestCaseDetail(testCase) {
this.testCaseReadOnly = true; this.testCaseReadOnly = true;
this.$refs.testCaseEditDialog.open(testCase); this.$refs.testCaseEditDialog.open(testCase);

View File

@ -2,7 +2,7 @@
<div> <div>
<el-dialog :title="$t('test_track.case.create')" :visible.sync="dialogFormVisible" width="65%"> <el-dialog :title="operationType == 'edit' ? $t('test_track.case.edit_case') : $t('test_track.case.create')" :visible.sync="dialogFormVisible" width="65%">
<el-form :model="form" :rules="rules" ref="caseFrom"> <el-form :model="form" :rules="rules" ref="caseFrom">
@ -246,6 +246,10 @@
if(testCase){ if(testCase){
// //
this.operationType = 'edit'; this.operationType = 'edit';
//
if (testCase.name === '') {
this.operationType = 'add';
}
let tmp = {}; let tmp = {};
Object.assign(tmp, testCase); Object.assign(tmp, testCase);
tmp.steps = JSON.parse(testCase.steps); tmp.steps = JSON.parse(testCase.steps);
@ -328,7 +332,6 @@
} }
}, },
resetForm() { resetForm() {
// //
if (this.$refs['caseFrom']) { if (this.$refs['caseFrom']) {
this.$refs['caseFrom'].validate((valid) => { this.$refs['caseFrom'].validate((valid) => {

View File

@ -1,4 +1,4 @@
<template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform"> <template>
<div> <div>
<el-card v-loading="result.loading"> <el-card v-loading="result.loading">
@ -73,7 +73,12 @@
<el-table-column <el-table-column
:label="$t('commons.operating')"> :label="$t('commons.operating')">
<template v-slot:default="scope"> <template v-slot:default="scope">
<ms-table-operator @editClick="handleEdit(scope.row)" @deleteClick="handleDelete(scope.row)"/> <ms-table-operator @editClick="handleEdit(scope.row)" @deleteClick="handleDelete(scope.row)">
<template v-slot:middle>
<ms-table-operator-button :tip="$t('commons.copy')" icon="el-icon-document-copy"
type="success" @exec="handleCopy(scope.row)"/>
</template>
</ms-table-operator>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -97,10 +102,12 @@
import TypeTableItem from "../../common/TableItems/TypeTableItem"; import TypeTableItem from "../../common/TableItems/TypeTableItem";
import MethodTableItem from "../../common/TableItems/MethodTableItem"; import MethodTableItem from "../../common/TableItems/MethodTableItem";
import MsTableOperator from "../../../common/components/MsTableOperator"; import MsTableOperator from "../../../common/components/MsTableOperator";
import MsTableOperatorButton from "../../../common/components/MsTableOperatorButton";
export default { export default {
name: "TestCaseList", name: "TestCaseList",
components: { components: {
MsTableOperatorButton,
MsTableOperator, MsTableOperator,
MethodTableItem, MethodTableItem,
TypeTableItem, TypeTableItem,
@ -177,6 +184,9 @@
handleEdit(testCase) { handleEdit(testCase) {
this.$emit('testCaseEdit', testCase); this.$emit('testCaseEdit', testCase);
}, },
handleCopy(testCase) {
this.$emit('testCaseCopy', testCase);
},
handleDelete(testCase) { handleDelete(testCase) {
this.$alert(this.$t('test_track.case.delete_confirm') + testCase.name + "", '', { this.$alert(this.$t('test_track.case.delete_confirm') + testCase.name + "", '', {
confirmButtonText: this.$t('commons.confirm'), confirmButtonText: this.$t('commons.confirm'),

View File

@ -43,6 +43,8 @@ export default {
'functional': 'Functional test', 'functional': 'Functional test',
'input_content': 'Please enter content', 'input_content': 'Please enter content',
'create': 'Create', 'create': 'Create',
'edit': 'Edit',
'copy': 'Copy',
'refresh': 'Refresh', 'refresh': 'Refresh',
'remark': 'Remark', 'remark': 'Remark',
'delete': 'Delete', 'delete': 'Delete',
@ -186,6 +188,7 @@ export default {
test_case: "Test Case", test_case: "Test Case",
case_list: "Test Case List", case_list: "Test Case List",
create_case: "Create Case", create_case: "Create Case",
eitd_case: "Eidt Case",
no_project: "There is no project in this workspace, please create the project first", no_project: "There is no project in this workspace, please create the project first",
priority: "Priority", priority: "Priority",
type: "Type", type: "Type",
@ -222,10 +225,11 @@ export default {
upload_limit_size: "Upload file size cannot exceed 20MB!", upload_limit_size: "Upload file size cannot exceed 20MB!",
success: "Import success", success: "Import success",
}, },
export: { export: {
export: "Export cases" export: "Export cases"
} }
},}, },
plan: { plan: {
test_plan: "Test Plan", test_plan: "Test Plan",
create_plan: "Create test plan", create_plan: "Create test plan",
@ -247,7 +251,6 @@ export default {
plan_status_running: "Starting", plan_status_running: "Starting",
plan_status_completed: "Completed", plan_status_completed: "Completed",
plan_delete_confirm: "Confirm delete test plan: ", plan_delete_confirm: "Confirm delete test plan: ",
}, },
module: { module: {
search: "Search module", search: "Search module",
@ -279,7 +282,7 @@ export default {
select_execute_result: "Select execute result", select_execute_result: "Select execute result",
confirm_cancel_relevance: "Confirm cancel relevance", confirm_cancel_relevance: "Confirm cancel relevance",
select_manipulate: "Select the data you want to manipulate", select_manipulate: "Select the data you want to manipulate",
}
}, },
test_resource_pool: { test_resource_pool: {
'type': 'type', 'type': 'type',

View File

@ -43,6 +43,8 @@ export default {
'functional': '功能测试', 'functional': '功能测试',
'input_content': '请输入内容', 'input_content': '请输入内容',
'create': '新建', 'create': '新建',
'edit': '编辑',
'copy': '复制',
'refresh': '刷新', 'refresh': '刷新',
'remark': '备注', 'remark': '备注',
'delete': '删除', 'delete': '删除',
@ -229,6 +231,7 @@ export default {
test_case: "测试用例", test_case: "测试用例",
case_list: "用例列表", case_list: "用例列表",
create_case: "创建用例", create_case: "创建用例",
edit_case: "编辑用例",
no_project: "该工作空间下无项目,请先创建项目", no_project: "该工作空间下无项目,请先创建项目",
priority: "优先级", priority: "优先级",
type: "类型", type: "类型",