天天看点

python接口测试_【Python自学】Python接口自动化测试的学习 - 伊凡Ivan  

最近用到了python和request的一些内容,感觉自己掌握的比较零散,所以将内容记录下来,方便查阅。

1)环境准备:

  接口测试的方式有很多,比如可以用工具(jmeter,postman)之类,也可以自己写代码进行接口测试,工具的使用相对来说都比较简单,重点是要搞清楚项目接口的协议是什么,然后有针对性的进行选择,甚至当工具不太适合项目时需要自己进行开发。

  在我们项目的初期,我们采用的是jmeter进行接口测试,当时觉得这个工具上手简单,团队成员学习成本低,并且接口测试的脚本稍微调整一下还可以用来做性能测试。

  不过随着项目规模、团队人数的不断增长,渐渐的这个工具有适应不了当前项目的需求了,为此我们项目也重新开发了相关接口自动化的平台。但是,但是。。。可能是我让大家中毒太深,现在很多同学一提到接口测试关联到jmeter,为此,我深深感到不安。毕竟jmeter只是个工具,换个项目换个协议你是否还能玩转接口测试呢?session和cookie有什么区别?工具又是怎么实现的呢?

  比如session如何保存,接口依赖如何处理,case如何管理及执行顺序,测试数据如何管理等等题,这个过程也有助于我们更加深刻的理解接口测试和http协议。

  本文主要采用python语言,python中http协议接口相关的库有urllib,urllib2以及reqeusts库,这其中reqeusts库用来起来最方便,因此我也主要采用requests库来做http协议的接口测试。首先来看下需要哪些环境信息:

一、安装python

  mac下自带安装了python,这个不多说了。

二、安装虚拟环境:

我们在一台机器上可以安装多个python版本,为了使每个版本的环境相互不受干扰,可以安装虚拟环境,安装方法如下:

1、安装virtualenv:pip install virtualenv

2、新建名为venv的虚拟环境:virtualenv venv

3、进入新环境:source venv/bin/activate

4、退出:deactivate

三、安装requests库:

>>>pip install requests

ps:用python做http协议的接口测试会用到这个库。

四、http测试工具:

一个使用 Python + Flask 编写的 HTTP 请求和响应服务,该服务主要用于测试 HTTP 库。后续测试我们都基于这个网站。

五、在本地搭建httpbin:

考虑到测试时要不断访问 httpbin 网站,请求过多担心被拉到黑名单,我们自己在本志搭建一套httpbin服务。

1、安装:pip install gunicorn

2、安装:pip install httpbin

3、启动:gunicorn httpbin:app

至此,环境搭建已经完毕,可以开始玩了~

(2)()

环境搭建好后,接下来我们先来了解一下requests的一些简单使用,主要包括:

  1. requests常用请求方法使用,包括:get,post
  2. requests库中的Session、Cookie的使用
  3. 其它高级部分:认证、代理、证书验证、超时配置、错误异常处理等。

本节首先来了解一下requests库中如何发送get请求:

一、看下方法定义:

1、到官方文档去了下()方法的定义,如下:

python接口测试_【Python自学】Python接口自动化测试的学习 - 伊凡Ivan  

2、点击右上角的【source】,看一下它的源码如下:

python接口测试_【Python自学】Python接口自动化测试的学习 - 伊凡Ivan  

看到最后一行return,get方法最后是通过调用  方法实现的,其实在其它的请求方法如post,put,head,delete等方法都是调用的request方法,然后把请求方法的类型传递给request方法第一个参数。

3、HTTP协议是一个基于请求/响应模式的、无状态的,应用层协议。既然有请求,就有响应,来看下resquest中常用的响应信息:

python接口测试_【Python自学】Python接口自动化测试的学习 - 伊凡Ivan  

二、get方法简单使用: 

1、不带参数的get:

输出:

2、 带参数的get:

 输出:

/get?show_env=1
{
    'origin': '',
    'headers': {
        'X-Request-Id': 'ebe922b4-c463-4fe9-9faf-49748d682fd7',
        'Accept-Encoding': 'gzip,
        deflate',
        'X-Forwarded-Port': '80',
        'Total-Route-Time': '0',
        'Connection': 'close',
        'Connect-Time': '0',
        'Via': '',
        'X-Forwarded-For': '',
        'Accept': '*/*',
        'User-Agent': 'python-requests/',
        'X-Request-Start': '1504755961007',
        'Host': '',
        'X-Forwarded-Proto': 'http'
    },
    'args': {
        'show_env': '1'
    },
    'url': 'http: ///get?show_env=1'
}
           

3、带header的get:

输出:

4、同时带参数和header:

输出:

test request headers
/get?show_env=1
           

(3)()

一、方法定义

二、post方法简单使用

  1、带数据的post

  2、带header的post

  3、带json的post

  4、带参数的post

  5、普通文件上传

  6、定制化文件上传

  7、多文件上传

一、方法定义:

1、到官方文档去了下()方法的定义,如下:

python接口测试_【Python自学】Python接口自动化测试的学习 - 伊凡Ivan  

2、源码:

python接口测试_【Python自学】Python接口自动化测试的学习 - 伊凡Ivan  

3、常用返回信息:

python接口测试_【Python自学】Python接口自动化测试的学习 - 伊凡Ivan  

二、post方法简单使用:

 1、带数据的post:

输出:

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "key1": "value1", 
    "key2": "value2"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "23", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "", 
    "User-Agent": "python-requests/"
  }, 
  "json": null, 
  "origin": "", 
  "url": "/post"
}
           

2、带header的post:

输出:

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "0", 
    "Host": "", 
    "User-Agent": "test request headers"
  }, 
  "json": null, 
  "origin": "", 
  "url": "/post"
}
           

3、带json的post:

输出:

{
  "args": {}, 
  "data": "{\"sites\": [{\"url\": \"\", \"name\": \"test\"}, {\"url\": \"\", \"name\": \"google\"}, {\"url\": \"\", \"name\": \"weibo\"}]}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "140", 
    "Content-Type": "application/json", 
    "Host": "", 
    "User-Agent": "python-requests/"
  }, 
  "json": {
    "sites": [
      {
        "name": "test", 
        "url": ""
      }, 
      {
        "name": "google", 
        "url": ""
      }, 
      {
        "name": "weibo", 
        "url": ""
      }
    ]
  }, 
  "origin": "", 
  "url": "/post"
}
           

4、带参数的post:

输出:

{

"args": {

"key1": "params1", 

"key2": "params2"

}, 

"data": "", 

"files": {}, 

"form": {}, 

"headers": {

"Accept": "*/*", 

"Accept-Encoding": "gzip, deflate", 

"Connection": "close", 

"Content-Length": "0", 

"Host": "", 

"User-Agent": "python-requests/"

}, 

"json": null, 

"origin": "", 

"url": "/post?key2=params2&key1=params1"

}

5.普通文件上传:

输出:

{
  "args": {}, 
  "data": "", 
  "files": {
    "file": "hello world!\n"
  }, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "157", 
    "Content-Type": "multipart/form-data; boundary=392865f79bf6431f8a53c9d56c62571e", 
    "Host": "", 
    "User-Agent": "python-requests/"
  }, 
  "json": null, 
  "origin": "", 
  "url": "/post"
}
           

6.定制化文件上传:

7.多文件上传:

# -*- coding:utf-8 -*-
import requests
import json

host = "/"
endpoint = "post"

url = ''.join([host,endpoint])
#多文件上传
files = [
    ('file1',('',open('', 'rb'))),
    ('file2', ('', open('', 'rb')))
    ]

r = (url,files=files)
print ()
           

8.流式上传:

输出:

{
  "args": {}, 
  "data": "hello world!\n", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "13", 
    "Host": "", 
    "User-Agent": "python-requests/"
  }, 
  "json": null, 
  "origin": "", 
  "url": "/post"
}
           

(4)Cookie&Session

掌握了前面几节的的内容,就可以做一些简单的http协议接口的请求发送了,但是这些还不够。HTTP协议是一个无状态的应用层协议,也就是说前后两次请求是没有任何关系的,那如果我们测试的接口之前有相互依赖关系怎么办呢(比如我要在博客园发文章,是需要先登录的),这时我们就要用到cookie和session技术来保持客户端与服务器端连接的状态,这也就是本节要介绍的内容:

一、Cookie:

1、获取cookie:

输出:

<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
{'BDORZ': '27315'}
BDORZ 27315
           

2、发送Cookie

二、Session

1、保持会话同步:

输出:

2、保存绘画信息:

输出:

3.删除已存在的会话信息,保存为None

{
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Host": "", 
    "Testa": "AAA", 
    "Testb": "BBB", 
    "User-Agent": "python-requests/"
  }
}

--------
{
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Host": "", 
    "Testb": "BBB", 
    "User-Agent": "python-requests/"
  }
}
           

4、提供默认数据:

参考:

http://docs.python-requests.org/en/master/user/quickstart/#cookies
http://docs.python-requests.org/en/master/user/advanced/#session-objects
           

(5)其他(认证&代理&超时设置)

一、认证

1、基本认证:

输出:

未提供用户名密码:401
已提供用户名密码:200
           

2、数字认证:

>>> from requests.auth import HTTPDigestAuth
>>> url = '/digest-auth/auth/user/pass'
>>> (url, auth=HTTPDigestAuth('user', 'pass'))
<Response [200]>
           

3、OAuth认证:

  参考:

二、代理

1、方法一:proxy参数:

2、方法二:设置环境变量:

3、HTTP Basic Auth使用代理方法:http://user:[email protected]/

proxies = {'http': 'http://user:pass@'}
           

三、证书验证

1、SSL证书(HTTPS):

import requests

#跳过12306 的证书验证,把 verify 设置为 False: 
r = ('', verify=False)
print 
           

2、客户端证书:

>>> ('', cert=('/path/', '/path/'))
<Response [200]>
           

or

s = ()
s.cert = '/path/'
           

四、超时配置

1 、利用timeout参数来配置最大请求时间:

r = ('', timeout=5)
           

2、设置timeout=None,告诉请求永远等待响应,而不将请求作为超时值传递

r = ('', timeout=None)
           

五、错误异常:

1、所有Requests显式抛出的异常都继承自:requests.exctptions.RequestException

2、遇到网络问题(如:DNS查询失败,拒绝连接等)时,requests会抛出一个 ConnectionError 异常

3、遇到罕见的无效HTTP响应时,Request则会抛出一个 HTTPError 异常

4、若请求超时,则抛出一个 Timeout 异常

5、若请求超过了最大的重写向次数,则会抛出一个 TooManyRedirects 异常

(6)unittest-单个用例管理:

上面主要介绍了环境搭建和requests库的使用,可以使用这些进行接口请求的发送。但是如何管理接口案例?返回结果如何自动校验?这些内容光靠上面五节是不行的,因此从本节开始我们引入python单元测试框架 unittest,用它来处理批量用例管理,校验返回结果,初始化工作以及测试完成后的环境复原工作等等。

一、单个用例管理起来比较简单,参考如下图,单个用例一般多用在调试的时候:

python接口测试_【Python自学】Python接口自动化测试的学习 - 伊凡Ivan  

二、代码如下:

输出:

(8)unittest-生成测试报告:

用例的管理问题解决了后,接下来要考虑的就是报告我问题了,这里生成测试报告主要用到  这个模块,下面简单介绍一下如何使用:

一、下载HTMLTestRunner下载:

这个模块不能通过pip安装,只能下载安装,下载地址如下:

  • 版本:http://tungwaiyip.info/software/HTMLTestRunner.html
  • python3.x版本:

二、mac下配置:

1、终端进入python环境

2、输入:

import sys
print sys.path
           

3、找到site-packages文件夹的路径并将下载的  文件拷贝到此的文件夹下 

4、在python环境下,输入 import  HTMLTestRunner 不报错即安装成功

三、使用该模块生成报告:

1、目录结构

  • case包下面有baidu,httpbin两个包
  • 每个包下面分别有两个测试的py文件
  • 每个文件里各有2个test case
  • 文件:用来执行所有的test case且生成测试报告

2、运行后生成报告如下:

python接口测试_【Python自学】Python接口自动化测试的学习 - 伊凡Ivan  

3、代码如下:

# -*- coding:utf-8 -*-
import unittest
import os
import time
import HTMLTestRunner

# 用例路径
case_path = (())
# 报告存放路径
report_path = ((), 'report')
print report_path

def all_case():
    discover = (case_path, pattern="test*.py", top_level_dir=None)

    print discover
    return discover

if __name__ == '__main__':
    # 1、获取当前时间,这样便于下面的使用。
    now = ("%Y-%m-%d-%H_%M_%S", (()))

    # 2、html报告文件路径
    report_abspath = (report_path, "result_"+now+".html")

    # 3、打开一个文件,将result写入此file中
    fp = open(report_abspath, "wb")
    runner = (stream=fp,
                                           title=u'接口自动化测试报告,测试结果如下:',
                                           description=u'用例执行情况:')
    # 4、调用add_case函数返回值
    (all_case())
    ()
           

继续阅读