Selaa lähdekoodia

feat: 添加黑盒测试tab

zhaoxingrui 5 vuotta sitten
vanhempi
commit
a6f8102a1a
4 muutettua tiedostoa jossa 411 lisäystä ja 1 poistoa
  1. 37 0
      src/api/functest.ts
  2. 2 0
      src/api/index.ts
  3. 1 0
      src/api/prefix.ts
  4. 371 1
      src/views/Project/APITest.vue

+ 37 - 0
src/api/functest.ts

@@ -0,0 +1,37 @@
+import axios from '@/utils/axios';
+
+import { FUNCTEST_PREFIX } from './prefix';
+
+export const getTestCases = (projectId: number) => axios.get(`${FUNCTEST_PREFIX}`, {
+  params: {
+    projectId,
+  },
+});
+
+export const createTestCase = (projectId: number, title: string) => axios.post(`${FUNCTEST_PREFIX}?projectId=${projectId}&title=${title}`);
+
+export const deleteTestCase = (testCaseId: number) => axios.delete(`${FUNCTEST_PREFIX}?testCaseId=${testCaseId}`);
+
+export const updateTestCase = (testCaseId: number, title: string) => axios.put(
+  `${FUNCTEST_PREFIX}?testCaseId=${testCaseId}&title=${title}`,
+);
+
+export const finishTestCase = (testCaseId: number) => axios.put(`${FUNCTEST_PREFIX}/finish?testCaseId=${testCaseId}`);
+
+export const reopenTestCase = (testCaseId: number) => axios.put(`${FUNCTEST_PREFIX}/reopen?testCaseId=${testCaseId}`);
+
+export const getTestCaseSteps = (testCaseId: number) => axios.get(`${FUNCTEST_PREFIX}/steps?testCaseId=${testCaseId}`);
+
+export const createTestCaseStep = (testCaseId: number) => axios.post(`${FUNCTEST_PREFIX}/steps?testCaseId=${testCaseId}`);
+
+export const updateTestCaseStep = (testStepId: number, description: string) => axios.put(
+  `${FUNCTEST_PREFIX}/steps?testStepId=${testStepId}&description=${description}`,
+);
+
+export const deleteTestCaseStep = (testStepId: number) => axios.delete(`${FUNCTEST_PREFIX}/steps?testStepId=${testStepId}`);
+
+export const getLatestRecord = (projectId: number) => axios.get(`${FUNCTEST_PREFIX}/record/latest`, {
+  params: {
+    projectId,
+  },
+});

+ 2 - 0
src/api/index.ts

@@ -3,6 +3,7 @@ import * as ProjectAPI from './project';
 import * as RequirementAPI from './tree';
 import * as PipelineAPI from './pipeline';
 import * as APITestAPI from './apitest';
+import * as FuncTestAPI from './functest';
 
 export {
   UserAPI,
@@ -10,4 +11,5 @@ export {
   RequirementAPI,
   PipelineAPI,
   APITestAPI,
+  FuncTestAPI,
 };

+ 1 - 0
src/api/prefix.ts

@@ -4,3 +4,4 @@ export const USER_PREFIX = '/users';
 export const TREE_PREFIX = '/tree';
 export const PROJECT_PREFIX = '/project';
 export const APITEST_PREFIX = '/test';
+export const FUNCTEST_PREFIX = '/test_cases';

+ 371 - 1
src/views/Project/APITest.vue

@@ -306,12 +306,239 @@
         </template>
       </ElDrawer>
     </ElTabPane>
+    <ElTabPane label="黑盒测试" name="testCases">
+      <ElTable :data="testcases" width="100%">
+        <ElTableColumn
+          prop="id"
+          label="ID"
+          align="center"
+          width="60">
+        </ElTableColumn>
+        <ElTableColumn
+          prop="title"
+          label="title"
+          align="center">
+        </ElTableColumn>
+        <ElTableColumn
+          prop="pass"
+          label="执行状态"
+          align="center"
+          width="100"
+          :filters="[{ text: '进行中', value: false }, { text: '已完成', value: true }]"
+          :filter-method="(value, row) => {
+            return row.pass === value;
+          }"
+          filter-placement="bottom-end">
+          <template #default="scope">
+            <template v-if="scope.row.pass === false">
+              <ElTag>进行中<i class="el-icon-loading"></i></ElTag>
+            </template>
+            <template v-else-if="scope.row.pass === true">
+              <ElTag type="success">已完成</ElTag>
+            </template>
+            <template v-else>
+              <ElTag type="warning">未知状态</ElTag>
+            </template>
+          </template>
+        </ElTableColumn>
+        <ElTableColumn
+          label="详情"
+          align="center">
+          <template #default="scope">
+            <ElButton
+              @click="handleTestCasesClick('latest', scope.row.id)"
+              type="text"
+              size="small">部署的历史记录</ElButton>
+            <ElButton
+              @click="handleTestCasesClick('steps', scope.row.id)"
+              type="text"
+              size="small">测试用例步骤列表</ElButton>
+          </template>
+        </ElTableColumn>
+        <ElTableColumn
+          align="center">
+          <template #header>
+            <span>操作</span>
+            <ElButton @click="handleTestCasesClick('create')" type="text" class="add-button">新建</ElButton>
+          </template>
+          <template #default="scope">
+            <ElButton v-if="scope.row.pass === false" @click="handleTestCasesClick('finish', scope.row.id)" type="text" size="small">
+              完成测试
+            </ElButton>
+            <ElButton v-else @click="handleTestCasesClick('finish', scope.row.id)" type="text" size="small" disabled>完成测试</ElButton>
+            <ElButton v-if="scope.row.pass === true" @click="handleTestCasesClick('reopen', scope.row.id)" type="text" size="small">
+              重新开放测试
+            </ElButton>
+            <ElButton v-else @click="handleTestCasesClick('reopen', scope.row.id)" type="text" size="small" disabled>重新开放测试</ElButton>
+            <ElButton @click="handleTestCasesClick('edit', scope.row.id)" type="text" size="small">编辑</ElButton>
+            <ElButton @click="handleTestCasesClick('delete', scope.row.id)" type="text" size="small">删除</ElButton>
+          </template>
+        </ElTableColumn>
+      </ElTable>
+      <!-- 新建测试用例 -->
+      <el-dialog
+        v-model="showTestCaseCreateModel"
+        width="600px"
+        :before-close="(done) => {$refs['createTestCaseForm'].resetFields();done();}"
+        destroy-on-close>
+        <template #title>创建测试用例</template>
+        <el-form
+          :model="createTestCaseForm"
+          ref="createTestCaseForm"
+          label-position="right"
+          label-width="60px"
+          label-suffix=":"
+          class="create-APITest-form">
+          <el-form-item label="title" prop="title">
+            <el-input
+              v-model="createTestCaseForm.title"
+              type="textarea"
+              :rows="5"
+              placeholder="请输入测试用例的标题"></el-input>
+          </el-form-item>
+        </el-form>
+        <template #footer>
+          <span class="dialog-footer">
+            <el-button type="primary" @click="handleTestCaseCreateConfirm">确 定</el-button>
+          </span>
+        </template>
+      </el-dialog>
+      <!-- 测试用例步骤详情 -->
+      <ElDrawer
+        v-model="stepsDrawer"
+        :size="650">
+        <template #title>
+          <el-row class="entry-row">
+            <el-col :span="3">
+              <div class="node-type">测试用例</div>
+            </el-col>
+            <el-col :span="2">
+              <template class="entry-row">
+                <span>#{{detailTestCaseInfo.id}}</span>
+              </template>
+            </el-col>
+            <el-col :span="6">
+              <div>
+                <ElButton @click="handleSteps('create', detailTestCaseInfo.id, 0)" type="text" class="add-button">新建测试用例步骤</ElButton>
+              </div>
+            </el-col>
+          </el-row>
+        </template>
+        <template #default>
+          <el-row type="flex" justify="center">
+            <el-col :span="20">
+              <el-row class="entry-row" style="margin-top: 15px; margin-bottom: 30px">
+                <el-col :span="2">
+                  <h4>title: </h4>
+                </el-col>
+                <el-col :span="18">
+                  <div>{{detailTestCaseInfo.title}}</div>
+                </el-col>
+              </el-row>
+              <el-tabs v-model="stepsTab">
+                <el-tab-pane label="测试用例步骤" name="steps">
+                  <el-table :data="detailStepsInfo" width="100%">
+                    <el-table-column
+                      prop="id"
+                      label="ID"
+                      align="center"
+                      width="60">
+                    </el-table-column>
+                    <el-table-column
+                      prop="description"
+                      label="描述"
+                      align="center">
+                    </el-table-column>
+                    <el-table-column
+                      align="center">
+                      <template #header>
+                        <span>操作</span>
+                      </template>
+                      <template #default="scope">
+                        <ElButton @click="handleSteps('update', scope.row.testCaseId, scope.row.id)" type="text" size="small">更新</ElButton>
+                        <ElButton @click="handleSteps('delete', scope.row.testCaseId, scope.row.id)" type="text" size="small">删除</ElButton>
+                      </template>
+                    </el-table-column>
+                  </el-table>
+                </el-tab-pane>
+              </el-tabs>
+            </el-col>
+          </el-row>
+        </template>
+      </ElDrawer>
+      <!-- 修改测试用例步骤 -->
+      <el-dialog
+        v-model="showUpdateStepModel"
+        width="600px"
+        :before-close="(done) => {$refs['updateStepForm'].resetFields();done();}"
+        destroy-on-close>
+        <template #title>修改测试用例步骤</template>
+        <el-form
+          :model="updateStepForm"
+          ref="updateStepForm"
+          label-position="right"
+          label-width="100px"
+          label-suffix=":">
+          <el-form-item label="id" prop="id">
+            <el-input
+              v-model="updateStepForm.id"
+              disabled>
+            </el-input>
+          </el-form-item>
+          <el-form-item label="description" prop="description">
+            <el-input
+              v-model="updateStepForm.description"
+              type="textarea"
+              :rows="4">
+            </el-input>
+          </el-form-item>
+        </el-form>
+        <template #footer>
+          <span class="dialog-footer">
+            <el-button type="primary" @click="handleStepUpdateConfirm">确 定</el-button>
+          </span>
+        </template>
+      </el-dialog>
+      <!-- 修改测试用例title -->
+      <el-dialog
+        v-model="showEditTestCaseModel"
+        width="600px"
+        :before-close="(done) => {$refs['detailTestCaseInfo'].resetFields();done();}"
+        destroy-on-close>
+        <template #title>编辑测试用例标题</template>
+        <el-form
+          :model="detailTestCaseInfo"
+          ref="detailTestCaseInfo"
+          label-position="right"
+          label-width="100px"
+          label-suffix=":">
+          <el-form-item label="id" prop="id">
+            <el-input
+              v-model="detailTestCaseInfo.id"
+              disabled>
+            </el-input>
+          </el-form-item>
+          <el-form-item label="title" prop="title">
+            <el-input
+              v-model="detailTestCaseInfo.title"
+              type="textarea"
+              :rows="4">
+            </el-input>
+          </el-form-item>
+        </el-form>
+        <template #footer>
+          <span class="dialog-footer">
+            <el-button type="primary" @click="handleTestCaseEditConfirm">确 定</el-button>
+          </span>
+        </template>
+      </el-dialog>
+    </ElTabPane>
   </ElTabs>
 </template>
 
 <script>
 import vueJsonEditor from 'vue-json-editor';
-import { APITestAPI } from '@/api';
+import { APITestAPI, FuncTestAPI } from '@/api';
 import { ElMessage } from 'element-plus';
 import * as echarts from 'echarts';
 
@@ -343,10 +570,24 @@ export default {
       latestResultInfo: {},
       qps: 0,
       timer: null,
+      testcases: [],
+      showTestCaseCreateModel: false,
+      createTestCaseForm: {
+        projectId: -1,
+        title: '',
+      },
+      stepsDrawer: false,
+      detailTestCaseInfo: [],
+      stepsTab: 'steps',
+      detailStepsInfo: {},
+      showUpdateStepModel: false,
+      updateStepForm: {},
+      showEditTestCaseModel: false,
     };
   },
   async mounted() {
     this.apitests = await APITestAPI.getAPITestInfosByProjectId(this.$store.state.workspace.currentProjectId);
+    this.testcases = await FuncTestAPI.getTestCases(this.$store.state.workspace.currentProjectId);
   },
   methods: {
     async handleClick(action, id) {
@@ -531,6 +772,135 @@ export default {
       };
       chart2.setOption(option2);
     },
+    async handleTestCasesClick(action, id) {
+      switch (action) {
+        case 'create': {
+          this.showTestCaseCreateModel = true;
+          break;
+        }
+        case 'update': {
+          break;
+        }
+        case 'finish': {
+          await FuncTestAPI.finishTestCase(id);
+          this.testcases = await FuncTestAPI.getTestCases(this.$store.state.workspace.currentProjectId);
+          break;
+        }
+        case 'reopen': {
+          await FuncTestAPI.reopenTestCase(id);
+          this.testcases = await FuncTestAPI.getTestCases(this.$store.state.workspace.currentProjectId);
+          break;
+        }
+        case 'edit': {
+          this.testcases.forEach((item) => {
+            if (item.id === id) {
+              this.detailTestCaseInfo = item;
+            }
+          });
+          this.showEditTestCaseModel = true;
+          break;
+        }
+        case 'delete': {
+          await FuncTestAPI.deleteTestCase(id);
+          ElMessage.success({
+            message: '删除成功!',
+            type: 'success',
+          });
+          this.testcases = await FuncTestAPI.getTestCases(this.$store.state.workspace.currentProjectId);
+          break;
+        }
+        case 'steps': {
+          this.testcases.forEach((item) => {
+            if (item.id === id) {
+              this.detailTestCaseInfo = item;
+            }
+          });
+          this.detailStepsInfo = await FuncTestAPI.getTestCaseSteps(id);
+          this.stepsDrawer = true;
+          break;
+        }
+        default: {
+          console.warn('Unknown type of action.');
+        }
+      }
+    },
+    async handleTestCaseCreateConfirm() {
+      this.$refs.createTestCaseForm.validate(async (valid) => {
+        if (valid) {
+          this.createTestCaseForm.projectId = this.$store.state.workspace.currentProjectId;
+          await FuncTestAPI.createTestCase(this.createTestCaseForm.projectId, this.createTestCaseForm.title);
+          this.testcases = await FuncTestAPI.getTestCases(this.$store.state.workspace.currentProjectId);
+          this.$refs.createTestCaseForm.resetFields();
+          this.showTestCaseCreateModel = false;
+          ElMessage.success({
+            message: '创建成功!',
+            type: 'success',
+          });
+        }
+      });
+    },
+    async handleSteps(action, caseId, stepId) {
+      switch (action) {
+        case 'create': {
+          await FuncTestAPI.createTestCaseStep(caseId);
+          ElMessage.success({
+            message: '创建成功!',
+            type: 'success',
+          });
+          this.detailStepsInfo = await FuncTestAPI.getTestCaseSteps(caseId);
+          break;
+        }
+        case 'delete': {
+          await FuncTestAPI.deleteTestCaseStep(stepId);
+          ElMessage.success({
+            message: '删除成功!',
+            type: 'success',
+          });
+          this.detailStepsInfo = await FuncTestAPI.getTestCaseSteps(caseId);
+          break;
+        }
+        case 'update': {
+          this.showUpdateStepModel = true;
+          this.detailStepsInfo.forEach((item) => {
+            if (item.id === stepId) {
+              this.updateStepForm = item;
+            }
+          });
+          break;
+        }
+        default: {
+          console.warn('Unknown type of action.');
+        }
+      }
+    },
+    async handleStepUpdateConfirm() {
+      this.$refs.updateStepForm.validate(async (valid) => {
+        if (valid) {
+          await FuncTestAPI.updateTestCaseStep(this.updateStepForm.id, this.updateStepForm.description);
+          this.detailStepsInfo = await FuncTestAPI.getTestCaseSteps(this.updateStepForm.testCaseId);
+          this.$refs.updateStepForm.resetFields();
+          this.showUpdateStepModel = false;
+          ElMessage.success({
+            message: '修改成功!',
+            type: 'success',
+          });
+        }
+      });
+    },
+    async handleTestCaseEditConfirm() {
+      this.$refs.detailTestCaseInfo.validate(async (valid) => {
+        if (valid) {
+          await FuncTestAPI.updateTestCase(this.detailTestCaseInfo.id, this.detailTestCaseInfo.title);
+          this.testcases = await FuncTestAPI.getTestCases(this.$store.state.workspace.currentProjectId);
+          this.$refs.detailTestCaseInfo.resetFields();
+          this.showEditTestCaseModel = false;
+          ElMessage.success({
+            message: '修改成功!',
+            type: 'success',
+          });
+        }
+      });
+    },
   },
 };
 </script>