接口自动化测试系列-接入测试平台

测试平台目录

测试平台自建源码

后台核心代码

python 复制代码
def add_api(kwags):
    """插入api数据"""
    try:
        join_info = CaseApi(name=kwags.get("name"), httpType=kwags.get("httpType"),
                            headers=kwags.get("headers") if kwags.get("headers") else '{}',
                            requestType=kwags.get("requestType"), apiAddress=kwags.get("apiAddress"),
                            requestParameterType=kwags.get("requestParameterType"),
                            project_id=filter_project(project_name=kwags.get("project"))[0].get("id"),
                            params=kwags.get("body") if kwags.get("body") else '{}',
                            create_time=kwags.get("create_time"), responseData='{}',
                            create_user=kwags.get("create_user"), update_time=kwags.get("update_time"),
                            update_user=kwags.get("update_user"))
        session.add(join_info)
        session.commit()
        return {"msg": "新增接口成功"}
    except Exception as e:
        logger.error(f"新增接口时失败:{e}")
        return {"msg": f"新增接口失败:{e}"}


def filter_api(kwags):
    """查询api列表数据"""
    try:
        logger.info("开始查询api列表")
        result = []
        # 获取页数
        page = kwags.get('page') if kwags.get('page') else 1
        # 获取条数
        limit = kwags.get('limit') if kwags.get('limit') else 20
        # 排序
        name = kwags.get('name')
        data_header = "session.query(CaseApi).filter_by"
        data_filter = '(name=name)' if name else '()'
        data_sort = f".order_by(CaseApi.id.asc()).all()" if kwags.get(
            'sort') == '+id' else f".order_by(CaseApi.id.desc()).all()"
        data = data_header + data_filter + data_sort
        data = eval(data)[(page - 1) * limit:limit]
        for i in data:
            case_item = i.to_json()
            case_item["project"] = filter_project(i.to_json()["project"])[0].get("project_name")
            result.append(case_item)
        return result
    except Exception as e:
        logger.error(f"查询api列表失败:{e}")

部分前端代码样例

python 复制代码
<template>
  <div class="app-container">
    <div class="filter-container">
      <el-row class="filter-row">
        <div class="filter-col">
          <el-col span="5">
            <label class="radio-label" style="font-style: normal;font-weight: normal">测试用例名称 </label>
            <el-input v-model="listQuery.name" style="width: 200px;" class="filter-item" clearable @keyup.enter.native="handleFilter" />
          </el-col>
          <el-col span="2">
            <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
              Search
            </el-button>
          </el-col>
          <el-col span="2">
            <el-button v-waves class="filter-item" type="primary" icon="el-icon-circle-plus-outline" @click="add_case">
              新增用例
            </el-button>
          </el-col>
        </div>
      </el-row>
    </div>

    <el-table
      :key="tableKey"
      :data="list"
      :header-cell-style="getRowClass"
      border
      fit
      highlight-current-row
      style="width: 100%;margin-top:30px"
      @sort-change="sortChange"
    >
      <el-table-column type="expand">
        <template slot-scope="props">
          <el-form label-position="left" inline class="table-expand">
            <el-form-item label="请求类型:">
              <span>{{ props.row.httpType }}</span>
            </el-form-item>
            <el-form-item label="接口地址:">
              <span>{{ props.row.apiAddress }}</span>
            </el-form-item>
            <el-form-item label="传参类型:">
              <span>{{ props.row.requestParameterType }}</span>
            </el-form-item>
            <el-form-item label="请求header:">
              <span>{{ props.row.headers }}</span>
            </el-form-item>
            <el-form-item label="参数:">
              <span>{{ props.row.body }}</span>
            </el-form-item>
            <el-form-item label="响应code:">
              <span>{{ props.row.httpCode }}</span>
            </el-form-item>
            <el-form-item label="响应data:">
              <span>{{ props.row.responseData }}</span>
            </el-form-item>
          </el-form></template></el-table-column>
      <el-table-column label="ID" prop="id" sortable="custom" align="center" width="100" :class-name="getSortClass('id')">
        <template slot-scope="{row}">
          <span>{{ row.id }}</span>
        </template>
      </el-table-column>
      <el-table-column label="测试用例名称" width="300px" align="center">
        <template slot-scope="{row}">
          <span>{{ row.name }}</span>
          <i class="el-icon-document-copy" style="margin-left:10%" @click="copyValue(row.name)" />
        </template>
      </el-table-column>
      <el-table-column label="请求方式" width="110px" align="center">
        <template slot-scope="{row}">
          <span>{{ row.requestType }}</span>
        </template>
      </el-table-column>
      <el-table-column label="所属项目" width="300px" align="center">
        <template slot-scope="{row}">
          <span>{{ row.project }}</span>
        </template>
      </el-table-column>
      <el-table-column label="创建人" width="280px" align="center">
        <template slot-scope="{row}">
          <span>{{ row.create_user }}</span>
        </template>
      </el-table-column>
      <el-table-column label="响应" width="280px" align="center">
        <template slot-scope="{row}">
          <el-popover
            placement="top-start"
            width="300"
            trigger="hover"
            :disabled="row.responseData.length <= 80"
          >
            <span>{{ row.responseData }}</span>
            <span v-if="row.responseData.length <= 80" slot="reference">{{ row.responseData }}</span>
            <span v-if="row.responseData.length > 80" slot="reference">{{ row.responseData.substr(0, 80) + "..." }}</span>
          </el-popover>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="280px" align="center" fixed="right">
        <template slot-scope="scope">
          <el-button type="success" size="small" icon="el-icon-video-play" :loading="loadingstatus" @click="runCase(scope.$index, scope.row)">运行</el-button>
          <el-button type="primary" size="small" @click="formEditDialog(scope.$index, scope.row)">编辑</el-button>
          <el-dialog :visible.sync="dialogFormVisible" :modal-append-to-body="false">
            <span slot="title" :model="editForm" style="font-weight:bold;">编辑用例:{{ editForm.id }}_{{ editForm.name }}</span>
            <el-form class="form" label-width="auto" :model="editForm" :rules="rules">
              <el-form-item label="用例名称:" prop="name" :rules="rules.name">
                <el-input v-model="editForm.name" />
              </el-form-item>
              <el-row>
                <el-col span="6">
                  <el-form-item label="http类型:">
                    <el-select v-model="editForm.httpType" placeholder="请选择http类型">
                      <el-option label="http" value="http" />
                      <el-option label="https" value="https" />
                    </el-select>
                  </el-form-item>
                </el-col>
                <el-col span="6">
                  <el-form-item label="请求方法:">
                    <el-select v-model="editForm.requestType" placeholder="请选择请求方法">
                      <el-option label="get" value="get" />
                      <el-option label="post" value="post" />
                      <el-option label="put" value="put" />
                      <el-option label="delete" value="delete" />
                    </el-select>
                  </el-form-item>
                </el-col>
                <el-col span="6">
                  <el-form-item label="参数类型:">
                    <el-select v-model="editForm.requestParameterType" placeholder="请选择参数类型">
                      <el-option label="data" value="data" />
                      <el-option label="json" value="json" />
                    </el-select>
                  </el-form-item>
                </el-col>
                <el-col span="6">
                  <el-form-item label="项目名:">
                    <el-select v-model="editForm.project" placeholder="项目名">
                      <el-option
                        v-for="item in options"
                        :key="item.id"
                        :label="item.project_name"
                        :value="item.id"
                      /></el-select>
                  </el-form-item>
                </el-col>
              </el-row>
              <el-form-item label="接口地址:" prop="apiAddress" :rules="rules.apiAddress">
                <el-input v-model="editForm.apiAddress" />
              </el-form-item>
              <el-form-item label="请求header:">
                <el-input v-model="editForm.headers" type="textarea" :rows="5" autocomplete="off" />
              </el-form-item>
              <el-form-item label="参数:">
                <el-input v-model="editForm.body" type="textarea" :rows="5" autocomplete="off" />
              </el-form-item></el-form>
            <div slot="footer" class="dialog-footer">
              <el-button @click="dialogFormVisible = false">取 消</el-button>
              <el-button type="primary" @click="formEditOn">确 定</el-button>
            </div>
          </el-dialog>
          <el-dialog :visible.sync="dialogFormVisibleAdd" :modal-append-to-body="false">
            <span slot="title" :model="addForm" style="font-weight:bold;">新增用例:</span>
            <el-form class="form" label-width="auto" :label-position="left" :model="addForm" :rules="rules">
              <el-form-item label="用例名称:" prop="name" :rules="rules.name">
                <el-input v-model="addForm.name" />
              </el-form-item>
              <el-row>
                <el-col span="6">
                  <el-form-item label="http类型:">
                    <el-select v-model="addForm.httpType" placeholder="请选择http类型">
                      <el-option label="http" value="http" />
                      <el-option label="https" value="https" />
                    </el-select>
                  </el-form-item>
                </el-col>
                <el-col span="6">
                  <el-form-item label="请求方法:">
                    <el-select v-model="addForm.requestType" placeholder="请选择请求方法">
                      <el-option label="get" value="get" />
                      <el-option label="post" value="post" />
                      <el-option label="put" value="put" />
                      <el-option label="delete" value="delete" />
                    </el-select>
                  </el-form-item>
                </el-col>
                <el-col span="6">
                  <el-form-item label="参数类型:">
                    <el-select v-model="addForm.requestParameterType" placeholder="请选择参数类型">
                      <el-option label="data" value="data" />
                      <el-option label="json" value="json" />
                    </el-select>
                  </el-form-item>
                </el-col>
                <el-col span="6">
                  <el-form-item label="项目名:">
                    <el-select v-model="editForm.project" placeholder="项目名">
                      <el-option
                        v-for="item in options"
                        :key="item.id"
                        :label="item.project_name"
                        :value="item.id"
                      /></el-select>
                  </el-form-item>
                </el-col>
              </el-row>
              <el-form-item label="接口地址:" prop="apiAddress" :rules="rules.apiAddress">
                <el-input v-model="addForm.apiAddress" />
              </el-form-item>
              <el-form-item label="请求header:" label-width="auto">
                <el-input v-model="editForm.headers" type="textarea" :rows="5" autocomplete="off" />
              </el-form-item>
              <el-form-item label="参数:">
                <el-input v-model="addForm.body" type="textarea" :rows="5" autocomplete="off" />
              </el-form-item></el-form>
            <div slot="footer" class="dialog-footer">
              <el-button @click="dialogFormVisibleAdd = false">取 消</el-button>
              <el-button type="primary" @click="formAdd">确 定</el-button>
            </div>
          </el-dialog>
        </template>
      </el-table-column>
    </el-table>
    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
  </div>
</template>
<script>
import Pagination from '@/components/Pagination'
import axios from 'axios'
import { platformBaseUrl } from '@/api/baseHost'
export default {
  components: { Pagination },
  data() {
    return {
      // formInline: {
      //   caseName: ''
      // },
      dialogFormVisible: false,
      dialogFormVisibleAdd: false,
      // formLabelWidth: '120px',
      tableKey: 0,
      list: [],
      total: 0,
      loadingstatus: false,
      listLoading: true,
      id: '',
      params: {},
      options: [{ 'id': 1, 'project_name': 'WGP-SRVbak' }, { 'id': 2, 'project_name': 'WGP-ADMINbak' }],
      rules: {
        name: [{ required: true, message: '用例名称不能为空', tigger: 'change' }],
        apiAddress: [{ required: true, message: '接口地址不能为空', tigger: 'change' }]
      },
      addForm: {
        name: '',
        httpType: 'http',
        requestType: 'get',
        requestParameterType: 'data',
        project: 'WGP-SRV',
        apiAddress: '',
        body: '',
        headers: ''
      },
      editForm: {
        id: undefined,
        name: '',
        httpType: '',
        requestType: '',
        requestParameterType: '',
        project: '',
        apiAddress: '',
        body: '',
        headers: ''
      },
      listQuery: {
        page: 1,
        limit: 10,
        name: '',
        sort: '+id'
      },
      sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }]
    }
  },
  created() {
    console.log('created')
    this.getProject()
    this.getList()
  },
  methods: {
    getList() {
      this.listLoading = true
      axios.post(platformBaseUrl + '/filter_Api/', this.listQuery)
        .then(response => {
          console.log(response.data)
          this.list = response.data.result.items
          this.total = response.data.result.total
        })
      setTimeout(() => {
        this.listLoading = false
      }, 1.5 * 1000)
    },
    getProject() {
      axios.post(platformBaseUrl + '/filter_Project/', {})
        .then(response => {
          console.log(response.data)
          this.options = response.data.result
        })
      setTimeout(() => {
        this.listLoading = false
      }, 1.5 * 1000)
    },
    copyValue(value) {
      console.log('cope 121212')
      const oInput = document.createElement('input') // 创建一个input标签
      oInput.setAttribute('value', value) // 设置改input的value值
      document.body.appendChild(oInput) // 将input添加到body
      oInput.select() // 获取input的文本内容
      document.execCommand('copy') // 执行copy指令
      document.body.removeChild(oInput) // 删除input标签
      this.$message({ message: '复制成功', type: 'success' })
    },

    handleFilter() {
      this.listQuery.page = 1
      this.getList()
    },
    formEditDialog(index, row) {
      this.dialogFormVisible = true
      this.id = index
      this.editForm = Object.assign({}, row)
      console.log(this.editForm)
    },
    runCase(index, row) {
      this.params = Object.assign({}, row)['id']
      // this.params = Object.assign({}, row)
      if ((this.params !== '')) {
        axios.post(platformBaseUrl + '/run_case/', this.params)
          .then(response => {
            console.log(response.data)
            this.dialogFormVisible = false
            // eslint-disable-next-line eqeqeq
            if (response.data.result.msg == '更新成功') {
              this.$message({ message: response.data.result.msg, type: 'success' })
              this.getList()
            } else {
              this.$message({ message: response.data.result.msg, type: 'error' })
            }
          })
        setTimeout(() => {
          this.listLoading = false
        }, 1.5 * 1000)
      }
    },
    formEditOn() {
      if ((this.editForm.name !== '' && this.editForm.apiAddress !== '')) {
        axios.post(platformBaseUrl + '/edit_Api/', this.editForm)
          .then(response => {
            console.log(response.data)
            this.dialogFormVisible = false
            // eslint-disable-next-line eqeqeq
            if (response.data.result.msg == '更新成功') {
              this.$message({ message: response.data.result.msg, type: 'success' })
              this.getList()
            } else {
              this.$message({ message: response.data.result.msg, type: 'error' })
            }
          })
        setTimeout(() => {
          this.listLoading = false
        }, 1.5 * 1000)
      }
    },
    add_case() {
      this.dialogFormVisibleAdd = true
    },
    formAdd() {
      if ((this.addForm.name !== '' && this.addForm.apiAddress !== '')) {
        this.dialogFormVisibleAdd = false
        axios.post(platformBaseUrl + '/add_Api/', this.addForm)
          .then(response => {
            console.log(response.data)
            if (response.data.result.msg === '新增接口成功') {
              this.$message({ message: response.data.result.msg, type: 'success' })
              this.getList()
            } else {
              this.$message({ message: response.data.result.msg, type: 'error' })
            }
          })
        setTimeout(() => {
          this.listLoading = false
        }, 1.5 * 1000)
      }
    },
    sortChange(data) {
      const { prop, order } = data
      if (prop === 'id') {
        this.sortByID(order)
      }
    },
    getRowClass({ row, column, rowIndex, columnIndex }) {
      if (rowIndex === 0) {
        return 'background:#C0C0C0;color:#666666;text-align:center;font-size:14px;font-weight:500;width: 100%'
      } else {
        return 'white-space: pre-line'
      }
    },
    sortByID(order) {
      if (order === 'ascending') {
        this.listQuery.sort = '+id'
      } else {
        this.listQuery.sort = '-id'
      }
      this.handleFilter()
    },
    getSortClass: function(key) {
      const sort = this.listQuery.sort
      return sort === `+${key}` ? 'ascending' : 'descending'
    }
  }
}
</script>

<style scoped>
.app-container{
  background: #f3f0f0;
  /* position: fixed; */
    width: 100%;
    height: 100%;
}
.filter-container{
background: #fdfdfd;
    width: 100%;
    height: 100px;
}
.filter-col{
  margin:30px 50px 10px 50px;
}
.table-expand {
    font-size: 0;
    border: 2px solid #078359;
  }
  .table-expand label {
    width: 90px;
    color: #99a9bf;
  }
  .table-expand .el-form-item {
    margin-right: 0;
    margin-bottom: 0;
    width: 50%;
  }
  .form{
    margin:0px 0px 10px 0px;
    width: 100%;

  border: 2px solid #078359;
    margin-bottom: 0;
  }
</style>
相关推荐
老白干2 小时前
jjwt 0.9.1 在 JDK 11+ 上的两个“坑”与完整解决方案
java·python·log4j
笨鸟先飞,勤能补拙9 小时前
AI 赋能网络安全:技术全景、成熟度评估与实战案例
人工智能·python·安全·web安全·网络安全·sqlite·github
长和信泰光伏储能9 小时前
京津冀光伏发电:绿色能源的未来之路
python·能源
浦信仿真大讲堂10 小时前
从重复操作到自动化闭环:如何让 CST 与 Python 真正协同起来
python·自动化·cst·仿真软件·达索软件
Gu Gu Study10 小时前
ScoutLoop开放域深度研究引擎(agent的初步设计想法)
人工智能·python
卷无止境11 小时前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境11 小时前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
lpfasd12311 小时前
MediaCrawler 项目深度分析
chrome·python·chrome devtools
Dxy123931021612 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
bamb0012 小时前
一个项目带你入门AI应用开发01
python