...

案例5 基于Excel的接口测试框架

简单版

读取以下格式excel(仅第一张Sheet), 逐个发送接口,断言接口返回200, 并将状态及错误信息写回Excel

已知:Excel中接口编写格式规范如下

  1. url如果有查询参数,要写到url中,例如?a=1&b=2
  2. 如果需要添加自定义请求头 按 key:value格式编写,:左右允许有空格,每行一个
  3. 请求数据支持表单和JSON格式,如果数据形似JSON格式 (如去除前后空格或空行后以{或[开头),按JSON格式发送数据
    否则按表单格式发送数据,表单变量和请求头变量编写格式一致,已:分开,左右允许有空格,如果值以<>包裹,则视为一个文件路径,按multipart/formdata格式发送文件
    注意:不使用其他测试框架,自己写循环和异常处理,如果断言状态码为200失败则视为FAIL,其他出错认为 ERROR, 结果根据状态单元格填充不同的颜色

难度版:

增加变量提取和断言

已知:

  • 在每个接口运行后,生成一个系统变量response (requests库的响应对象),并存入一个字典格式的上下文变量中
  • 允许用户使用$上下文中的变量名 (如 $response)来使用变量,并提取生成新的变量,放入上下文字典中
  • 允许用户使用标准 Python表达式来进行断言 ,断言中支持上下文变量引用 如 $respoonse.status_code == 200
  • 断言中也可以使用前面提取的变量,下面的接口url, 请求数据,headers,数据提取,断言中也支持引用上面生成的变量

思路

数据读取及发请求

  1. 读取excel得到所有接口数据列表(跳过标题行或,和标题行组成字典格式)
  2. 按requests.request()方法的参数要求清洗组装数据 得到:
{"method": "GET", "url": "https://....", "headers": {}, "data": {}, "json": {}, "files": {}} 
  • 其中headers要求是一个字典,可以没有或为None, 例如 {"flag": "test", "token": "JWT abcd"}
  • data是所有非文件的表单数据,字典格式 例如 {"name": "kevin", "password": "test"}
  • json从excel单元格中读出来是字符串,要用json.loads() 转为字典 (或列表),可能有异常(用户填写的JSON格式不合规),如果数据解析出错,该用例状态为ERROR
  1. 遍历清理后的数据 列表,for循环发请求,断言响应状态码为200, 并做异常捕获(发请求 和 断言一起捕获),分别捕获断言异常和其他异常,断言异常时状态为FAIL, 并记录异常信息,其他异常时状态为ERROR并记录异常信息
  2. 将状态回写到原Excel,添加单元格颜色,并保存(也可以生成新Excel, 不破坏原格式)

断言及数据提取

  1. Excel单元格中读出来是一个多行字符串,例如:
excepted = '''$response.json()['form']['name']=='admin'
$response.json()['form']['password']=='test'
$response.json()['form']['password']==$flag'''
  1. 按换行分割可以得到每一个断言 描述 (字符串格式)
assert_list = excpeted.split('\n')

另外我们需要把每个语句前的\(符号去掉 , 注意:假设咱们的断言描述,暂时只允许`\)变量` 开头

assert_list = [item.lstrip('$') for item in assert_list]   # 推导式不理解的可以问我
  1. 请求后得到response变量
response = requests.request(**req)  

其中**req是字典解包, req是request方法的参数数据, 例如 {"method" : ... , "url": ..., "headers": ...}

  1. python使用exec()可以运行字符串,使用eval()可以对字符串进行表达式求值

比如,字符串形式的断言描述 "response.json()['form']['name']=='admin'"我们可以用

eval("response.json()['form']['name']=='admin'")

来用Python来计算,相等返回True, 不相等返回False, 加上assert关键词就变成了断言

assert eval("response.json()['form']['name']=='admin'")
  1. 对于断言后面的 $变量,如$flag, 假设暂时只支持引用基本类型变量(数字、字符串、列表、字典等)
    用一个字典类型的变量来保存可使用\(引用的变量,如`context = {}` 变量提取时 `"flag=\)response.headers['flag']"先按等号拆分成key = "flag" value = "\(response.headers['flag']" ·, 去掉value前的`\)并用eval()`求值得到结果,并放入context中
context["flag"] = eval(response.headers['flag']")

处理 断言语句中的 变量引用"response.json()['form']['password']=='$flag'"

可以先用python string库的Template中的变量替换,将$变量替换成对应的值

from string import Template

rendered_text = Template("response.json()['form']['password']=='$flag'").safe_substitute({"flag": "test")  

就可以吧字符串变成了response.json()['form']['password']=='test'

然后用eval求值,加assert断言即可

assert eval(response.json()['form']['password']=='test')

参考

posted @ 2023-06-14 11:14  韩志超  阅读(188)  评论(0编辑  收藏  举报