Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
c4d38a2c4f
|
@ -24,7 +24,6 @@ import org.apache.jmeter.testelement.TestElement;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ -51,7 +50,7 @@ public class MsJDBCSampler extends MsTestElement {
|
||||||
@JSONField(ordinal = 28)
|
@JSONField(ordinal = 28)
|
||||||
private String dataSourceId;
|
private String dataSourceId;
|
||||||
@JSONField(ordinal = 29)
|
@JSONField(ordinal = 29)
|
||||||
private String protocol="SQL";
|
private String protocol = "SQL";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
|
||||||
|
@ -62,7 +61,8 @@ public class MsJDBCSampler extends MsTestElement {
|
||||||
this.getRefElement(this);
|
this.getRefElement(this);
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotEmpty(dataSourceId)) {
|
if (StringUtils.isNotEmpty(dataSourceId)) {
|
||||||
initDataSource();
|
this.dataSource = null;
|
||||||
|
this.initDataSource();
|
||||||
}
|
}
|
||||||
if (this.dataSource == null) {
|
if (this.dataSource == null) {
|
||||||
MSException.throwException("数据源为空无法执行");
|
MSException.throwException("数据源为空无法执行");
|
||||||
|
@ -79,14 +79,16 @@ public class MsJDBCSampler extends MsTestElement {
|
||||||
|
|
||||||
private void initDataSource() {
|
private void initDataSource() {
|
||||||
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
|
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
|
||||||
ApiTestEnvironmentWithBLOBs environment = environmentService.get(this.dataSourceId);
|
ApiTestEnvironmentWithBLOBs environment = environmentService.get(environmentId);
|
||||||
if (environment != null && environment.getConfig() != null) {
|
if (environment != null && environment.getConfig() != null) {
|
||||||
EnvironmentConfig config = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class);
|
EnvironmentConfig envConfig = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class);
|
||||||
if (CollectionUtils.isNotEmpty(config.getDatabaseConfigs())) {
|
if (CollectionUtils.isNotEmpty(envConfig.getDatabaseConfigs())) {
|
||||||
List<DatabaseConfig> databaseConfigs = config.getDatabaseConfigs().stream().filter((DatabaseConfig d) -> this.dataSourceId.equals(d.getId())).collect(Collectors.toList());
|
envConfig.getDatabaseConfigs().forEach(item -> {
|
||||||
if (CollectionUtils.isNotEmpty(databaseConfigs)) {
|
if (item.getId().equals(this.dataSourceId)) {
|
||||||
this.dataSource = databaseConfigs.get(0);
|
this.dataSource = item;
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,6 +297,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
|
||||||
requestResult.setHeaders(result.getRequestHeaders());
|
requestResult.setHeaders(result.getRequestHeaders());
|
||||||
requestResult.setRequestSize(result.getSentBytes());
|
requestResult.setRequestSize(result.getSentBytes());
|
||||||
requestResult.setStartTime(result.getStartTime());
|
requestResult.setStartTime(result.getStartTime());
|
||||||
|
requestResult.setEndTime(result.getEndTime());
|
||||||
requestResult.setTotalAssertions(result.getAssertionResults().length);
|
requestResult.setTotalAssertions(result.getAssertionResults().length);
|
||||||
requestResult.setSuccess(result.isSuccessful());
|
requestResult.setSuccess(result.isSuccessful());
|
||||||
requestResult.setError(result.getErrorCount());
|
requestResult.setError(result.getErrorCount());
|
||||||
|
|
|
@ -18,6 +18,8 @@ public class RequestResult {
|
||||||
|
|
||||||
private long startTime;
|
private long startTime;
|
||||||
|
|
||||||
|
private long endTime;
|
||||||
|
|
||||||
private int error;
|
private int error;
|
||||||
|
|
||||||
private boolean success;
|
private boolean success;
|
||||||
|
|
|
@ -163,6 +163,7 @@ public class ApiScenarioReportService {
|
||||||
String passRate = new DecimalFormat("0%").format((float) scenarioResult.getSuccess() / (scenarioResult.getSuccess() + scenarioResult.getError()));
|
String passRate = new DecimalFormat("0%").format((float) scenarioResult.getSuccess() / (scenarioResult.getSuccess() + scenarioResult.getError()));
|
||||||
testPlanApiScenario.setPassRate(passRate);
|
testPlanApiScenario.setPassRate(passRate);
|
||||||
testPlanApiScenario.setReportId(report.getId());
|
testPlanApiScenario.setReportId(report.getId());
|
||||||
|
testPlanApiScenario.setUpdateTime(System.currentTimeMillis());
|
||||||
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
|
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
|
||||||
}
|
}
|
||||||
returnReport = report;
|
returnReport = report;
|
||||||
|
@ -220,6 +221,7 @@ public class ApiScenarioReportService {
|
||||||
apiScenarioReportDetailMapper.insert(detail);
|
apiScenarioReportDetailMapper.insert(detail);
|
||||||
|
|
||||||
testPlanApiScenario.setReportId(report.getId());
|
testPlanApiScenario.setReportId(report.getId());
|
||||||
|
testPlanApiScenario.setUpdateTime(System.currentTimeMillis());
|
||||||
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
|
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
|
||||||
|
|
||||||
lastReport = report;
|
lastReport = report;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 387ca56312b62ae5edb3d7f34afa08946d86d621
|
Subproject commit a641c1331e1813b5294a1d0e380b8682a78754e1
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
<ms-main-container>
|
<ms-main-container>
|
||||||
<el-tabs v-model="activeName" @tab-click="addTab" @tab-remove="removeTab">
|
<el-tabs v-model="activeName" @tab-click="addTab" @tab-remove="removeTab">
|
||||||
<el-tab-pane name="default" :label="$t('api_test.automation.scenario_test')">
|
<el-tab-pane name="default" :label="$t('api_test.automation.scenario_list')">
|
||||||
<ms-api-scenario-list
|
<ms-api-scenario-list
|
||||||
:module-tree="nodeTree"
|
:module-tree="nodeTree"
|
||||||
:module-options="moduleOptions"
|
:module-options="moduleOptions"
|
||||||
|
|
|
@ -118,6 +118,7 @@
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
this.getFails();
|
this.getFails();
|
||||||
|
this.computeTotalTime();
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
} else {
|
} else {
|
||||||
setTimeout(this.getReport, 2000)
|
setTimeout(this.getReport, 2000)
|
||||||
|
@ -146,12 +147,30 @@
|
||||||
failScenario.requestResults.push(failRequest);
|
failScenario.requestResults.push(failRequest);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computeTotalTime() {
|
||||||
|
if (this.content.scenarios) {
|
||||||
|
let startTime = 99991611737506593;
|
||||||
|
let endTime = 0;
|
||||||
|
this.content.scenarios.forEach((scenario) => {
|
||||||
|
scenario.requestResults.forEach((request) => {
|
||||||
|
if (request.startTime && Number(request.startTime) < startTime) {
|
||||||
|
startTime = request.startTime;
|
||||||
|
}
|
||||||
|
if (request.endTime && Number(request.endTime) > endTime) {
|
||||||
|
endTime = request.endTime;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
if (startTime < endTime) {
|
||||||
|
this.totalTime = endTime - startTime + 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
requestResult(requestResult) {
|
requestResult(requestResult) {
|
||||||
this.active();
|
this.active();
|
||||||
this.isRequestResult = false;
|
this.isRequestResult = false;
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="request-result">
|
<div class="request-result">
|
||||||
<div>
|
<div>
|
||||||
<el-row :gutter="10" type="flex" align="middle" class="info">
|
<el-row :gutter="8" type="flex" align="middle" class="info">
|
||||||
<el-col :span="2">
|
<el-col :span="2">
|
||||||
<div class="method">
|
<div class="method">
|
||||||
{{request.method}}
|
{{request.method}}
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="8">
|
||||||
<el-tooltip effect="dark" :content="request.url" placement="bottom" :open-delay="800">
|
<el-tooltip effect="dark" :content="request.url" placement="bottom" :open-delay="800">
|
||||||
<div class="url">{{request.url}}</div>
|
<div class="url">{{request.url}}</div>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="url"> {{$t('api_report.start_time')}}:{{request.startTime | timestampFormatDate(true) }}
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
<el-collapse-transition>
|
<el-collapse-transition>
|
||||||
|
@ -19,7 +23,7 @@
|
||||||
<el-tabs v-model="activeName" v-show="isActive" v-if="hasSub">
|
<el-tabs v-model="activeName" v-show="isActive" v-if="hasSub">
|
||||||
<el-tab-pane :label="$t('api_report.sub_result')" name="sub">
|
<el-tab-pane :label="$t('api_report.sub_result')" name="sub">
|
||||||
<ms-request-sub-result class="sub-result" v-for="(sub, index) in request.subRequestResults"
|
<ms-request-sub-result class="sub-result" v-for="(sub, index) in request.subRequestResults"
|
||||||
:key="index" :indexNumber="index" :request="sub"/>
|
:key="index" :indexNumber="index" :request="sub"/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('api_report.request_result')" name="result">
|
<el-tab-pane :label="$t('api_report.request_result')" name="result">
|
||||||
<ms-response-text :request-type="requestType" :response="request.responseResult" :request="request"/>
|
<ms-response-text :request-type="requestType" :response="request.responseResult" :request="request"/>
|
||||||
|
@ -43,7 +47,7 @@
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsRequestResultTail",
|
name: "MsRequestResultTail",
|
||||||
components: {MsResponseText, MsRequestText, MsAssertionResults, MsRequestMetric, MsRequestResult,MsRequestSubResult},
|
components: {MsResponseText, MsRequestText, MsAssertionResults, MsRequestMetric, MsRequestResult, MsRequestSubResult},
|
||||||
props: {
|
props: {
|
||||||
request: Object,
|
request: Object,
|
||||||
scenarioName: String,
|
scenarioName: String,
|
||||||
|
|
|
@ -35,8 +35,8 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<el-button class="ht-btn-add" size="mini" p="$t('commons.add')" icon="el-icon-circle-plus-outline" @click="add">添加
|
<el-button class="ht-btn-add" size="mini" p="$t('commons.add')" icon="el-icon-circle-plus-outline" @click="add">{{$t("commons.add")}}</el-button>
|
||||||
</el-button>
|
<el-button class="ht-btn-add" size="mini" p="$t('commons.add')" icon="el-icon-files" @click="copy">{{$t("commons.copy")}}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -68,6 +68,16 @@
|
||||||
this.$emit('change', this.hostTable);
|
this.$emit('change', this.hostTable);
|
||||||
},
|
},
|
||||||
add: function (r) {
|
add: function (r) {
|
||||||
|
let row = {
|
||||||
|
ip: '',
|
||||||
|
domain: '',
|
||||||
|
status: 'edit',
|
||||||
|
annotation: '',
|
||||||
|
uuid: this.uuid(),
|
||||||
|
}
|
||||||
|
this.hostTable.push(row);
|
||||||
|
},
|
||||||
|
copy: function (r) {
|
||||||
let row = {
|
let row = {
|
||||||
ip: '',
|
ip: '',
|
||||||
domain: '',
|
domain: '',
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<span v-if="triggerMode === 'SCHEDULE'">{{$t('commons.trigger_mode.schedule')}}</span>
|
<span v-if="triggerMode === 'SCHEDULE'">{{$t('commons.trigger_mode.schedule')}}</span>
|
||||||
<span v-if="triggerMode === 'TEST_PLAN_SCHEDULE'">{{$t('commons.trigger_mode.schedule')}}</span>
|
<span v-if="triggerMode === 'TEST_PLAN_SCHEDULE'">{{$t('commons.trigger_mode.schedule')}}</span>
|
||||||
<span v-if="triggerMode === 'API'">{{$t('commons.trigger_mode.api')}}</span>
|
<span v-if="triggerMode === 'API'">{{$t('commons.trigger_mode.api')}}</span>
|
||||||
<span v-if="triggerMode === 'CASE'">用例触发</span>
|
<span v-if="triggerMode === 'CASE'">{{$t('commons.trigger_mode.case')}}</span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,7 @@ export default {
|
||||||
{text: this.$t('commons.trigger_mode.manual'), value: 'MANUAL'},
|
{text: this.$t('commons.trigger_mode.manual'), value: 'MANUAL'},
|
||||||
{text: this.$t('commons.trigger_mode.schedule'), value: 'SCHEDULE'},
|
{text: this.$t('commons.trigger_mode.schedule'), value: 'SCHEDULE'},
|
||||||
{text: this.$t('commons.trigger_mode.api'), value: 'API'},
|
{text: this.$t('commons.trigger_mode.api'), value: 'API'},
|
||||||
|
{text: this.$t('commons.trigger_mode.case'), value: 'CASE'},
|
||||||
],
|
],
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,14 +31,14 @@
|
||||||
@select="handleSelect"
|
@select="handleSelect"
|
||||||
@cell-mouse-enter="showPopover"
|
@cell-mouse-enter="showPopover"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
class="test-content adjust-table ms-select-all"
|
class="test-content adjust-table ms-select-all-fixed"
|
||||||
ref="table" @row-click="handleEdit">
|
ref="table" @row-click="handleEdit">
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
width="50"
|
width="50"
|
||||||
type="selection"/>
|
type="selection"/>
|
||||||
|
|
||||||
<ms-table-select-all
|
<ms-table-header-select-popover v-show="total>0"
|
||||||
:page-size="pageSize > total ? total : pageSize"
|
:page-size="pageSize > total ? total : pageSize"
|
||||||
:total="total"
|
:total="total"
|
||||||
@selectPageAll="isSelectDataAll(false)"
|
@selectPageAll="isSelectDataAll(false)"
|
||||||
|
@ -78,6 +78,7 @@
|
||||||
prop="priority"
|
prop="priority"
|
||||||
:filters="priorityFilters"
|
:filters="priorityFilters"
|
||||||
column-key="priority"
|
column-key="priority"
|
||||||
|
min-width="100px"
|
||||||
:label="$t('test_track.case.priority')"
|
:label="$t('test_track.case.priority')"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
@ -98,6 +99,7 @@
|
||||||
prop="method"
|
prop="method"
|
||||||
column-key="method"
|
column-key="method"
|
||||||
:filters="methodFilters"
|
:filters="methodFilters"
|
||||||
|
min-width="100px"
|
||||||
:label="$t('test_track.case.method')"
|
:label="$t('test_track.case.method')"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
|
@ -108,6 +110,7 @@
|
||||||
<el-table-column
|
<el-table-column
|
||||||
:filters="statusFilters"
|
:filters="statusFilters"
|
||||||
column-key="status"
|
column-key="status"
|
||||||
|
min-width="100px"
|
||||||
:label="$t('test_track.case.status')">
|
:label="$t('test_track.case.status')">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<span class="el-dropdown-link">
|
<span class="el-dropdown-link">
|
||||||
|
@ -127,6 +130,7 @@
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="nodePath"
|
prop="nodePath"
|
||||||
:label="$t('test_track.case.module')"
|
:label="$t('test_track.case.module')"
|
||||||
|
min-width="150px"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
|
@ -134,12 +138,13 @@
|
||||||
prop="updateTime"
|
prop="updateTime"
|
||||||
sortable="custom"
|
sortable="custom"
|
||||||
:label="$t('commons.update_time')"
|
:label="$t('commons.update_time')"
|
||||||
|
min-width="150px"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip>
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column fixed="right"
|
||||||
:label="$t('commons.operating')" min-width="150">
|
:label="$t('commons.operating')" min-width="150">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<ms-table-operator :is-tester-permission="true" @editClick="handleEdit(scope.row)"
|
<ms-table-operator :is-tester-permission="true" @editClick="handleEdit(scope.row)"
|
||||||
|
@ -169,6 +174,7 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import MsCreateBox from '../../../settings/CreateBox';
|
import MsCreateBox from '../../../settings/CreateBox';
|
||||||
|
import MsTableHeaderSelectPopover from "@/business/components/common/components/table/MsTableHeaderSelectPopover";
|
||||||
import TestCaseImport from '../components/TestCaseImport';
|
import TestCaseImport from '../components/TestCaseImport';
|
||||||
import TestCaseExport from '../components/TestCaseExport';
|
import TestCaseExport from '../components/TestCaseExport';
|
||||||
import MsTablePagination from '../../../../components/common/pagination/TablePagination';
|
import MsTablePagination from '../../../../components/common/pagination/TablePagination';
|
||||||
|
@ -191,7 +197,6 @@ import TestCaseDetail from "./TestCaseDetail";
|
||||||
import ReviewStatus from "@/business/components/track/case/components/ReviewStatus";
|
import ReviewStatus from "@/business/components/track/case/components/ReviewStatus";
|
||||||
import {getCurrentProjectID} from "../../../../../common/js/utils";
|
import {getCurrentProjectID} from "../../../../../common/js/utils";
|
||||||
import MsTag from "@/business/components/common/components/MsTag";
|
import MsTag from "@/business/components/common/components/MsTag";
|
||||||
import MsTableSelectAll from "../../../common/components/table/MsTableSelectAll";
|
|
||||||
import {_handleSelect, _handleSelectAll} from "../../../../../common/js/tableUtils";
|
import {_handleSelect, _handleSelectAll} from "../../../../../common/js/tableUtils";
|
||||||
import BatchMove from "./BatchMove";
|
import BatchMove from "./BatchMove";
|
||||||
|
|
||||||
|
@ -199,7 +204,7 @@ export default {
|
||||||
name: "TestCaseList",
|
name: "TestCaseList",
|
||||||
components: {
|
components: {
|
||||||
BatchMove,
|
BatchMove,
|
||||||
MsTableSelectAll,
|
MsTableHeaderSelectPopover,
|
||||||
MsTableButton,
|
MsTableButton,
|
||||||
MsTableOperatorButton,
|
MsTableOperatorButton,
|
||||||
MsTableOperator,
|
MsTableOperator,
|
||||||
|
|
|
@ -603,6 +603,7 @@ export default {
|
||||||
customize_req: "Customize req",
|
customize_req: "Customize req",
|
||||||
reference_info: "Reference info",
|
reference_info: "Reference info",
|
||||||
scenario_test: "Scenario test",
|
scenario_test: "Scenario test",
|
||||||
|
scenario_list: "Scenario List",
|
||||||
add_scenario: "Add scenario",
|
add_scenario: "Add scenario",
|
||||||
scenario_name: "Scenario name",
|
scenario_name: "Scenario name",
|
||||||
case_level: "Case level",
|
case_level: "Case level",
|
||||||
|
|
|
@ -604,6 +604,7 @@ export default {
|
||||||
customize_req: "自定义请求",
|
customize_req: "自定义请求",
|
||||||
reference_info: "请选择接口或用例",
|
reference_info: "请选择接口或用例",
|
||||||
scenario_test: "场景",
|
scenario_test: "场景",
|
||||||
|
scenario_list: "场景列表",
|
||||||
add_scenario: "创建场景",
|
add_scenario: "创建场景",
|
||||||
scenario_name: "场景名称",
|
scenario_name: "场景名称",
|
||||||
case_level: "用例等级",
|
case_level: "用例等级",
|
||||||
|
|
|
@ -603,6 +603,7 @@ export default {
|
||||||
customize_req: "自定義請求",
|
customize_req: "自定義請求",
|
||||||
reference_info: "請選擇接口或用例",
|
reference_info: "請選擇接口或用例",
|
||||||
scenario_test: "場景",
|
scenario_test: "場景",
|
||||||
|
scenario_list: "場景列表",
|
||||||
add_scenario: "創建場景",
|
add_scenario: "創建場景",
|
||||||
scenario_name: "場景名稱",
|
scenario_name: "場景名稱",
|
||||||
case_level: "用例等級",
|
case_level: "用例等級",
|
||||||
|
|
Loading…
Reference in New Issue