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

背景

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

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

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

开发环境

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

操作系统:Mac OS X EI Caption

Python版本:2.7

IDE:Pycharm

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

分析

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

架构

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

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

数据源

数据源我使用的是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://jb51.net/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
  <script src="http://jb51.net/jquery/2.0.0/jquery.min.js"></script>
  <script src="http://jb51.net/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写一个工具很容易,主要还是要能更方便地满足实际工作中的使用需要为目的。如果要做完整的接口测试,还是尽量使用已经成熟的工具。

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

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

(0)

相关推荐

  • 深入解析Python中的WSGI接口

    概述 WSGI接口包含两方面:server/gateway 及 application/framework. server调用由application提供的可调用对象. 另外在server和application之间还可能有一种称作middleware的中间件. 可调用对象是指:函数.方法.类或者带有callable方法的实例. 关于application 函数.方法.类及带有callable方法的实例等可调用对象都可以作为the application object. WSGI协议要求: th

  • linux系统使用python监测网络接口获取网络的输入输出

    net.py 获取网络接口的输入和输出 复制代码 代码如下: #!/usr/bin/env Pythonimport timeimport sys if len(sys.argv) > 1: INTERFACE = sys.argv[1]else: INTERFACE = 'eth0'STATS = []print 'Interface:',INTERFACE def rx(): ifstat = open('/proc/net/dev').readlines() for interface i

  • 使用Python的Bottle框架写一个简单的服务接口的示例

    是不是有这么一个场景,对外提供一堆数据或者是要返回给用户一个结果.但是不想把内部的一些数据和逻辑暴露给对方...简单点来说,就是想以服务的方式对外提供一个接口.对于这种有很多处理方式,RPC,搭建一个web服务啥的....但是这些毕竟都太重量级了,操作起来很麻烦.我这里给出的一种非常easy的方式来处理.使用bottle解决问题. 需求: 检查一个zookeeper服务中的某些节点是否存在,如果存在返回OK,不存在则给出不存的节点信息.要求返回的信息是和pyunit的结果信息一致. 实现环境:

  • 使用python实现接口的方法

    接口基础知识: 简单说下接口测试,现在常用的2种接口就是http api和rpc协议的接口,今天主要说:http api接口是走http协议通过路径来区分调用的方法,请求报文格式都是key-value形式,返回报文一般是json串: 接口协议:http.webservice.rpc等. 请求方式:get.post方式 请求参数格式: a. get请求都是通过url?param=xxx&param1=xxx b. post请求的请求参数常用类型有:application/json.applicat

  • 在Python的框架中为MySQL实现restful接口的教程

    最近在做游戏服务分层的时候,一直想把mysql的访问独立成一个单独的服务DBGate,原因如下: 请求收拢到DBGate,可以使DBGate变为无状态的,方便横向扩展 当请求量或者存储量变大时,mysql需要做分库分表,DBGate可以内部直接处理,外界无感知 通过restful限制对数据请求的形式,仅支持简单的get/post/patch/put 进行增删改查,并不支持复杂查询.这个也是和游戏业务的特性有关,如果网站等需要复杂查询的业务,对此并不适合 DBGate使用多进程模式,方便控制与my

  • Python+微信接口实现运维报警

    说到运维报警,我觉得都可以写个长篇历史来详细解释了报警的前世来生,比如最早报警都是用邮件,但邮件实时性不高,比如下班回家总不能人一直盯着邮箱吧,所以邮件这种报警方式不适合用来报紧急的故障,日常磁盘利用率监控什么的可以用它来报没问题,网站宕机不能访问这种故障,用它就明显不合适了,那对这种业务稳定性要求比较高的业务,后来就发展成了用短信,就是公司买个短信机,提供一个http接口,然后运维人员写脚本把收集到的异常数据写入文件,然后脚本实时检测如果这个文件不为空,就调用短信机接口把文件里的内容发送出去,

  • 详解Python程序与服务器连接的WSGI接口

    了解了HTTP协议和HTML文档,我们其实就明白了一个Web应用的本质就是: 浏览器发送一个HTTP请求: 服务器收到请求,生成一个HTML文档: 服务器把HTML文档作为HTTP响应的Body发送给浏览器: 浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示. 所以,最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回.Apache.Nginx.Lighttpd等这些常见的静态服务器就是干这件事情的. 如果要动

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

    背景 最近公司在做消息推送,那么自然就会产生很多接口,测试的过程中需要调用接口,我就突然觉得是不是可以自己写一个测试框架? 说干就干,由于现有的接口测试工具Jmeter.SoupUI等学习周期有点长,干脆自己写一个吧,不求人,所有功能自己都能一清二楚. 当然,写工具造轮子只是学习的一种方式,现成成熟的工具肯定比我们自己的写的好用. 开发环境 ------------------------------------------------------------- 操作系统:Mac OS X EI

  • Python reques接口测试框架实现代码

    一.框架菜单 1.1 common模块 1.2 其他 二.Excel接口测试案例编写 三.读取Excel测试封装(核心封装) excel_utils.py 读取Excel中的数据 import os import xlrd #内置模块.第三方模块pip install 自定义模块 class ExcelUtils(): def __init__(self,file_path,sheet_name): self.file_path = file_path self.sheet_name = she

  • python模拟Django框架实例

    一.python实现web服务器 web开发首先要有web服务器才行.比如apache,但是在开发阶段最好有一个简单方便的开发服务器, 容易重启进行调试,等开发调试完毕后,再将代码部署到成熟稳定高效的web服务器. # -*- coding: utf-8 -*- from wsgiref import simple_server # 定义一个输出 hello world 和环境变量的简单web应用程序 def hello_app(environ, start_response): # 输出 ht

  • 使用基于Python的Tornado框架的HTTP客户端的教程

    由于tornado内置的AsyncHTTPClient功能过于单一, 所以自己写了一个基于Tornado的HTTP客户端库, 鉴于自己多处使用了这个库, 所以从项目中提取出来, 写成一个单独库 tornadohttpclient TornadoHTTPClient 是一个基于Tornado的高效的异步HTTP客户端库, 支持Cookie和代理, 目前仅在Python2.7平台上测试过, 不支持Python3 听取了仙子君的意见, 直接对tornado.curl_httpclient.CurlAs

  • Python使用Web框架Flask开发项目

    目录 一.简介 二.安装 三.从 Hello World 开始 3.1 Hello World 3.2 修改Flask的配置 3.3 调试模式 3.4 绑定IP和端口 3.5 本节源码 四.获取 URL 参数 4.1 建立Flask项目 4.2 列出所有的url参数 4.3 获取某个指定的参数 4.4 如何处理多值 4.5 本节源码 五.获取POST方法传送的数据 5.1 建立Flask项目 5.2 查看POST数据内容 5.3 解析POST数据 5.4 本节源码 六.处理和响应JSON数据 6

  • Python使用django框架实现多人在线匿名聊天的小程序

    最近看到好多设计类网站,都提供了多人在线匿名聊天的小功能,感觉很有意思,于是基于python的django框架自己写了一个,支持手动实时更名,最下方提供了完整的源码. 在线聊天地址(无需登录,开一个窗口,代表一个用户): http://zhaozhaoli.vicp.io/chatroom/happy/ 移动端聊天效果图: 网页版聊天效果图: 实现思路: 发送的消息通过ajax先写入数据库,通过ajax的循环请求,将写入数据库的消息显示到前端界面. 前端核心代码: <script> $(fun

  • 基于python socketserver框架全面解析

    socketserver框架是一个基本的socket服务器端框架, 使用了threading来处理多个客户端的连接, 使用seletor模块来处理高并发访问, 是值得一看的python 标准库的源码之一 对于select网络框架的理解可以看 << 基于python select.select模块通信的实例讲解 >>.socketserver框架采用了selector框架来供你选择相适应的网络通信框架, 比如select, poll, epoll等.有了这些网络框架我们就能处理高并发

  • 基于python图书馆管理系统设计实例详解

    写完这个项目后,导师说这个你完全可以当作毕业项目使用了,写的很全,很多的都设计考虑周全,但我的脚步绝不止于现在,我想要的是星辰大海!与君共勉! 这个项目不是我的作业, 只是无意中被拉进来了,然后就承担了所有,肝了一周多,终于完成,但这个也算是一个很大的项目了吧,对于我现在来说,写这个项目遇到了很多困难,这是真的,其中涉及到数据库的使用,就遇到了一点瓶颈, 但这不算什么,还是要被我搞定的. 梦想就像这个远处夕阳,终究触手可及! Python项目: 项目前提: 这个项目涉及到的知识点有很多, 知识串

  • 基于Python的接口自动化unittest测试框架和ddt数据驱动详解

    引言 在编写接口自动化用例时,我们一般针对一个接口建立一个.py文件,一条接口测试用例封装为一个函数(方法),但是在批量执行的过程中,如果其中一条出错,后面的用例就无法执行,还有在运行大量的接口测试用例时测试数据如何管理和加载.针对测试用例加载以及执行控制,python语言提供了unittest单元测试框架,将测试用例编写在unittest框架下,使用该框架可以单个或者批量加载互不影响的用例执行及更灵活的执行控制,对于更好的进行测试数据的管理和加载,这里我们引入数据驱动的模块:ddt,测试数据和

  • 基于python select.select模块通信的实例讲解

    要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值. select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接收所有要发出去的data(outgoing data),第3个监控错误信息在网上一直在找这个select.select的参数解释, 但实在是没有, 哎...自己硬着头皮分析了一下. readable, writable, exceptional = select.select(inputs, ou

随机推荐