python接口测试之session&token的处理(十四)

概述:      

    1.1 cookie

      在做接口的自动化测试中,无法绕过cookie,某些时候我们需要处理,那么怎么处理?另外一个方面,什么是cookie?

cookie它的工作机制是用户识别以及状态管理,网站为了管理用户的状态会通过web的浏览器,把一些数据临时写入用户

的计算机内,用户再次访问web站点的时候,可通过通信方式取回之前存放的cookie,调用cookie时,检验cookie的时效。

    1.2 session

      session是存储在服务器端的,使用session来保持会话,在实际的产品测试中,特别是移动互联网的产品是,大多数是

token,那么token我们简单的可以理解是就是令牌,原理上是通过session来实现的,也就是说,在登录的时候,是客户端

请求服务器的一个过程,登录成功后,服务器端会生成一个随机的字符串也就是说是token,并且把token放在session中,

然后把token返回给客户端,客户端带着这个token,就可以对系统的业务进行操作。token每次登录后,返回是都是不同的

那么也就是说,在产品的接口自动化测试中,如果要对系统进行接口的自动化测试,那么首先需要获取token,获取token的

整个思路为:

A.先进行登录

B.登录成功后

C.获取token

D.把获取的token当作下一个接口的请求参数

下面通过工具,代码的方式分别来讲下如何获取token,以及对token的处理,工具我们这里使用大家经常时候并且的postman,

jmeter,代码使用python,在这里我们一次性的解决token的获取和处理。我们先来看我们需要处理的程序究竟是怎么样的,见

登录的请求过程,见截图:

见登录的响应正文,返回了token,见截图:

我们再见下一个接口,它的参数必须得带token,并且这个token是登录成功后返回的token,见截图:

见该接口的请求正文,见截图:

通过如上截图我们知道,它的请求正文是token,并且这个token与登录成功后返回的token必须是一一对应的。如上的接口

测试大概步骤为:

1、调用login的接口,login的接口调用成功后,返回token

2、登录成功后的请求都必须带这个token,否则就会出现token无效请求出现401无权限的操作,那么如何获取token,让token

成一个变量,供后面的接口来进行调用了?这就是下面要进行说的。

案例:

     2.1 postman

       我们首先在postman中完成login的接口,见截图:

请求参数见截图:

点击send,见请求成功后返回的json字符串,见截图:

现在我们来进行操作获取token和对该接口的测试用例进行断言,这些操作都是在Tests中进行的,见Tests的js代码:

注释:在如上的代码中,我们对返回的json字符串进行了解析,然后把获取的token放在了token的变量中。同时也对login的接口做了

断言,执行成功后,见断言的结果,见截图:

如果断言失败,也会提示的,这里不在详细的演示。

下面我们来进行另外一个接口,也就是infoGet的接口,见该接口的请求路由,和请求参数:

我们看到,它的请求参数是token,而这个token就是每次登录成功后的token,我们点击send看下,看执行的结果,见截图:

出现502,验证信息已失效,为什么会出现这样的结果了,这个很好理解,这是因为,我们在执行infoGet接口的时候,它的token

与我们登录成功后的token不一致,所以就是无效,我们在login的接口中,对响应正文中获取了token,并且把该token放在了变量

token,那么就需要在infoGet的接口中,我们直接调用这个变量就可以了,调用的方式为,见如下的结果:

我们把login和infoGet的接口添加到一个collection中(关于postman的collection不知道的,可以看我的博客python接口测试之postman),

该cllection的名称是blog,我们执行collecion,见截图:

点击run,来进行执行,见执行后的结果,见截图:

见ingoGet的请求正文截图:

再见infoGet接口的响应正文内容,见截图:

为了让测试具备完整性,我们给接口infoGet增加断言,见增加的断言,见截图:

再次对collection进行执行,见执行的结果:

2.2 jmeter

      下面我们使用jmeter来进行接口自动化的测试,来进行获取token和参数的传递以及调用,关于jmeter如何自动发送邮件,以及怎么和jenkins

整合到一起,可以参考Jmeter&Ant构建自动化测试平台的文章,这里就不详细的再描述。启动jmeter后,我们在测试计划中创建线程组,以及

在线程组中创建要添加的cookie,headers的数据,和断言,见截图:

我们来看HTTP消息头管理器,这里面就是headers部分,见截图:

见对每个接口测试用例Response Headers的检查点,见截图:

在接口测试中,某些变量是全局的,我们可以放在用户定义的变量,比如这里接口请求的url,登录的用户名和密码

我们可以放在用户定义的变量,其它接口用例直接调用,见截图:

在接口用例中,每个接口用例我们都得加请求的url,实际上我们有更简单的方式,就是使用HTTP请求默认值,见截图:

查看结果树很好理解,因为我们的接口用例执行成功后,我们需要看下执行的结果是通过还是失败,这里我们添加了登录的

接口用例,见login接口用例截图:

我们点击在结果树查看接口执行的结果,见截图:

依据结果我们看到,执行成功,在这里接口用例存在一个问题,就是缺少断言,缺少断言的自动化测试用例都是无效的

所以这点切记。OK,我们进行添加断言,这里我们已ID和status为断言,见添加的断言截图:

这样接口用例就是有效的,下面我们来看在jmeter中如何获取token,我们执行用例成功后,看到返回了信息中包含了

token,见登录成功后返回的详情信息:

复制代码
{
    "status":0,
    "msg":"",
    "data":
    {
        "id":600192,
        "name":"\u81ea\u52a8\u5316\u6d4b\u8bd5",
        "token":"ma750WfVczJOyjeo7PO1513521787088"
        }
}
复制代码

获取token有二种方式,分别是:

1、使用后置处理器,结合正则表达式来获取token

2、使用后置处理器的jp@gc - JSON Path Extractor来获取token,并把获取到的token放在一个变量中

这里我们使用第二种的方式,在login的接口用例中增加后置处理器,并且获取token,见截图:

获取token成功后,下来的接口用例操作就很简单了,我们来继续添加infoGet的接口用例,见截图:

我们对infoGet的接口添加断言,断言username和status,见断言的截图:

     坦白的说,使用jmeter来进行接口自动化测试是一个不错的选择,关于为什么一定要先获取token,在文章的开头我们已经解释了,在使用

jmeter进行做接口的自动化测试中,数据直接都是互相定义并且调用,这样的好处是我们不需要为了接口用例而额外的创造数据。

2.3 python处理token

     在前面我们介绍了使用postman,jmeter如何获取token以及传递token,下面我们就来使用python语言来进行实现,在这里我们使用第三方的

库requests,需要单独的安装下,安装的命令是:

                                                           pip  install -U requests

见安装的截图:

 

安装成功后,如果可以在正常的导入,说明安装OK,见截图:

      安装好requests好后,我们就可以开始了,关于requests有不清楚的,可以看Python接口测试之requests(七)

这里我们直接来进行实战,我们再来进行回顾下我们需要做的事情,我们需要做的就是登录成功后,获取token,后面的

接口都需要这个参数,所以我们需要把获取的token当作参数来进行传递,在这里我们来思考一个问题,在python的函数

中,为什么会有返回值?返回值可以干什么?python中,函数的返回值是为了给另外一个函数传递参数,传递参数可以

理解为是通过自动将对象赋值给本地变量名来实现。OK,下面我们就来使用实现这个过程,我们首先使用代码来实现

登录的接口并且获取返回的json字符串,见实现的代码:

复制代码
#!/usr/bin/env python 
#-*-coding:utf-8-*-

import requests

def getToken():
    r=requests.post(
        url='https://ecapi.parkingwang.com/v4/login',
        json={"username":"autoapi","password":"8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92","role":2},
        headers={'Content-Type':'application/json;charset=UTF-8','Parkingwang-Client-Source':'ParkingWangAPIClientWeb'},timeout=5)
    return r.json()

print getToken()
复制代码

 

见执行函数getToken后获取的json字符串:

C:\Python27\python.exe D:/git/Python/UnitCI/blog/weke.py
{u'status': 0, u'msg': u'', u'data': {u'token': u'ma7uW5KiqKpBYPQ6kBI1514038085951', u'id': 600192, u'name': u'\u81ea\u52a8\u5316\u6d4b\u8bd5'}}

Process finished with exit code 0

 

我们可以看到,获取的内容是json字符串,经过反序列化后,数据类型是字典(dict),按字典的方式来获取token就很简单的,见获取token

的代码:

复制代码
#!/usr/bin/env python 
#-*-coding:utf-8-*-

import requests

def getToken():
    r=requests.post(
        url='https://ecapi.parkingwang.com/v4/login',
        json={"username":"autoapi","password":"8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92","role":2},
        headers={'Content-Type':'application/json;charset=UTF-8','Parkingwang-Client-Source':'ParkingWangAPIClientWeb'},timeout=5)
    return r.json()['data']['token']
复制代码

 

见执行后,获取的token字符串,见截图:

下面来实现infoGet接口的测试,依据前面的案例我们知道,该接口的参数就是token,而且必须是和登录成功后返回的token

是一致,否则就会提示502的错误,token无效,我们来实现infoGet接口测试,见实现代码:

复制代码
#!/usr/bin/env python 
#-*-coding:utf-8-*-

import requests

def getToken():
    r=requests.post(
        url='https://ecapi.parkingwang.com/v4/login',
        json={"username":"autoapi","password":"8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92","role":2},
        headers={'Content-Type':'application/json;charset=UTF-8','Parkingwang-Client-Source':'ParkingWangAPIClientWeb'},timeout=5)
    return r.json()['data']['token']


def infoGet():
    r=requests.post(
        url='https://ecapi.parkingwang.com/v4/infoGet',
        json={"token":getToken()},
        headers={'Content-Type':'application/json;charset=UTF-8','Parkingwang-Client-Source':'ParkingWangAPIClientWeb'},timeout=5)
    print r.json()


infoGet()
复制代码

 

见执行infoGet函数后,返回的json字符串内容:

C:\Python27\python.exe D:/git/Python/UnitCI/blog/weke.py
{u'status': 0, u'msg': u'', u'data': {u'username': u'autoapi', u'online_agreement': 0, u'name': u'\u81ea\u52a8\u5316\u6d4b\u8bd5', u'valid_period': 0, u'id': 600192, u'phone': u'', u'pigeon_id': u'maLdrGaCEMAoS9kYW9t1514038531444', u'address': u'', u'supports': u'0', u'email': u'', u'park_code': 6666666666L}}

 

我们接着加一个接口,该接口为isSoonExpire,见测试该接口实现的代码:

复制代码
#!/usr/bin/env python 
#-*-coding:utf-8-*-

import requests

def getToken():
    r=requests.post(
        url='https://ecapi.parkingwang.com/v4/login',
        json={"username":"autoapi","password":"8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92","role":2},
        headers={'Content-Type':'application/json;charset=UTF-8','Parkingwang-Client-Source':'ParkingWangAPIClientWeb'},timeout=5)
    return r.json()['data']['token']


def infoGet():
    r=requests.post(
        url='https://ecapi.parkingwang.com/v4/infoGet',
        json={"token":getToken()},
        headers={'Content-Type':'application/json;charset=UTF-8','Parkingwang-Client-Source':'ParkingWangAPIClientWeb'},timeout=5)
    print r.json()


def isSoonExpire():
    r=requests.post(
        url='https://ecapi.parkingwang.com/v4/isSoonExpire',
        json={"token":getToken()},
        headers={'Content-Type':'application/json;charset=UTF-8','Parkingwang-Client-Source':'ParkingWangAPIClientWeb'},timeout=5)
    print r.json()
复制代码

下面我们对代码进行重构下,引入unittest,见重构后的代码:

复制代码
#!/usr/bin/env python 
#-*-coding:utf-8-*-

import requests
import  unittest

class InterfaceTest(unittest.TestCase):
    def setUp(self):
        self.url='https://ecapi.parkingwang.com/v4/'
        self.headers={'Content-Type':'application/json;charset=UTF-8','Parkingwang-Client-Source':'ParkingWangAPIClientWeb'}
        self.timeout=5

    def tearDown(self):
        pass

    def getToken(self):
        r = requests.post(
            url=self.url+'login',
            json={"username": "autoapi", "password": "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92","role": 2},
            headers=self.headers, timeout=self.timeout)
        return r.json()['data']['token']

    def test_infoGet(self):
        '''验证:测试infoGet接口是否正确'''
        r = requests.post(
            url=self.url+'infoGet',json={"token": self.getToken()},headers=self.headers, timeout=self.timeout)
        print r.json()

    def test_isSoonExpire(self):
        '''验证:测试isSoonExpire接口是否正确'''
        r = requests.post(
            url='https://ecapi.parkingwang.com/v4/isSoonExpire',json={"token":self.getToken()},headers=self.headers, timeout=5)
        print r.json()

if __name__ == '__main__':
    unittest.main(verbosity=2)
复制代码

 

如上的接口测试用例缺少断言,在这里特别强调,没有断言的自动化测试用例是无效的,是没有任何的价值的。至于具体断言什么,得格局具体的接口

测试的业务来进行,我们对如上的接口添加断言,见增加断言后的接口测试代码:

复制代码
#!/usr/bin/env python 
#-*-coding:utf-8-*-

import requests
import  unittest
import  time as t

class InterfaceTest(unittest.TestCase):
    def setUp(self):
        self.url='https://ecapi.parkingwang.com/v4/'
        self.headers={'Content-Type':'application/json;charset=UTF-8','Parkingwang-Client-Source':'ParkingWangAPIClientWeb'}
        self.timeout=5

    def tearDown(self):
        t.sleep(1)

    def getToken(self):
        r = requests.post(
            url=self.url+'login',
            json={"username": "autoapi", "password": "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92","role": 2},
            headers=self.headers, timeout=self.timeout)
        return r.json()['data']['token']

    def test_infoGet(self):
        '''验证:测试infoGet接口是否正确'''
        r = requests.post(
            url=self.url+'infoGet',json={"token": self.getToken()},headers=self.headers, timeout=self.timeout)
        self.assertEqual(r.json()['status'],0)
        self.assertEqual(r.json()['data']['username'],'autoapi')

    def test_isSoonExpire(self):
        '''验证:测试isSoonExpire接口是否正确'''
        r = requests.post(
            url='https://ecapi.parkingwang.com/v4/isSoonExpire',json={"token":self.getToken()},headers=self.headers, timeout=5)
        self.assertEqual(r.json()['status'],0)
        self.assertEqual(r.json()['data']['expire'],False)

if __name__ == '__main__':
    unittest.main(verbosity=2)
复制代码

 

执行上面的测试用例后,我们发现二个测试用例都调用了getToken()方法,而getToken()方法我们知道是登录的接口,登录成功后

获取token,言外之意也就是说登录了二次,缺点很明显,如果在N个测试用例,参数都需要token,都会调用getToken(),那么也会

出现登录N次,很实现这个方法不是我们想要的,我们要实现的是不管有多少个接口测试用例,登录只能是一次,如果登录多次,会

出现token无效502的问题,或者引起其他的问题,在这里我们把登录成功后的token存储在文件中,然后从文件中读取,这样就可以

登录一次,见实现的代码:

复制代码
#!/usr/bin/env python 
#-*-coding:utf-8-*-

import requests
import  unittest
import  time as t
import  os



def getHeaders():
    '''获取headers'''
    return {'Content-Type':'application/json;charset=UTF-8','Parkingwang-Client-Source':'ParkingWangAPIClientWeb'}

def login():
    '''把token写入到文件中'''
    r = requests.post(
        url=self.url + 'login',
        json={"username": "autoapi", "password": "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92",
              "role": 2},
        headers=getHeaders(), timeout=5)
    with open(base_dir(), 'w') as f:
        f.write(r.json()['data']['token'])


def base_dir():
    '''获取当前文件的目录'''
    return os.path.join(os.path.dirname(__file__), 'token.md')

def getToken():
    '''读取存储在文件中的token'''
    with open(base_dir(),'r') as f:
        return f.read()

class InterfaceTest(unittest.TestCase):
    def setUp(self):
        self.url='https://ecapi.parkingwang.com/v4/'

    def tearDown(self):
        t.sleep(1)

    def test_infoGet(self):
        '''验证:测试infoGet接口是否正确'''
        r = requests.post(url=self.url+'infoGet',json={"token": getToken()},headers=getHeaders(), timeout=5)
        self.assertEqual(r.json()['status'],0)
        self.assertEqual(r.json()['data']['username'],'autoapi')

    def test_isSoonExpire(self):
        '''验证:测试isSoonExpire接口是否正确'''
        r = requests.post(url=self.url+'isSoonExpire',json={"token":getToken()},headers=getHeaders(), timeout=5)
        self.assertEqual(r.json()['status'],0)
        self.assertEqual(r.json()['data']['expire'],False)

if __name__ == '__main__':
    unittest.main(verbosity=2)
复制代码

 

 

代码经过重构后,不管有多少个测试用例,我们的登录只会进行一次。接下来我们会写关于session这部分,python是如何解决的。

2.4 python处理session

     下面我们使用python来处理session的部分,下面我们来看一个例子,登录成功后,并没有返回token,只是返回了请求成功的code,

而是存储在session中,那么我们应该如何来获取session了,我们编写该登录的接口用例,看返回的json字符串是什么,见实现的代码

以及输出的截图:

在截图中我们看到,输出的json字符串只有code是200的,再没有什么,但是后面的请求都需要带上session,我们看下一个接口

请求的内容,见截图:

OK,那么就说明我们登录后必须得获取session,见获取session的代码:

通过cookies.get_dict()就可以获取session,见如上截图中获取的session内容,下面的就很简单,我们在下一个接口用例中带上session,见实现的代码:

执行如上的代码后,我们发现代码错误,错误的原因是test_access_datas()函数没有带上登录成功后的session,所以导致错误,不带session,一般直接就跳转到了

login的页面,让重新登录,那么如何解决了,我们只需要在test_access_datas()函数中,在接口请求中带上session就可以了,见修改后执行的代码:

      在本文章中我们详细的介绍了如何使用postman,jmeter,python语言来处理token和session的问题,在这里一次性的进行总结,

  • 4
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值