pytest测试实战pdf_Pytest测试实战之token处理(十一)

HTTP是应用层的协议,同时也是无状态的协议,所以也就有了COOKIE技术的发展,关于COOKIE和SESSION以及TOKEN这些我就不详细的解释了,在我的书籍《Python自动化测试实战》里面有很详细的解释。本节继续沿着Python测试实战(十)的主题来看Pytest测试框架对token的处理和API的案例应用实战。在案例里面,应用了Flask-JWT,关于JWT部分改天我在博客里面详细的写下。对之前的源码增加token的验证,最新的案例代码为:

#!/usr/bin/python3
#coding:utf-8
from flask import  Flask,make_response,jsonify,abort,request
from flask_restful import  Api,Resource
from flask_httpauth import  HTTPBasicAuth

from flask import Flask
from flask_jwt import JWT, jwt_required, current_identity
from werkzeug.security import safe_str_cmp

app=Flask(__name__)
app.debug = True
app.config['SECRET_KEY'] = 'super-secret'
api=Api(app=app)
auth=HTTPBasicAuth()

@auth.get_password
def get_password(name):
   if name=='admin':
      return 'admin'
@auth.error_handler
def authoorized():
   return make_response(jsonify({'msg':"请认证"}),401)

books=[
   {'id':1,'author':'wuya','name':'Python接口自动化测试实战','done':True},
   {'id':2,'author':'无涯','name':'Selenium3自动化测试实战','done':False}
]


class User(object):
    def __init__(self, id, username, password):
        self.id = id
        self.username = username
        self.password = password

    def __str__(self):
        return "User(id='%s')" % self.id

users = [
    User(1, 'wuya', 'asd888'),
    User(2, 'user2', 'abcxyz'),
]

username_table = {u.username: u for u in users}
userid_table = {u.id: u for u in users}

def authenticate(username, password):
    user = username_table.get(username, None)
    if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')):
        return user

def identity(payload):
    user_id = payload['identity']
    return userid_table.get(user_id, None)

jwt = JWT(app, authenticate, identity)

class Books(Resource):
   # decorators = [auth.login_required]
   decorators=[jwt_required()]

   def get(self):
      return jsonify({'status':0,'msg':'ok','datas':books})

   def post(self):
      if not request.json:
         return jsonify({'status':1001,'msg':'请求参数不是JSON的数据,请检查,谢谢!'})
      else:
         book = {
            'id': books[-1]['id'] + 1,
            'author': request.json.get('author'),
            'name': request.json.get('name'),
            'done': True
         }
         books.append(book)
         return jsonify({'status':1002,'msg': '添加书籍成功','datas':book}, 201)


class Book(Resource):
   # decorators = [auth.login_required]
   decorators = [jwt_required()]

   def get(self,book_id):
      book = list(filter(lambda t: t['id'] == book_id, books))
      if len(book) == 0:
         return jsonify({'status': 1003, 'msg': '很抱歉,您查询的书的信息不存在'})
      else:
         return jsonify({'status': 0, 'msg': 'ok', 'datas': book})

   def put(self,book_id):
      book = list(filter(lambda t: t['id'] == book_id, books))
      if len(book) == 0:
         return jsonify({'status': 1003, 'msg': '很抱歉,您查询的书的信息不存在'})
      elif not request.json:
         return jsonify({'status': 1001, 'msg': '请求参数不是JSON的数据,请检查,谢谢!'})
      elif 'author' not in request.json:
         return jsonify({'status': 1004, 'msg': '请求参数author不能为空'})
      elif 'name' not in request.json:
         return jsonify({'status': 1005, 'msg': '请求参数name不能为空'})
      elif 'done' not in request.json:
         return jsonify({'status': 1006, 'msg': '请求参数done不能为空'})
      elif type(request.json['done'])!=bool:
         return jsonify({'status': 1007, 'msg': '请求参数done为bool类型'})
      else:
         book[0]['author'] = request.json.get('author', book[0]['author'])
         book[0]['name'] = request.json.get('name', book[0]['name'])
         book[0]['done'] = request.json.get('done', book[0]['done'])
         return jsonify({'status': 1008, 'msg': '更新书的信息成功', 'datas': book})

   def delete(self,book_id):
      book = list(filter(lambda t: t['id'] == book_id, books))
      if len(book) == 0:
         return jsonify({'status': 1003, 'msg': '很抱歉,您查询的书的信息不存在'})
      else:
         books.remove(book[0])
         return jsonify({'status': 1009, 'msg': '删除书籍成功'})

api.add_resource(Books,'/v1/api/books')
api.add_resource(Book,'/v1/api/book/<int:book_id>')

if __name__ == '__main__':
    app.run(debug=True)

在上面的的案例代码中,特别是在类里面提供了JWT,这样访问每个API都需要token的校验,如果在请求头里面没有带token的校验,就会返回401的错误信息,如下图所示:

3fdba448caf593d8819c37586e168133.png

那么针对token的获取以及token在请求头中的应用,完全可以使用pytest测试框架中的conftest.py的文件里面,这样在每个请求的接口中应用它就可以了,案例代码如下:

#!/usr/bin/python3
#coding:utf-8
import  requests
import  pytest


def getToken():
   dict1={'username':'wuya','password':'asd888'}
   r=requests.post(
      url='http://127.0.0.1:5000/auth',
      json=dict1)
   return r.json()['access_token']

@pytest.fixture()
def headers():
   return {'Authorization':'JWT {0}'.format(getToken())}

在如上的代码中,我们获取到了token,这样在每个接口的请求中带上请求头就可以很轻松的解决了token的校验,测试代码如下:

#!/usr/bin/python3
#coding:utf-8
import  pytest
import  yaml
import  os
import  requests
import  json


class Request:
   def request(self,url,method='get',**kwargs):
      if method=='get':
         return requests.request(url=url,method=method,**kwargs)
      elif method=='post':
         return requests.request(url=url,method=method,**kwargs)
      elif method=='put':
         return requests.request(url=url,method=method,**kwargs)
      elif method=='delete':
         return requests.request(url=url,method=method,**kwargs)

   def get(self,url,**kwargs):
      return self.request(url=url,method='get',**kwargs)

   def post(self,url,**kwargs):
      return self.request(url=url,method='post',**kwargs)

   def put(self,url,**kwargs):
      return self.request(url=url,method='put',**kwargs)

   def delete(self,url,**kwargs):
      return self.request(url=url,method='delete',**kwargs)


def readYaml():
   with  open('books.yaml','r')  as f:
      return list(yaml.safe_load_all(f))

@pytest.mark.parametrize('datas',readYaml())
def test_books(datas,headers):
   if datas['method']=='get':
      r=Request().get(url=datas['url'],headers=headers)
      assert  datas['expect'] in json.dumps(r.json(),ensure_ascii=False)
   elif datas['method']=='post':
      r=Request().post(url=datas['url'],json=datas['dict1'],headers=headers)
      assert datas['expect'] in json.dumps(r.json(),ensure_ascii=False)
   elif datas['method']=='put':
      r=Request().put(url=datas['url'],json=datas['dict1'],headers=headers)
      assert datas['expect'] in json.dumps(r.json(), ensure_ascii=False)
   elif datas['method']=='delete':
      r=Request().delete(url=datas['url'],headers=headers)
      assert datas['expect'] in json.dumps(r.json(), ensure_ascii=False)


if __name__ == '__main__':
    pytest.main(["-v","-s","test_jwt_token.py"])

在Pytets测试框架里面,conftest.py的模块是不能导入的,直接引用就可以了,测试如上的测试代码后,它的输出结果为:

1c65b56e9589a7f3e9982382cfe2948b.png

虽然每次生成的token都是不一样的,但是结合conftest.py就可以很轻松的解决这个问题。

感谢您的关注和阅读,后续会继续更新Pytest测试实战案例文章。您也看 购买本人的书籍和实战视频课程。

《Python自动化测试实战》(无涯)【摘要 书评 试读】- 京东图书​item.jd.com Python接口自动化测试实战 - 网易云课堂​study.163.com

8ded9519a0a79852d9a0876f61793f5f.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值