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

测试平台目录

测试平台自建源码

后台核心代码

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 分钟前
celery在django项目中实现并发任务和定时任务
python·django·celery·定时任务·异步任务
斯凯利.瑞恩10 分钟前
Python决策树、随机森林、朴素贝叶斯、KNN(K-最近邻居)分类分析银行拉新活动挖掘潜在贷款客户附数据代码
python·决策树·随机森林
yannan2019031331 分钟前
【算法】(Python)动态规划
python·算法·动态规划
蒙娜丽宁41 分钟前
《Python OpenCV从菜鸟到高手》——零基础进阶,开启图像处理与计算机视觉的大门!
python·opencv·计算机视觉
光芒再现dev43 分钟前
已解决,部署GPTSoVITS报错‘AsyncRequest‘ object has no attribute ‘_json_response_data‘
运维·python·gpt·语言模型·自然语言处理
好喜欢吃红柚子1 小时前
万字长文解读空间、通道注意力机制机制和超详细代码逐行分析(SE,CBAM,SGE,CA,ECA,TA)
人工智能·pytorch·python·计算机视觉·cnn
小馒头学python1 小时前
机器学习是什么?AIGC又是什么?机器学习与AIGC未来科技的双引擎
人工智能·python·机器学习
神奇夜光杯1 小时前
Python酷库之旅-第三方库Pandas(202)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长
千天夜1 小时前
使用UDP协议传输视频流!(分片、缓存)
python·网络协议·udp·视频流
测试界的酸菜鱼1 小时前
Python 大数据展示屏实例
大数据·开发语言·python