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](https://i-blog.csdnimg.cn/blog_migrate/69cc64d118800334a2ac8bd841bf9e3a.jpeg)
那么针对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](https://i-blog.csdnimg.cn/blog_migrate/855ceb9969e9ed84ca037c3ecc9555c8.jpeg)
虽然每次生成的token都是不一样的,但是结合conftest.py就可以很轻松的解决这个问题。
感谢您的关注和阅读,后续会继续更新Pytest测试实战案例文章。您也看 购买本人的书籍和实战视频课程。
《Python自动化测试实战》(无涯)【摘要 书评 试读】- 京东图书item.jd.com Python接口自动化测试实战 - 网易云课堂study.163.com![8ded9519a0a79852d9a0876f61793f5f.png](https://i-blog.csdnimg.cn/blog_migrate/5b3389beab470a928b0ea83825e558e1.jpeg)