基于Python的接口测试框架实例


Posted in Python onNovember 04, 2016

背景

最近公司在做消息推送,那么自然就会产生很多接口,测试的过程中需要调用接口,我就突然觉得是不是可以自己写一个测试框架?

说干就干,由于现有的接口测试工具Jmeter、SoupUI等学习周期有点长,干脆自己写一个吧,不求人,所有功能自己都能一清二楚。

当然,写工具造轮子只是学习的一种方式,现成成熟的工具肯定比我们自己的写的好用。

开发环境

-------------------------------------------------------------

操作系统:Mac OS X EI Caption

Python版本:2.7

IDE:Pycharm

-------------------------------------------------------------

分析

接口是基于HTTP协议的,那么说白了,就是发起HTTP请求就行了,对于Python来说简直就是小菜一碟。直接使用requests就可以很轻松的完成任务。

架构

整个框架是比较小的,涉及的东西也比较少,只要分清楚几个模块的功能就行了。

基于Python的接口测试框架实例

上面是一个接口测试的完整流程。只要一步一步的走下来就行了,并不是很难。

数据源

数据源我使用的是JSON来保存,当然,比较广泛的是使用Excel来保存,用JSON来保存是因为JSON用起来比较方便,懒得去读取Excel了,Python对JSON的支持是非常友好的。当然这个就看个人喜好了。

{
  "TestId": "testcase004",
  "Method": "post",
  "Title": "单独推送消息",
  "Desc": "单独推送消息",
  "Url": "http://xxx.xxx.xxx.xx",
  "InputArg": {
   "action": "44803",
   "account": "1865998xxxx",
   "uniqueid": "00D7C889-06A0-426E-BAB1-5741A1192038",
   "title": "测试测试",
   "summary": "豆豆豆",
   "message": "12345",
   "msgtype": "25",
   "menuid": "203"
  },
  "Result": {
   "errorno": "0"
  }
 }

示例如上面代码所示,可以根据个人的业务需要进行调整。

发送请求

发送请求就很简单了,用requests模块,然后从JSON中读取发送的参数,post、get或者其他。由于要生成测试报告,那么发送的数据需要做一下记录,我选择用txt文本来作为记录的容器。

f = file("case.json")
testData = json.load(f)
f.close()


def sendData(testData, num):
  payload = {}
  # 从json中获取发送参数
  for x in testData[num]['InputArg'].items():
    payload[x[0]] = x[1]
  with open('leftside.txt', 'a+') as f:
    f.write(testData[num]['TestId'])
    f.write('-')
    f.write(testData[num]['Title'])
    f.write('\n')

  # 发送请求
  data = requests.get(testData[num]['Url'], params=payload)
  r = data.json()

接受返回

由于我们是需要生成测试报告的,那么返回的数据我们先需要进行一次存储,可以选择用数据库存储,但是我觉得数据库存储太麻烦了,只要用txt文本作为存储容器即可。

with open('rightside.txt', 'a+') as rs:
    rs.write('发送数据')
    rs.write('|')
    rs.write('标题:'+testData[num]['Title'])
    rs.write('|')
    rs.write('发送方式:'+testData[num]['Method'])
    rs.write('|')
    rs.write('案例描述:'+testData[num]['Desc'])
    rs.write('|')
    rs.write('发送地址:'+testData[num]['Url'])
    rs.write('|')
    rs.write('发送参数:'+str(payload).decode("unicode-escape").encode("utf-8").replace("u\'","\'"))
    rs.write('|')
    rs.write(testData[num]['TestId'])
    rs.write('\n')

结果判定

结果判定我使用的是全等于判定。因为我们的接口只需要这样处理就行了,如果有需要,可以写成正则判定。

with open('result.txt', 'a+') as rst:
    rst.write('返回数据')
    rst.write('|')
    for x, y in r.items():
      rst.write(' : '.join([x, y]))
      rst.write('|')
    # 写测试结果
    try:
      if cmp(r, testData[num]['Result']) == 0:
        rst.write('pass')
      else:
        rst.write('fail')
    except Exception:
      rst.write('no except result')
    rst.write('\n')

我这里结果有3种,成功、失败或者没结果。结果的设置就看自己的定义了。

生成测试报告

测试报告是一个重头戏,由于我发送数据、返回数据和结果都是用txt文本存储,那么每次使用a+模式新增,会让结果越来越多,而且检查起来非常蛋疼。

我的处理方式是每次测试完毕之后,用Python读取txt文本中的数据,然后使用Django动态生成一个结果,然后再使用requests抓取这个网页,保存在Report文件夹中。

网页报告

Django的方法我就不多说了,博客中已经有一整个系列文章了。我们需要在views文件中打开之前记录的3个txt文件,然后做一些数据处理,返回给前端,前端用Bootstrap来渲染,就能生成一个比较漂亮的测试报告。

def index(request):
  rightside = []
  result = []
  rst_data = []
  leftside = []
  passed = 0
  fail = 0
  noresult = 0
  with open(os.getcwd() + '/PortTest/leftside.txt') as ls:
    for x in ls.readlines():
      lf_data = {
        'code': x.strip().split('-')[0],
        'title': x.strip().split('-')[1]
      }
      leftside.append(lf_data)

  with open(os.getcwd() + '/PortTest/rightside.txt') as rs:
    for x in rs.readlines():
      row = x.strip().split('|')
      rs_data = {
        "fssj": row[0],
        "csbt": row[1],
        "fsfs": row[2],
        "alms": row[3],
        "fsdz": row[4],
        "fscs": row[5],
        'testid': row[6]
      }
      rightside.append(rs_data)

  with open(os.getcwd() + '/PortTest/result.txt') as rst:
    for x in rst.readlines():
      row = x.strip().split('|')
      if row[len(row)-1] == 'fail':
        fail += 1
      elif row[len(row)-1] == 'pass':
        passed += 1
      elif row[len(row)-1] == 'no except result':
        noresult += 1

      rs_data = []
      for y in row:
        rs_data.append(y)
      result.append(rs_data)
  for a, b in zip(rightside, result):
    data = {
      "sendData": a,
      "dealData": b,
      "result": b[len(b)-1]
    }
    rst_data.append(data)
  return render(request, 'PortTest/index.html', {"leftside": leftside,
                          "rst_data": rst_data,
                          "pass": passed,
                          "fail": fail,
                          "noresult": noresult})

基本上都是一些很基础的知识,字符串分割等等。这里的数据处理为了方便,在获取数据存储的时候就要按照一定的格式来存储,views的方法就很容易做处理。

前端代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <link href="http://3water.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
  <script src="http://3water.com/jquery/2.0.0/jquery.min.js"></script>
  <script src="http://3water.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
  <div class="row">
    <div class="page-header">
      <h1>接口测试报告
        <small>Design By Sven</small>
      </h1>
    </div>
  </div>
  <div class="row">
    <div class="col-md-4">
      <h3>测试通过 <span class="label label-success">{{ pass }}</span></h3>
    </div>
    <div class="col-md-4">
      <h3>测试失败 <span class="label label-danger">{{ fail }}</span></h3>
    </div>
    <div class="col-md-4">
      <h3>无结果 <span class="label label-warning">{{ noresult }}</span></h3>
    </div>
  </div>
  <p></p>
  <div class="row">
    <div class="col-md-3">
      <ul class="list-group">
        {% for ls in leftside %}
          <li class="list-group-item"><a href="#{{ ls.code }}">{{ ls.code }} - {{ ls.title }}</a></li>
        {% endfor %}
      </ul>
    </div>
    <div class="col-md-9">
      {{ x.result }}
      {% for x in rst_data %}
        <div class="panel-group" id="accordion">
        {% if x.result == 'pass' %}
          <div class="panel panel-success">
        {% elif x.result == 'fail' %}
          <div class="panel panel-danger">
        {% elif x.result == 'no except result' %}
          <div class="panel panel-warning">
        {% endif %}

      <div class="panel-heading">
        <h4 class="panel-title">
          <a data-toggle="collapse" href="#{{ x.sendData.testid }}">
            {{ x.sendData.testid }} - {{ x.sendData.csbt }}
          </a>
        </h4>
      </div>
      <div id="{{ x.sendData.testid }}" class="panel-collapse collapse">
        <div class="panel-body">
          <b>{{ x.sendData.fssj }}</b><br>
          {{ x.sendData.csbt }}<br>
          {{ x.sendData.fsfs }}<br>
          {{ x.sendData.alms }}<br>
          {{ x.sendData.fsdz }}<br>
          {{ x.sendData.fscs }}
          <hr>
          {% for v in x.dealData %}
            {{ v }}<br>
          {% endfor %}
        </div>
      </div>
      </div>
      </div>
        <p></p>
      {% endfor %}
      </div>
      </div>
    </div>
    <script>
      $(function () {
        $(window).scroll(function () {
          if ($(this).scrollTop() != 0) {
            $("#toTop").fadeIn();
          } else {
            $("#toTop").fadeOut();
          }
        });
        $("body").append("<div id=\"toTop\" style=\"border:1px solid #444;background:#333;color:#fff;text-align:center;padding:10px 13px 7px 13px;position:fixed;bottom:10px;right:10px;cursor:pointer;display:none;font-family:verdana;font-size:22px;\">^</div>");
        $("#toTop").click(function () {
          $("body,html").animate({scrollTop: 0}, 800);
        });
      });
    </script>
</body>
</html>

测试报告效果图

基于Python的接口测试框架实例

最后

用Python写一个工具很容易,主要还是要能更方便地满足实际工作中的使用需要为目的。如果要做完整的接口测试,还是尽量使用已经成熟的工具。

PS:简单的造轮子也是学习原理的一个绝佳的方法。

以上这篇基于Python的接口测试框架实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用Python求解最大公约数的实现方法
Aug 20 Python
Python变量和数据类型详解
Feb 15 Python
python使用os.listdir和os.walk获得文件的路径的方法
Dec 16 Python
用xpath获取指定标签下的所有text的实例
Jan 02 Python
python并发编程 Process对象的其他属性方法join方法详解
Aug 20 Python
Django实现文件上传和下载功能
Oct 06 Python
pyspark给dataframe增加新的一列的实现示例
Apr 24 Python
python有几个版本
Jun 17 Python
python opencv角点检测连线功能的实现代码
Nov 24 Python
详解Django自定义图片和文件上传路径(upload_to)的2种方式
Dec 01 Python
分享unittest单元测试框架中几种常用的用例加载方法
Dec 02 Python
Python爬虫实例之2021猫眼票房字体加密反爬策略(粗略版)
Feb 22 Python
浅谈Python爬取网页的编码处理
Nov 04 #Python
Django接受前端数据的几种方法总结
Nov 04 #Python
Python多维/嵌套字典数据无限遍历的实现
Nov 04 #Python
浅谈Python数据类型判断及列表脚本操作
Nov 04 #Python
浅谈python字典多键值及重复键值的使用
Nov 04 #Python
用Python将动态GIF图片倒放播放的方法
Nov 02 #Python
各种Python库安装包下载地址与安装过程详细介绍(Windows版)
Nov 02 #Python
You might like
PHP导入Excel到MySQL的方法
2011/04/23 PHP
php5.3 goto函数介绍和示例
2014/03/21 PHP
详解PHP的Yii框架中的Controller控制器
2016/03/29 PHP
laravel中命名路由的使用方法
2017/02/24 PHP
php分享朋友圈的实现代码
2019/02/18 PHP
Laravel框架运行出错提示RuntimeException No application encryption key has been specified.解决方法
2019/04/02 PHP
跨浏览器的 mouseenter mouseleave 以及 compareDocumentPosition的使用说明
2010/05/04 Javascript
javascript 伪数组实现方法
2010/10/11 Javascript
javascript之Partial Application学习
2013/01/10 Javascript
JavaScript中发布/订阅模式的简单实例
2014/11/05 Javascript
跟我学习javascript的闭包
2015/11/16 Javascript
JS Array.slice 截取数组的实现方法
2016/01/02 Javascript
JavaScript编写带旋转+线条干扰的验证码脚本实例
2016/05/30 Javascript
JavaScript中Form表单技术汇总(推荐)
2016/06/26 Javascript
简单的JS控制button颜色随点击更改的实现方法
2017/04/17 Javascript
JS实现碰撞检测的方法分析
2018/01/19 Javascript
3种vue路由传参的基本模式
2018/02/22 Javascript
Nodejs异步流程框架async的方法
2019/06/07 NodeJs
vue引入静态js文件的方法
2020/06/20 Javascript
vue2.* element tabs tab-pane 动态加载组件操作
2020/07/19 Javascript
Python实现的生成自我描述脚本分享(很有意思的程序)
2014/07/18 Python
Django框架下在视图中使用模版的方法
2015/07/16 Python
Python的Django框架中从url中捕捉文本的方法
2015/07/20 Python
Python绘制频率分布直方图的示例
2019/07/08 Python
python 控制Asterisk AMI接口外呼电话的例子
2019/08/08 Python
python+opencv实现车牌定位功能(实例代码)
2019/12/24 Python
使用Python合成图片的实现代码(图片添加个性化文本,图片上叠加其他图片)
2020/04/30 Python
html5 canvas-1.canvas介绍(hello canvas)
2013/01/07 HTML / CSS
朗仕(Lab series)英国官网:雅诗兰黛集团男士专属护肤品牌
2017/11/28 全球购物
视图的作用
2014/12/19 面试题
贷款委托书怎么写
2014/08/02 职场文书
五月的鲜花活动方案
2014/08/21 职场文书
普通党员四风问题对照检查材料
2014/09/27 职场文书
计划生育工作汇报
2014/10/28 职场文书
董事长秘书岗位职责
2015/02/13 职场文书
mysql使用instr达到in(字符串)的效果
2022/04/03 MySQL