add: 性能测试-报告
This commit is contained in:
@@ -68,4 +68,12 @@ export function editAndExecuteTest(data) {
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 测试-编辑-立即执行
|
||||
export function executeTest(query) {
|
||||
return request({
|
||||
url: '/test/performanceTest/executeNow?' + query,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1 +1,26 @@
|
||||
import request from '@/utils/request'
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 报告-列表查询
|
||||
export function getReportList(query) {
|
||||
return request({
|
||||
url: '/test/performanceReport//list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 报告-列表删除
|
||||
export function deleteReport(data) {
|
||||
return request({
|
||||
url: '/test/performanceReport/delete/' + data,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 报告-详情
|
||||
export function getReportDetail(query) {
|
||||
return request({
|
||||
url: '/test/performanceReport/getInfo/' + query,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ export default {
|
||||
addForm: {
|
||||
performanceName: '', // 性能测试名称
|
||||
performanceTestCaseVOList: [], // 场景列表
|
||||
concurrentThreads: '', // 并发用户数
|
||||
concurrentThreads: '0', // 并发用户数
|
||||
errorOperType: '', // 在取样器错误后要执行的动作,1:继续;2:开始下一个线程轮询;3:停止线程;4:停止测试;5:立即停止测试
|
||||
executeType: '', // 执行方式,1:按持续时间;2:按迭代次数
|
||||
rampUpSeconds: '0', // 多少秒内线程建立完成,默认0
|
||||
@@ -193,14 +193,36 @@ export default {
|
||||
time: "2025-02-22 10:00:00",
|
||||
},
|
||||
],
|
||||
validation: false, // 校验
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getTestCaseData()
|
||||
},
|
||||
methods: {
|
||||
// 校验
|
||||
validationForm() {
|
||||
if (this.addForm.performanceName === '' || this.addForm.performanceName === null) {
|
||||
this.$message({ message: '请输入测试名称', type: 'warning' })
|
||||
return
|
||||
}
|
||||
|
||||
if (this.addForm.errorOperType === '' || this.addForm.errorOperType === null) {
|
||||
this.$message({ message: '请填写取样器错误后', type: 'warning' })
|
||||
return
|
||||
}
|
||||
|
||||
if (this.addForm.executeType === '' || this.addForm.executeType === null) {
|
||||
this.$message({ message: '请选择执行方式', type: 'warning' })
|
||||
return
|
||||
}
|
||||
|
||||
this.validation = true
|
||||
},
|
||||
// 保存
|
||||
handleWithSave() {
|
||||
this.validationForm()
|
||||
if (this.validation === false) { return }
|
||||
this.changeList.forEach(item => {
|
||||
var par = {
|
||||
testCaseId: item.id,
|
||||
@@ -208,7 +230,6 @@ export default {
|
||||
}
|
||||
this.addForm.performanceTestCaseVOList.push(par)
|
||||
})
|
||||
console.log(this.addForm)
|
||||
addTest(this.addForm).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.$message({ message: '新增成功', type: 'success' })
|
||||
@@ -220,6 +241,9 @@ export default {
|
||||
},
|
||||
// 保存并执行
|
||||
handleWithSaveAndExecute() {
|
||||
this.validationForm()
|
||||
if (this.validation === false) { return }
|
||||
// 需要校验crontab表达式
|
||||
addAndExecuteTest(this.addForm).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.$message({ message: '新增成功', type: 'success' })
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<div class="save">
|
||||
<el-button type="primary" plain @click="handleWithSave">保存</el-button>
|
||||
<el-button type="primary" plain @click="handleWithSaveAndExecute">保存并执行</el-button>
|
||||
<el-button type="primary" plain @click="handleWithExecute">立即执行</el-button>
|
||||
<el-button type="warning" plain @click="handleWithCancel">取消</el-button>
|
||||
</div>
|
||||
<div class="date">
|
||||
@@ -143,7 +144,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { editTest, editAndExecuteTest, getTestCaseList, getTestDetail } from '../../../api/performance';
|
||||
import { editTest, editAndExecuteTest, getTestCaseList, getTestDetail, executeTest } from '../../../api/performance';
|
||||
|
||||
export default {
|
||||
name: "PerformanceEdit",
|
||||
@@ -233,6 +234,17 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
// 立即执行
|
||||
handleWithExecute() {
|
||||
executeTest(this.$route.query.id).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.$message({ message: '执行成功', type: 'success' })
|
||||
this.$tab.closeOpenPage({ path: "/performance/performance" });
|
||||
} else {
|
||||
this.$message({ message: '执行失败', type: 'error' })
|
||||
}
|
||||
})
|
||||
},
|
||||
// 取消
|
||||
handleWithCancel() {
|
||||
this.$tab.closeOpenPage({ path: "/performance/performance" });
|
||||
|
||||
@@ -9,16 +9,24 @@
|
||||
<div class="table">
|
||||
<el-table :data="data">
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name0" label="名称" align="center" sortable />
|
||||
<el-table-column prop="name1" label="创建人" align="center" width="150" sortable />
|
||||
<el-table-column prop="name2" label="并发数" align="center" width="150" sortable />
|
||||
<el-table-column prop="name3" label="响应(s)" align="center" width="150" sortable />
|
||||
<el-table-column prop="name4" label="TPS" align="center" width="150" sortable />
|
||||
<el-table-column prop="name5" label="开始时间" align="center" width="150" sortable />
|
||||
<el-table-column prop="name6" label="结束时间" align="center" width="150" sortable />
|
||||
<el-table-column prop="name7" label="执行时长" align="center" width="150" sortable />
|
||||
<el-table-column prop="name8" label="触发方式" align="center" width="150" sortable />
|
||||
<el-table-column prop="name9" label="状态" align="center" width="150" sortable />
|
||||
<el-table-column prop="name" label="名称" align="center" sortable width="150" />
|
||||
<el-table-column prop="createBy" label="创建人" align="center" width="150" sortable />
|
||||
<el-table-column prop="concurrentThreads" label="并发数" align="center" width="150" sortable />
|
||||
<el-table-column prop="tps" label="TPS" align="center" width="150" sortable />
|
||||
<el-table-column prop="startTime" label="开始时间" align="center" sortable />
|
||||
<el-table-column prop="endTime" label="结束时间" align="center" sortable />
|
||||
<el-table-column prop="triggerType" label="触发方式" align="center" sortable>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.triggerType === 1">按持续时间</div>
|
||||
<div v-else>按迭代次数</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" align="center" width="150" sortable>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.triggerType === 1">开启</div>
|
||||
<div v-else>关闭</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="action" label="操作" align="center" width="150" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" icon="el-icon-view" @click="hadleClickDetail(scope.row)">查看</el-button>
|
||||
@@ -36,6 +44,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getReportList, deleteReport } from '../../../api/performance/report';
|
||||
|
||||
export default {
|
||||
name: "Report",
|
||||
data() {
|
||||
@@ -46,24 +56,41 @@ export default {
|
||||
performanceName: '', // 名称
|
||||
},
|
||||
total: 0,
|
||||
data: [{}, {}],
|
||||
data: [],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getReportListData()
|
||||
},
|
||||
methods: {
|
||||
// 查看
|
||||
hadleClickDetail() {
|
||||
this.$tab.openPage("报告详情", "/performance/report/detail");
|
||||
hadleClickDetail(val) {
|
||||
this.$tab.openPage("报告详情", "/performance/report/detail", { id: val.id });
|
||||
},
|
||||
// 删除’
|
||||
hadleClickDelete() {
|
||||
|
||||
// 删除
|
||||
hadleClickDelete(val) {
|
||||
deleteReport(val.id).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.$message({ message: '删除成功', type: 'success' })
|
||||
this.getReportListData()
|
||||
}
|
||||
})
|
||||
},
|
||||
// 获取列表数据
|
||||
getReportListData() {
|
||||
getReportList(this.serachForm).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.data = res.rows
|
||||
this.total = res.total
|
||||
}
|
||||
})
|
||||
},
|
||||
// 分页
|
||||
handleSizeChange() { },
|
||||
handleCurrentChange() { },
|
||||
serachList() { },
|
||||
serachList() {
|
||||
this.getReportListData()
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,63 +1,85 @@
|
||||
<template>
|
||||
<div class="report-detail">
|
||||
<div class="header">
|
||||
<div class="title">执行时长</div>
|
||||
<div class="title">开始时间</div>
|
||||
<div class="title">结束时间</div>
|
||||
<div class="title">执行时长:{{ detailData ? detailData.costTime : '' }}</div>
|
||||
<div class="title">开始时间:{{ detailData ? detailData.startTime : '' }}</div>
|
||||
<div class="title">结束时间:{{ detailData ? detailData.endTime : ' ' }}</div>
|
||||
</div>
|
||||
<div class="tabs">
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane label="请求统计" name="first">
|
||||
<div class="btn-wrap">
|
||||
<el-button @click="exportExcel">导出为Excel</el-button>
|
||||
</div>
|
||||
<el-table :data="statisticsData">
|
||||
<el-table-column label="Requests" align="center">
|
||||
<el-table-column prop="name" label="Label" width="120" sortable align="center" />
|
||||
<el-table-column prop="label" label="Label" sortable align="center" />
|
||||
</el-table-column>
|
||||
<el-table-column label="Executions" align="center">
|
||||
<el-table-column prop="name" label="Samples" width="120" sortable align="center" />
|
||||
<el-table-column prop="name" label="FAIL" width="120" sortable align="center" />
|
||||
<el-table-column prop="name" label="Error%" width="120" sortable align="center" />
|
||||
<el-table-column prop="samples" label="Samples" sortable align="center" />
|
||||
</el-table-column>
|
||||
<el-table-column label="Response Times(ms)" align="center">
|
||||
<el-table-column prop="name" label="Avg" width="120" sortable align="center" />
|
||||
<el-table-column prop="name" label="Min" width="120" sortable align="center" />
|
||||
<el-table-column prop="name" label="Max" width="120" sortable align="center" />
|
||||
<el-table-column prop="name" label="Med" width="120" sortable align="center" />
|
||||
<el-table-column prop="name" label="90%" width="120" sortable align="center" />
|
||||
<el-table-column prop="name" label="95%" width="120" sortable align="center" />
|
||||
<el-table-column prop="name" label="99%" width="120" sortable align="center" />
|
||||
<el-table-column prop="average" label="Avg" sortable align="center" />
|
||||
<el-table-column prop="min" label="Min" sortable align="center" />
|
||||
<el-table-column prop="max" label="Max" sortable align="center" />
|
||||
<el-table-column prop="errorRate" label="ErrorRate" sortable align="center">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ getFormatToTwoDecimalPlaces(scope.row.errorRate) }}%</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="Throughput" align="center">
|
||||
<el-table-column prop="name" label="Trans/s" width="120" sortable align="center" />
|
||||
<el-table-column prop="throughput" label="Trans/s" width="120" sortable align="center">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ getFormatToTwoDecimalPlaces(scope.row.throughput) }}%</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="NetWork(KB/Sec)" align="center">
|
||||
<el-table-column prop="name" label="Recd" width="120" sortable align="center" />
|
||||
<el-table-column prop="name" label="Sent" width="120" sortable align="center" />
|
||||
<el-table-column prop="receivedKBPerSec" label="Recd" width="120" sortable align="center">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ getFormatToTwoDecimalPlaces(scope.row.receivedKBPerSec) }}%</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sentKBPerSec" label="Sent" width="120" sortable align="center">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ getFormatToTwoDecimalPlaces(scope.row.sentKBPerSec) }}%</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="错误记录" name="second">
|
||||
<div class="title-error">Errors</div>
|
||||
<el-table :data="errorList" border>
|
||||
<el-table-column prop="date" label="Type of error" sortable />
|
||||
<el-table-column prop="name" label="Number of errors" sortable />
|
||||
<el-table-column prop="address" label="% in errors" sortable />
|
||||
<el-table-column prop="address" label="% in samples" sortable />
|
||||
<el-table :data="errorCodeStatList" border>
|
||||
<el-table-column prop="responseCode" label="Type of error" sortable align="center" />
|
||||
<el-table-column prop="count" label="Number of errors" sortable align="center" />
|
||||
<el-table-column prop="errorRatio" label="% in errors" sortable align="center">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ getFormatToTwoDecimalPlaces(scope.row.errorRatio) }}%</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="totalRatio" label="% in samples" sortable align="center">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ getFormatToTwoDecimalPlaces(scope.row.totalRatio) }}%</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="title-error">Top 5 Errors</div>
|
||||
<el-table :data="errorList" border>
|
||||
<el-table-column prop="date" label="Sample" sortable />
|
||||
<el-table-column prop="name" label="#Samples" sortable />
|
||||
<el-table-column prop="address" label="All Errors" sortable />
|
||||
</el-table>
|
||||
<div class="title-error">#1 Errors</div>
|
||||
<el-table :data="errorList" border>
|
||||
<el-table-column prop="date" label="Sample" sortable />
|
||||
<el-table-column prop="name" label="#1 Error" sortable />
|
||||
<el-table-column prop="address" label="#1 Error Count" sortable />
|
||||
<el-table :data="top5InterfaceErrorStatList" border>
|
||||
<el-table-column prop="interfaceName" label="Sample" sortable align="center" />
|
||||
<el-table-column prop="errorCount" label="#Samples" sortable align="center" />
|
||||
<el-table-column prop="totalSamples" label="All Errors" sortable align="center" />
|
||||
</el-table>
|
||||
<div v-for="(item, index) in interfaceErrorDetailList">
|
||||
<div class="title-error">#{{ index + 1 }} Errors</div>
|
||||
<el-table :data="interfaceErrorDetailList" border>
|
||||
<el-table-column prop="interfaceName" label="Sample" sortable align="center" />
|
||||
<el-table-column prop="errorName" :label="getLabel(index)" sortable align="center">
|
||||
<template slot-scope="scope">{{ getErrorName(scope.row) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="errorCount" :label="getErrorCount(index)" sortable align="center">
|
||||
<template slot-scope="scope">{{ getErrorCountDetail(scope.row) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
@@ -65,21 +87,62 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getReportDetail } from '../../../api/performance/report';
|
||||
|
||||
export default {
|
||||
name: "ReportDetail",
|
||||
data() {
|
||||
return {
|
||||
activeName: 'first',
|
||||
statisticsData: [], // 统计
|
||||
errorList: []
|
||||
errorCodeStatList: [],
|
||||
top5InterfaceErrorStatList: [],
|
||||
interfaceErrorDetailList: [],
|
||||
detailData: null,
|
||||
errorReport: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getReportDetailData()
|
||||
},
|
||||
methods: {
|
||||
// 导出excel
|
||||
exportExcel() {
|
||||
|
||||
getReportDetailData() {
|
||||
getReportDetail(this.$route.query.id).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.detailData = res.data
|
||||
this.statisticsData = JSON.parse(res.data.summaryReport)
|
||||
this.errorReport = JSON.parse(res.data.errorReport)
|
||||
this.errorCodeStatList = this.errorReport.errorCodeStatList
|
||||
this.top5InterfaceErrorStatList = this.errorReport.top5InterfaceErrorStatList
|
||||
this.interfaceErrorDetailList = this.errorReport.interfaceErrorDetailList
|
||||
}
|
||||
})
|
||||
},
|
||||
// 保留2为小数
|
||||
getFormatToTwoDecimalPlaces(num) {
|
||||
return Math.round(num * 100) / 100;
|
||||
},
|
||||
getLabel(index) {
|
||||
const i = index + 1
|
||||
return '#' + i + ' Error'
|
||||
},
|
||||
getErrorCount(index) {
|
||||
const i = index + 1
|
||||
return '#' + i + ' Error ' + 'Count'
|
||||
},
|
||||
getErrorName(val) {
|
||||
var key1 = ''
|
||||
for (let key in val.errorCodeCounts) {
|
||||
key1 = key
|
||||
}
|
||||
return key1
|
||||
},
|
||||
getErrorCountDetail(val) {
|
||||
var keyV = ''
|
||||
for (let key in val.errorCodeCounts) {
|
||||
keyV = val.errorCodeCounts[key]
|
||||
}
|
||||
return keyV
|
||||
},
|
||||
}
|
||||
|
||||
@@ -106,11 +169,6 @@ export default {
|
||||
.tabs {
|
||||
margin-top: 10px;
|
||||
|
||||
.btn-wrap {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.title-error {
|
||||
|
||||
Reference in New Issue
Block a user