Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MeterSphere
metersphere
提交
3dcf2f0f
M
metersphere
项目概览
MeterSphere
/
metersphere
上一次同步 大约 3 年
通知
25
Star
1
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
M
metersphere
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3dcf2f0f
编写于
7月 08, 2020
作者:
C
chenjianxing
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
接口测试导入- Metersphere(json)
上级
1ab097bc
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
280 addition
and
8 deletion
+280
-8
backend/src/main/java/io/metersphere/api/controller/APITestController.java
...java/io/metersphere/api/controller/APITestController.java
+6
-0
backend/src/main/java/io/metersphere/api/dto/parse/ApiImport.java
...src/main/java/io/metersphere/api/dto/parse/ApiImport.java
+11
-0
backend/src/main/java/io/metersphere/api/parse/ApiImportParser.java
...c/main/java/io/metersphere/api/parse/ApiImportParser.java
+9
-0
backend/src/main/java/io/metersphere/api/parse/ApiImportParserFactory.java
...java/io/metersphere/api/parse/ApiImportParserFactory.java
+16
-0
backend/src/main/java/io/metersphere/api/parse/MsParser.java
backend/src/main/java/io/metersphere/api/parse/MsParser.java
+36
-0
backend/src/main/java/io/metersphere/api/service/APITestService.java
.../main/java/io/metersphere/api/service/APITestService.java
+49
-2
backend/src/main/java/io/metersphere/commons/constants/ApiImportPlatform.java
...a/io/metersphere/commons/constants/ApiImportPlatform.java
+5
-0
backend/src/main/java/io/metersphere/commons/constants/FileType.java
.../main/java/io/metersphere/commons/constants/FileType.java
+1
-1
frontend/src/business/components/api/test/ApiTestConfig.vue
frontend/src/business/components/api/test/ApiTestConfig.vue
+12
-2
frontend/src/business/components/api/test/components/import/ApiImport.vue
...iness/components/api/test/components/import/ApiImport.vue
+132
-0
frontend/src/business/components/track/case/components/TestCaseImport.vue
...iness/components/track/case/components/TestCaseImport.vue
+3
-3
未找到文件。
backend/src/main/java/io/metersphere/api/controller/APITestController.java
浏览文件 @
3dcf2f0f
...
...
@@ -96,4 +96,10 @@ public class APITestController {
return
apiTestService
.
run
(
request
);
}
@PostMapping
(
"/import/{platform}/{projectId}"
)
@RequiresRoles
(
value
=
{
RoleConstants
.
TEST_USER
,
RoleConstants
.
TEST_MANAGER
},
logical
=
Logical
.
OR
)
public
ApiTest
testCaseImport
(
MultipartFile
file
,
@PathVariable
String
platform
,
@PathVariable
String
projectId
)
{
return
apiTestService
.
apiTestImport
(
file
,
platform
,
projectId
);
}
}
backend/src/main/java/io/metersphere/api/dto/parse/ApiImport.java
0 → 100644
浏览文件 @
3dcf2f0f
package
io.metersphere.api.dto.parse
;
import
io.metersphere.api.dto.scenario.Scenario
;
import
lombok.Data
;
import
java.util.List
;
@Data
public
class
ApiImport
{
private
List
<
Scenario
>
scenarios
;
}
backend/src/main/java/io/metersphere/api/parse/ApiImportParser.java
0 → 100644
浏览文件 @
3dcf2f0f
package
io.metersphere.api.parse
;
import
io.metersphere.api.dto.parse.ApiImport
;
import
java.io.InputStream
;
public
interface
ApiImportParser
{
ApiImport
parse
(
InputStream
source
);
}
backend/src/main/java/io/metersphere/api/parse/ApiImportParserFactory.java
0 → 100644
浏览文件 @
3dcf2f0f
package
io.metersphere.api.parse
;
import
io.metersphere.commons.constants.ApiImportPlatform
;
import
io.metersphere.commons.constants.FileType
;
import
io.metersphere.performance.parse.EngineSourceParser
;
import
io.metersphere.performance.parse.xml.XmlEngineSourceParse
;
import
org.apache.commons.lang3.StringUtils
;
public
class
ApiImportParserFactory
{
public
static
ApiImportParser
getApiImportParser
(
String
platform
)
{
if
(
StringUtils
.
equals
(
ApiImportPlatform
.
Metersphere
.
name
(),
platform
))
{
return
new
MsParser
();
}
return
null
;
}
}
backend/src/main/java/io/metersphere/api/parse/MsParser.java
0 → 100644
浏览文件 @
3dcf2f0f
package
io.metersphere.api.parse
;
import
com.alibaba.fastjson.JSON
;
import
io.metersphere.api.dto.parse.ApiImport
;
import
io.metersphere.commons.exception.MSException
;
import
io.metersphere.commons.utils.LogUtil
;
import
java.io.*
;
public
class
MsParser
implements
ApiImportParser
{
@Override
public
ApiImport
parse
(
InputStream
source
)
{
BufferedReader
bufferedReader
=
null
;
StringBuilder
testStr
=
null
;
try
{
bufferedReader
=
new
BufferedReader
(
new
InputStreamReader
(
source
,
"UTF-8"
));
testStr
=
new
StringBuilder
();
String
inputStr
=
null
;
while
((
inputStr
=
bufferedReader
.
readLine
())
!=
null
)
{
testStr
.
append
(
inputStr
);
}
}
catch
(
Exception
e
)
{
MSException
.
throwException
(
e
.
getMessage
());
LogUtil
.
error
(
e
.
getMessage
(),
e
);
}
finally
{
try
{
source
.
close
();
}
catch
(
IOException
e
)
{
MSException
.
throwException
(
e
.
getMessage
());
LogUtil
.
error
(
e
.
getMessage
(),
e
);
}
}
return
JSON
.
parseObject
(
testStr
.
toString
(),
ApiImport
.
class
);
}
}
backend/src/main/java/io/metersphere/api/service/APITestService.java
浏览文件 @
3dcf2f0f
...
...
@@ -2,14 +2,19 @@ package io.metersphere.api.service;
import
com.alibaba.fastjson.JSONObject
;
import
io.metersphere.api.dto.APITestResult
;
import
io.metersphere.api.dto.parse.ApiImport
;
import
io.metersphere.api.dto.QueryAPITestRequest
;
import
io.metersphere.api.dto.SaveAPITestRequest
;
import
io.metersphere.api.jmeter.JMeterService
;
import
io.metersphere.api.parse.ApiImportParser
;
import
io.metersphere.api.parse.ApiImportParserFactory
;
import
io.metersphere.api.parse.MsParser
;
import
io.metersphere.base.domain.*
;
import
io.metersphere.base.mapper.ApiTestFileMapper
;
import
io.metersphere.base.mapper.ApiTestMapper
;
import
io.metersphere.base.mapper.ext.ExtApiTestMapper
;
import
io.metersphere.commons.constants.APITestStatus
;
import
io.metersphere.commons.constants.FileType
;
import
io.metersphere.commons.constants.ScheduleGroup
;
import
io.metersphere.commons.constants.ScheduleType
;
import
io.metersphere.commons.exception.MSException
;
...
...
@@ -26,8 +31,7 @@ import org.springframework.util.CollectionUtils;
import
org.springframework.web.multipart.MultipartFile
;
import
javax.annotation.Resource
;
import
java.io.ByteArrayInputStream
;
import
java.io.InputStream
;
import
java.io.*
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.Random
;
...
...
@@ -163,6 +167,15 @@ public class APITestService {
}
}
private
Boolean
isNameExist
(
SaveAPITestRequest
request
)
{
ApiTestExample
example
=
new
ApiTestExample
();
example
.
createCriteria
().
andNameEqualTo
(
request
.
getName
()).
andProjectIdEqualTo
(
request
.
getProjectId
()).
andIdNotEqualTo
(
request
.
getId
());
if
(
apiTestMapper
.
countByExample
(
example
)
>
0
)
{
return
true
;
}
return
false
;
}
private
ApiTest
updateTest
(
SaveAPITestRequest
request
)
{
checkNameExist
(
request
);
final
ApiTest
test
=
new
ApiTest
();
...
...
@@ -246,4 +259,38 @@ public class APITestService {
private
void
addOrUpdateApiTestCronJob
(
Schedule
request
)
{
scheduleService
.
addOrUpdateCronJob
(
request
,
ApiTestJob
.
getJobKey
(
request
.
getResourceId
()),
ApiTestJob
.
getTriggerKey
(
request
.
getResourceId
()),
ApiTestJob
.
class
);
}
public
ApiTest
apiTestImport
(
MultipartFile
file
,
String
platform
,
String
projectId
)
{
try
{
ApiImportParser
apiImportParser
=
ApiImportParserFactory
.
getApiImportParser
(
platform
);
ApiImport
apiImport
=
apiImportParser
.
parse
(
file
.
getInputStream
());
SaveAPITestRequest
request
=
getImportApiTest
(
file
,
projectId
,
apiImport
);
ApiTest
test
=
createTest
(
request
);
return
test
;
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
private
SaveAPITestRequest
getImportApiTest
(
MultipartFile
file
,
String
projectId
,
ApiImport
apiImport
)
{
SaveAPITestRequest
request
=
new
SaveAPITestRequest
();
request
.
setName
(
file
.
getOriginalFilename
());
request
.
setProjectId
(
projectId
);
request
.
setScenarioDefinition
(
apiImport
.
getScenarios
());
request
.
setUserId
(
SessionUtils
.
getUser
().
getId
());
request
.
setId
(
UUID
.
randomUUID
().
toString
());
for
(
FileType
fileType
:
FileType
.
values
())
{
String
suffix
=
fileType
.
suffix
();
String
name
=
request
.
getName
();
if
(
name
.
endsWith
(
suffix
))
{
request
.
setName
(
name
.
substring
(
0
,
name
.
length
()
-
suffix
.
length
()));
}
};
if
(
isNameExist
(
request
))
{
request
.
setName
(
request
.
getName
()
+
"_"
+
request
.
getId
().
substring
(
0
,
5
));
}
return
request
;
}
}
backend/src/main/java/io/metersphere/commons/constants/ApiImportPlatform.java
0 → 100644
浏览文件 @
3dcf2f0f
package
io.metersphere.commons.constants
;
public
enum
ApiImportPlatform
{
Metersphere
,
Postman
}
backend/src/main/java/io/metersphere/commons/constants/FileType.java
浏览文件 @
3dcf2f0f
package
io.metersphere.commons.constants
;
public
enum
FileType
{
JMX
(
".jmx"
),
CSV
(
".csv"
);
JMX
(
".jmx"
),
CSV
(
".csv"
)
,
JSON
(
".json"
)
;
// 保存后缀
private
String
suffix
;
...
...
frontend/src/business/components/api/test/ApiTestConfig.vue
浏览文件 @
3dcf2f0f
...
...
@@ -39,12 +39,18 @@
<el-dropdown-item
command=
"performance"
:disabled=
"create || isReadOnly"
>
{{
$t
(
'
api_test.create_performance_test
'
)
}}
</el-dropdown-item>
<el-dropdown-item
command=
"export"
:disabled=
"is
Disabled || isReadOnly
"
>
<el-dropdown-item
command=
"export"
:disabled=
"is
ReadOnly || create
"
>
{{
$t
(
'
api_test.export_config
'
)
}}
</el-dropdown-item>
<el-dropdown-item
command=
"import"
:disabled=
"isReadOnly"
>
导入
<!--
{{
$t
(
'
api_test.export_config
'
)
}}
-->
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<api-import
:project-id=
"test.projectId"
ref=
"apiImport"
/>
<ms-api-report-dialog
:test-id=
"id"
ref=
"reportDialog"
/>
<ms-schedule-config
:schedule=
"test.schedule"
:save=
"saveCronExpression"
@
scheduleChange=
"saveSchedule"
:check-open=
"checkScheduleEdit"
/>
...
...
@@ -64,11 +70,12 @@
import
MsApiReportDialog
from
"
./ApiReportDialog
"
;
import
{
checkoutTestManagerOrTestUser
,
downloadFile
}
from
"
../../../../common/js/utils
"
;
import
MsScheduleConfig
from
"
../../common/components/MsScheduleConfig
"
;
import
ApiImport
from
"
./components/import/ApiImport
"
;
export
default
{
name
:
"
MsApiTestConfig
"
,
components
:
{
MsScheduleConfig
,
MsApiReportDialog
,
MsApiReportStatus
,
MsApiScenarioConfig
},
components
:
{
ApiImport
,
MsScheduleConfig
,
MsApiReportDialog
,
MsApiReportStatus
,
MsApiScenarioConfig
},
props
:
[
"
id
"
],
...
...
@@ -211,6 +218,9 @@
case
"
export
"
:
downloadFile
(
this
.
test
.
name
+
"
.json
"
,
this
.
test
.
export
());
break
;
case
"
import
"
:
this
.
$refs
.
apiImport
.
open
();
break
;
}
},
saveCronExpression
(
cronExpression
)
{
...
...
frontend/src/business/components/api/test/components/import/ApiImport.vue
0 → 100644
浏览文件 @
3dcf2f0f
<
template
>
<el-dialog
:title=
"'接口测试导入'"
:visible.sync=
"visible"
class=
"api-import"
v-loading=
"result.loading"
>
<div
class=
"data-format"
>
<div>
数据格式
</div>
<el-radio-group
v-model=
"selectedPlatformValue"
>
<el-radio
v-for=
"(item, index) in platforms"
:key=
"index"
:label=
"item.value"
>
{{
item
.
name
}}
</el-radio>
</el-radio-group>
</div>
<div
class=
"api-upload"
>
<el-upload
drag
action=
""
:http-request=
"upload"
:limit=
"1"
:beforeUpload=
"uploadValidate"
:show-file-list=
"false"
:file-list=
"fileList"
multiple
>
<i
class=
"el-icon-upload"
></i>
<div
class=
"el-upload__text"
>
将文件拖到此处,或
<em>
点击上传
</em></div>
<div
class=
"el-upload__tip"
slot=
"tip"
>
文件大小不超过 20 M
</div>
</el-upload>
</div>
<div
class=
"format-tip"
>
<div>
<span>
说明:
{{
selectedPlatform
.
tip
}}
</span>
</div>
<div>
<span>
导出方法:
{{
selectedPlatform
.
exportTip
}}
</span>
</div>
</div>
</el-dialog>
</
template
>
<
script
>
import
MsDialogFooter
from
"
../../../../common/components/MsDialogFooter
"
;
export
default
{
name
:
"
ApiImport
"
,
components
:
{
MsDialogFooter
},
props
:
[
'
projectId
'
],
data
()
{
return
{
visible
:
false
,
platforms
:
[
{
name
:
'
Metersphere
'
,
value
:
'
Metersphere
'
,
tip
:
'
支持 Metersphere json 格式
'
,
exportTip
:
'
通过 Metersphere Api 测试页面或者浏览器插件导出 json 格式文件
'
,
suffixes
:
new
Set
([
'
json
'
])
}
],
selectedPlatform
:
{},
selectedPlatformValue
:
'
Metersphere
'
,
fileList
:
[],
result
:
{},
}
},
created
()
{
this
.
selectedPlatform
=
this
.
platforms
[
0
];
},
watch
:
{
selectedPlatformId
()
{
for
(
let
i
in
this
.
platforms
)
{
if
(
this
.
platforms
[
i
].
id
===
this
.
selectedPlatformValue
)
{
this
.
selectedPlatform
=
this
.
platforms
[
i
];
break
;
}
}
}
},
methods
:
{
open
()
{
this
.
visible
=
true
;
},
upload
(
file
)
{
this
.
fileList
.
push
(
file
.
file
);
this
.
result
=
this
.
$fileUpload
(
'
/api/import/
'
+
this
.
selectedPlatformValue
+
'
/
'
+
this
.
projectId
,
this
.
fileList
,
response
=>
{
let
res
=
response
.
data
;
this
.
$success
(
this
.
$t
(
'
test_track.case.import.success
'
));
this
.
visible
=
false
;
this
.
$router
.
push
({
path
:
'
/api/test/edit
'
,
query
:
{
id
:
res
.
id
}});
});
this
.
fileList
=
[];
},
uploadValidate
(
file
,
fileList
)
{
let
suffix
=
file
.
name
.
substring
(
file
.
name
.
lastIndexOf
(
'
.
'
)
+
1
);
if
(
!
this
.
selectedPlatform
.
suffixes
.
has
(
suffix
))
{
this
.
$warning
(
"
格式错误
"
);
return
false
;
}
if
(
file
.
size
/
1024
/
1024
>
20
)
{
this
.
$warning
(
this
.
$t
(
'
test_track.case.import.upload_limit_size
'
));
return
false
;
}
return
true
;
}
}
}
</
script
>
<
style
scoped
>
.format-tip
{
background
:
#EDEDED
;
}
.api-upload
{
text-align
:
center
;
}
.el-radio-group
{
margin
:
10px
0
;
}
.data-format
,
.format-tip
,
.api-upload
{
border
:
solid
#E1E1E1
1px
;
margin
:
10px
0
;
padding
:
10px
;
border-radius
:
3px
;
}
.api-import
>>>
.el-dialog__body
{
padding
:
15px
25px
;
}
</
style
>
frontend/src/business/components/track/case/components/TestCaseImport.vue
浏览文件 @
3dcf2f0f
...
...
@@ -16,7 +16,7 @@
:limit=
"1"
action=
""
:on-exceed=
"handleExceed"
:beforeUpload=
"
U
ploadValidate"
:beforeUpload=
"
u
ploadValidate"
:on-error=
"handleError"
:show-file-list=
"false"
:http-request=
"upload"
...
...
@@ -66,8 +66,8 @@
handleExceed
(
files
,
fileList
)
{
this
.
$warning
(
this
.
$t
(
'
test_track.case.import.upload_limit_count
'
));
},
U
ploadValidate
(
file
)
{
var
suffix
=
file
.
name
.
substring
(
file
.
name
.
lastIndexOf
(
'
.
'
)
+
1
);
u
ploadValidate
(
file
)
{
let
suffix
=
file
.
name
.
substring
(
file
.
name
.
lastIndexOf
(
'
.
'
)
+
1
);
if
(
suffix
!=
'
xls
'
&&
suffix
!=
'
xlsx
'
)
{
this
.
$warning
(
this
.
$t
(
'
test_track.case.import.upload_limit_format
'
));
return
false
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录