例如测试支付业务的过程:
用户登录
加入购物
下单
支付
import json
import requests
class UserLogin:
def __init__(self, username, password):
self.username = username
self.password = password
def get_token(self):
"""获取用户登录token"""
url = "http://httpbin.org/post"
data = {
"username": self.username,
"password": self.password,
"token": "token123" # 假装这是接口返回的toKen
}
r = requests.post(url, data=data)
if r.status_code != 200:
raise ValueError("接口请求失败")
try:
r.json()
except json.decoder.JSONDecodeError:
raise ValueError("接口不是json格式")
if r.json()["headers"]["Host"] != "httpbin.org":
raise ValueError("接口返回必要参数错误")
token = r.json()["form"]["token"]
return token
if __name__ == '__main__':
user_login = UserLogin("zhangsan", "mima123")
token = user_login.get_token()
print(token)
单看接口这么封装,貌似没有问题~!但每个接口调用之后都需要经历以下过程:
判断状态码是否为 ,如果不是 说明接口不通。
仅接着判断返回值格式是否为 ,如果不是,你就无法提取数据。
检查接口返回的必要参数,例如:。
提取接口返回的数据。例如: 。
python装饰器
这里就不领着大家一步步推演如何创建一个装饰器,直接看例子。
装饰器
def dec():
"""
python装饰器
"""
def decorator(func):
def wrapper(*args, **kwargs):
func_name = func.__name__
print(f"被装饰的方法名: {func_name}")
print(f"方法的入参 args: {args}")
print(f"方法的入参 kwargs: {kwargs}")
r = func(*args, **kwargs)
print(f"方法的返回值 return: {r}")
return wrapper
return decorator
装饰器的架子大概长这个样子,重点在装饰器的入参和返回值。
用法
@dec()
def add(a, b):
c = a + b
return c
add(1, 2)
调用装饰器来装饰一个 函数
运行结果
被装饰的方法名: add
方法的入参 args: (1, 2)
方法的入参 kwargs: {}
方法的返回值 return: 3
这个装饰器可以拿到被装饰函数的、、,是不是很有意思。
接口检查装饰器
check_response() 装饰器实现
import json
from jmespath import search
def check_response(
describe: str = "",
status_code: int = 200,
ret: str = None,
check: dict = None,
debug: bool = False):
"""
checkout response data
:param describe: interface describe
:param status_code: http status code
:param ret: return data
:param check: check data
:param debug: debug Ture/False
:return:
"""
def decorator(func):
def wrapper(*args, **kwargs):
func_name = func.__name__
if debug is True:
print(f"Execute {func_name} - args: {args}")
print(f"Execute {func_name} - kwargs: {kwargs}")
r = func(*args, **kwargs)
flat = True
if r.status_code != status_code:
print(f"Execute {func_name} - {describe} failed: {r.status_code}")
flat = False
try:
r.json()
except json.decoder.JSONDecodeError:
print(f"Execute {func_name} - {describe} failed:Not in JSON format")
flat = False
if debug is True:
print(f"Execute {func_name} - response:\n {r.json()}")
if flat is True:
print(f"Execute {func_name} - {describe} success!")
if check is not None:
for expr, value in check.items():
data = search(expr, r.json())
if data != value:
print(f"Execute {func_name} - check data failed:{value}")
raise ValueError(f"{data} != {value}")
if ret is not None:
data = search(ret, r.json())
if data is None:
print(f"Execute {func_name} - return {ret} is None")
return data
else:
return r.json()
return wrapper
return decorator
核心就是在前面 装饰器的架子上扩展,增加参数和返回值校验。
代码引用了 库,主要是为了提取数据。
使用
import requests
class UserLogin:
def __init__(self, username, password):
self.username = username
self.password = password
@check_response("获取用户登录token", 200, ret="form.token", check={"headers.Host": "httpbin.org"}, debug=True)
def get_token(self):
"""获取用户登录token"""
url = "http://httpbin.org/post"
data = {
"username": self.username,
"password": self.password,
"token": "token123" # 假装是接口返回的toKen
}
r = requests.post(url, data=data)
return r
if __name__ == '__main__':
user_login = UserLogin("zhangsan", "mima123")
token = user_login.get_token()
print(token)
通过 装饰被调用接口,可以极大的简化代码。参数说明:
: 检查接口返回值状态码是否为 。
: 检查接口返回值中包含的参数。相当于对接口数据进行断言。
运行信息
Execute get_token - args: (<__main__.UserLogin object at 0x000001EF4397E1C0>,)
Execute get_token - kwargs: {}
Execute get_token - response:
{'args': {}, 'data': '', 'files': {}, 'form': {'password': 'mima123', 'token': 'token123', 'username': 'zhangsan'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '49', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.25.0', 'X-Amzn-Trace-Id': 'Root=1-62682337-2cd21bd0599368e54d2063bd'}, 'json': None, 'origin': '173.248.248.88', 'url': 'http://httpbin.org/post'}
Execute get_token - 获取用户登录token success!
token123
有了这个小小的装饰器,我们减少了很多相同的样例代码。最后,python装饰器 YYDS~!