feat(接口定义): 完成JDBC快捷调试

This commit is contained in:
fit2-zhao 2020-11-25 18:52:33 +08:00
parent 948fcdb3b8
commit 2ba69e9a32
7 changed files with 190 additions and 73 deletions

View File

@ -14,7 +14,6 @@ import org.apache.jmeter.protocol.jdbc.sampler.JDBCSampler;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.collections.ListedHashTree;
import java.util.List;
@ -40,10 +39,9 @@ public class MsJDBCSampler extends MsTestElement {
private String environmentId;
public void toHashTree(HashTree tree, List<MsTestElement> hashTree) {
final HashTree samplerHashTree = new ListedHashTree();
samplerHashTree.add(jdbcDataSource());
samplerHashTree.add(arguments(this.getName() + " Variables", this.getVariables()));
tree.set(jdbcSampler(), samplerHashTree);
final HashTree samplerHashTree = tree.add(jdbcSampler());
tree.add(jdbcDataSource());
tree.add(arguments(this.getName() + " Variables", this.getVariables()));
if (CollectionUtils.isNotEmpty(hashTree)) {
hashTree.forEach(el -> {
el.toHashTree(samplerHashTree, el.getHashTree());
@ -53,6 +51,7 @@ public class MsJDBCSampler extends MsTestElement {
private Arguments arguments(String name, List<KeyValue> variables) {
Arguments arguments = new Arguments();
if (!variables.isEmpty()) {
arguments.setEnabled(true);
arguments.setName(name);
arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName());
@ -60,6 +59,7 @@ public class MsJDBCSampler extends MsTestElement {
variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue ->
arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=")
);
}
return arguments;
}
@ -69,13 +69,13 @@ public class MsJDBCSampler extends MsTestElement {
sampler.setProperty(TestElement.TEST_CLASS, JDBCSampler.class.getName());
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
// request.getDataSource() 是ID需要转换为Name
sampler.setDataSource(this.dataSource.getName());
sampler.setQuery(this.getQuery());
sampler.setQueryTimeout(String.valueOf(this.getQueryTimeout()));
sampler.setResultVariable(this.getResultVariable());
sampler.setVariableNames(this.getVariableNames());
sampler.setResultSetHandler("Store as String");
sampler.setQueryType("Callable Statement");
sampler.setProperty("dataSource", this.dataSource.getName());
sampler.setProperty("query", this.getQuery());
sampler.setProperty("queryTimeout", String.valueOf(this.getQueryTimeout()));
sampler.setProperty("resultVariable", this.getResultVariable());
sampler.setProperty("variableNames", this.getVariableNames());
sampler.setProperty("resultSetHandler", "Store as String");
sampler.setProperty("queryType", "Callable Statement");
return sampler;
}
@ -85,19 +85,19 @@ public class MsJDBCSampler extends MsTestElement {
dataSourceElement.setName(this.getName() + " JDBCDataSource");
dataSourceElement.setProperty(TestElement.TEST_CLASS, DataSourceElement.class.getName());
dataSourceElement.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
dataSourceElement.setAutocommit(true);
dataSourceElement.setKeepAlive(true);
dataSourceElement.setPreinit(true);
dataSourceElement.setDataSource(dataSource.getName());
dataSourceElement.setDbUrl(dataSource.getDbUrl());
dataSourceElement.setDriver(dataSource.getDriver());
dataSourceElement.setUsername(dataSource.getUsername());
dataSourceElement.setPassword(dataSource.getPassword());
dataSourceElement.setPoolMax(String.valueOf(dataSource.getPoolMax()));
dataSourceElement.setTimeout(String.valueOf(dataSource.getTimeout()));
dataSourceElement.setConnectionAge("5000");
dataSourceElement.setTrimInterval("60000");
dataSourceElement.setTransactionIsolation("DEFAULT");
dataSourceElement.setProperty("autocommit", true);
dataSourceElement.setProperty("keepAlive", true);
dataSourceElement.setProperty("preinit", false);
dataSourceElement.setProperty("dataSource", dataSource.getName());
dataSourceElement.setProperty("dbUrl", dataSource.getDbUrl());
dataSourceElement.setProperty("driver", dataSource.getDriver());
dataSourceElement.setProperty("username", dataSource.getUsername());
dataSourceElement.setProperty("password", dataSource.getPassword());
dataSourceElement.setProperty("poolMax", dataSource.getPoolMax());
dataSourceElement.setProperty("timeout", String.valueOf(dataSource.getTimeout()));
dataSourceElement.setProperty("connectionAge", 5000);
dataSourceElement.setProperty("trimInterval", 6000);
dataSourceElement.setProperty("transactionIsolation", "DEFAULT");
return dataSourceElement;
}
}

View File

@ -96,7 +96,6 @@
this.runData.forEach(item => {
threadGroup.hashTree.push(item);
})
console.log(testPlan)
let reqObj = {id: this.reportId, testElement: testPlan};
let bodyFiles = this.getBodyUploadFiles(reqObj);
let url = "";

View File

@ -12,12 +12,12 @@
<p class="tip">{{$t('api_test.definition.request.req_param')}} </p>
<!-- HTTP 请求参数 -->
<ms-basis-parameters :request="request" :currentProject="currentProject"/>
<ms-basis-parameters :request="request" @callback="runDebug" :currentProject="currentProject" ref="requestForm"/>
<!-- HTTP 请求返回数据 -->
<p class="tip">{{$t('api_test.definition.request.res_param')}} </p>
<ms-request-result-tail :response="responseData" ref="debugResult"/>
<ms-request-result-tail :response="responseData" :currentProtocol="currentProtocol" ref="debugResult"/>
<!-- 执行组件 -->
<ms-run :debug="true" :reportId="reportId" :run-data="runData" @runRefresh="runRefresh" ref="runTest"/>
@ -64,20 +64,7 @@
}
},
created() {
switch (this.currentProtocol) {
case Request.TYPES.SQL:
this.request = createComponent("JDBCSampler");
break;
case Request.TYPES.DUBBO:
this.request = createComponent("JDBCSampler");
break;
case Request.TYPES.TCP:
this.request = createComponent("TCPSampler");
break;
default:
this.createHttp();
break;
}
},
watch: {
debugResultId() {
@ -89,14 +76,10 @@
if (e === "save_as") {
this.saveAs();
} else {
this.runDebug();
this.$refs['requestForm'].validate();
}
},
createHttp() {
let header = createComponent("HeaderManager");
this.request = createComponent("HTTPSamplerProxy");
this.request.hashTree = [header];
},
runDebug() {
this.loading = true;
this.request.name = getUUID().substring(0, 8);
@ -111,18 +94,8 @@
this.$refs.debugResult.reload();
},
saveAs() {
this.$refs['debugForm'].validate((valid) => {
if (valid) {
this.debugForm.request = JSON.stringify(this.request);
this.debugForm.userId = getCurrentUser().id;
this.debugForm.status = "Underway";
this.debugForm.protocol = this.currentProtocol;
this.$emit('saveAs', this.debugForm);
}
else {
return false;
}
})
let obj = {request: JSON.stringify(this.request)};
this.$emit('saveAs', obj);
}
}
}

View File

@ -3,7 +3,7 @@
<el-row>
<el-col :span="21" style="padding-bottom: 50px">
<div style="border:1px #DCDFE6 solid; height: 100%;border-radius: 4px ;width: 100% ;margin: 20px">
<el-form :model="request" ref="request" label-width="100px" :disabled="isReadOnly" style="margin: 20px">
<el-form :model="request" :rules="rules" ref="request" label-width="100px" :disabled="isReadOnly" style="margin: 20px">
<el-row>
<el-col :span="8">
@ -131,6 +131,10 @@
databaseConfigsOptions: [],
isReloadData: false,
activeName: "variables",
rules: {
environmentId: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
dataSource: [{required: true, message: this.$t('api_test.request.sql.dataSource'), trigger: 'change'}],
},
}
},
created() {
@ -168,12 +172,16 @@
this.isReloadData = false
})
},
validateApi() {
validate() {
if (this.currentProject === null) {
this.$error(this.$t('api_test.select_project'), 2000);
return;
}
this.$refs['basicForm'].validate();
this.$refs['request'].validate((valid) => {
if (valid) {
this.$emit('callback');
}
})
},
saveApi() {
this.basisData.method = this.basisData.protocol;

View File

@ -1,7 +1,7 @@
<template>
<div class="request-result">
<ms-request-metric :response="response"/>
<ms-response-result :response="response"/>
<ms-response-result :currentProtocol="currentProtocol" :response="response"/>
</div>
</template>
@ -14,6 +14,7 @@
components: {MsRequestMetric, MsResponseResult},
props: {
response: Object,
currentProtocol: String,
},
data() {

View File

@ -6,7 +6,8 @@
<pre>{{ response.responseResult.headers }}</pre>
</el-tab-pane>
<el-tab-pane :label="$t('api_test.definition.request.response_body')" name="body" class="pane">
<ms-code-edit :mode="mode" :read-only="true" :modes="modes" :data.sync="response.responseResult.body" ref="codeEdit"/>
<ms-sql-result-table v-if="isSqlType" :body="response.responseResult.body"/>
<ms-code-edit v-if="!isSqlType" :mode="mode" :read-only="true" :modes="modes" :data.sync="response.responseResult.body" ref="codeEdit"/>
</el-tab-pane>
<el-tab-pane label="Cookie" name="cookie" class="pane cookie">
<pre>{{response.cookies}}</pre>
@ -27,7 +28,9 @@
<el-tab-pane v-if="activeName == 'body'" :disabled="true" name="mode" class="pane cookie">
<template v-slot:label>
<ms-dropdown :commands="modes" :default-command="mode" @command="modeChange"/>
<ms-dropdown v-if="currentProtocol==='SQL'" :commands="sqlModes" :default-command="mode" @command="sqlModeChange"/>
<ms-dropdown v-else :commands="modes" :default-command="mode" @command="modeChange"/>
</template>
</el-tab-pane>
</el-tabs>
@ -39,6 +42,7 @@
import MsCodeEdit from "../MsCodeEdit";
import MsDropdown from "../../../../common/components/MsDropdown";
import {BODY_FORMAT} from "../../model/ApiTestModel";
import MsSqlResultTable from "./SqlResultTable";
export default {
name: "MsResponseResult",
@ -47,10 +51,12 @@
MsDropdown,
MsCodeEdit,
MsAssertionResults,
MsSqlResultTable
},
props: {
response: Object,
currentProtocol: String,
},
data() {
@ -58,12 +64,16 @@
isActive: true,
activeName: "headers",
modes: ['text', 'json', 'xml', 'html'],
sqlModes: ['text', 'table'],
mode: BODY_FORMAT.TEXT
}
},
methods: {
modeChange(mode) {
this.mode = mode;
},
sqlModeChange(mode) {
this.mode = mode;
}
},
mounted() {
@ -73,6 +83,11 @@
if (this.response.headers.indexOf("Content-Type: application/json") > 0) {
this.mode = BODY_FORMAT.JSON;
}
},
computed: {
isSqlType() {
return (this.currentProtocol === "SQL" && this.response.responseResult.responseCode === '200' && this.mode ==='table');
}
}
}
</script>

View File

@ -0,0 +1,121 @@
<template>
<div>
<el-table
v-for="(table, index) in tables"
:key="index"
:data="table.tableData"
border
size="mini"
highlight-current-row>
<el-table-column v-for="(title, index) in table.titles" :key="index" :label="title" min-width="150px">
<template v-slot:default="scope">
<el-popover
placement="top"
trigger="click">
<el-container>
<div>{{ scope.row[title] }}</div>
</el-container>
<span class="table-content" slot="reference">{{ scope.row[title] }}</span>
</el-popover>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: "MsSqlResultTable",
data() {
return {
tables: [],
titles: []
}
},
props: {
body: String
},
created() {
if (!this.body) {
return;
}
let rowArry = this.body.split("\n");
this.getTableData(rowArry);
if (this.tables.length > 1) {
for (let i = 0; i < this.tables.length; i++) {
if (this.tables[i].titles.length === 1 && i < this.tables.length - 1) {
this.tables[i].tableData.splice(this.tables[i].tableData.length - 1, 1);
}
}
let lastTable = this.tables[this.tables.length - 1];
if (lastTable.titles.length === 1) {
if (lastTable.tableData.length > 4) {
lastTable.tableData.splice(lastTable.tableData.length - 4, 4);
} else {
this.tables.splice(this.tables.length - 1, 1);
}
} else {
this.tables.splice(this.tables.length - 1, 1);
}
} else {
let table = this.tables[0];
table.tableData.splice(table.tableData.length - 4, 4);
}
},
methods: {
getTableData(rowArry) {
let titles;
let result = [];
for (let i = 0; i < rowArry.length; i++) {
let colArray = rowArry[i].split("\t");
if (i === 0) {
titles = colArray;
} else {
if (colArray.length != titles.length) {
//
if (colArray.length === 1 && colArray[0] === '') {
this.getTableData(rowArry.slice(i + 1));
} else {
this.getTableData(rowArry.slice(i));
}
break;
} else {
let item = {};
for (let j = 0; j < colArray.length; j++) {
item[titles[j]] = (colArray[j] ? colArray[j] : "");
}
result.push(item);
}
}
}
this.tables.splice(0, 0, {
titles: titles,
tableData: result
});
}
}
}
</script>
<style scoped>
.el-table {
margin-bottom: 20px;
}
.el-table >>> .cell {
white-space: nowrap;
}
.table-content {
cursor: pointer;
}
.el-container {
overflow:auto;
max-height: 500px;
}
</style>