太长时间没有做接口自动化了,一直都在完善项目的UI自动化脚本,谨以此篇回顾一下接口自动化的一些小九九
接口自动化的用例设计不同于功能测试用例,不需要具体的某某实现步骤,但是相对于功能来说,接口自动化用例设计逻辑更复杂,写死的规定比较多,主要是为了适应自己项目而编写的一套接口测试框架。
关于接口的返回值提取
基本上所有项目都会基于登录以后再进行其他的操作。在做接口测试的时候也不例外:想要发起项目的其他请求,必须带上鉴权。接下来以我们项目为例:
登录接口
抓包获取一下信息:
请求url:https://pj-*****sit.agile168.com/login
请求体:
可以看到这里的密码被加密了。对于这种被加密的传参,有两种解决方案:
第一个问题,加密的密码怎么传参?
一。找开发获取加密方式,加密密码后传参
二。曲线救国:去数据库查这个账号的密码,一般在注册以后,接口会将加密的密码和用户其他信息保存在数据库中,我们只需要查到这个加密的密码进行传参即可。
那么这里就需要在请求发送前,执行sql,获取加密后密码进行传参,excle用例设计就必须给予这个用例一个前置sql。设计的规则我们可以自己项目的数据查询方式自定义,由于公司这里用的是mongodb,那么就把前置sql设置如下:
{'database':'atclientpoolsit','muster':'usersgm','sql':{'email': 'tyler.tang@6317.io'},'field':['encrypt_secret']}
database:要查询的库;muster:要查询的集合;mongodb查询语句:{'email': 'tyler.tang@6317.io'};encrypt_secret:要查询的字段即(密码被加密后的值)
可以看到我这里设计的是一个字典,最后一个key,field的值是一个字典,表示我们可以查询多个字段。
第二个问题,数据库查询的值要怎么作为请求数据进行传参?
这里就需要进行excel的用例设计了,我们从excel读取出来的数据都是字符串,那么可不可以用replace方法进行替换呢?怎么替换?替换的值是什么?
根据re模块的正则表达式来替换读取数据中的所有满足规则的字符串,设计思想如下:
定制一个正则表达式提取规则:#***#,凡是这种以#开头和结尾的字符串都提取出来进行替换;
替换的值哪里来?
1.来自于全局变量。
2.来自于python方法。
全局变量的值好取,但是python方法的值怎么传递给这个要替换的字符串呢?那我们就新建一个方法,用于替换这个被替换的字符串,通过字符串与函数的映射关系,执行这个函数,替换这个字符串!首先我们先新建一个生成数据的python方法,放在handle_gen_data,py中,这个模块的方法全部用来替换字符串中的占位符:由于现在还没有这种需要替换的占位符,就暂时只写两种方法
import time
from faker import Faker
from loguru import logger
from handle_config import SystemEnv
from handle_database import DatabaseOperate
#实例对象作为全局变量
fake = Faker('zh-CN')
dataBase = DatabaseOperate()
#指定对外开放的类或者函数,字符串与函数的映射
__all__ = ['gen_cur_time',
'gen_random_str']
def gen_cur_time()->str:
"""
返回13位时间戳
"""
return str(int(time.time()*1000))
def gen_random_str(min_chars=10,max_chars=12)->str:
"""
返回10-12位随机字符串
"""
return fake.pystr(min_chars=min_chars,max_chars=max_chars)
定义一个提取字符串占位符的方法,提取规则“#(\w+)#”
import re
from handle_config import SystemEnv
import handle_gen_data
from loguru import logger
def replace_mark_by_data(req_str:str,pattern:str='#(\w+)#')->str:
"""
根据正则表达式提取字符串并返回非重列表
:param req_str:被提取的字符串
:param pattern:正则表达式,默认为'#(\w+)#'
"""
mark_list = re.findall(pattern,req_str)
if mark_list:
logger.info('字符串中有要替换的mark')
to_be_replaced_mark = list(set(mark_list)) #去重列表
logger.info(f'需要替换的mark:{to_be_replaced_mark}')
for mark in to_be_replaced_mark:#遍历mark,判断全局变量SystemEnv是否有mark属性
if hasattr(SystemEnv,mark): #判断全局变量SystemEnv有mark属性,就替换
global_data = getattr(SystemEnv,mark)
logger.info(f"从全局变量类的属性中获取值来替换字符串中的mark:将 #{mark}# 替换为{global_data}")
req_str = req_str.replace(f'#{mark}#',global_data)
else:#全局变量SystemEnv没有mark属性,调用handle_gen_data模块方法返回值替换
func_data = getattr(handle_gen_data,mark)()
logger.info(f"从python方法返回的值来替换字符串中的mark:将 #{mark}# 替换为{func_data}")
req_str = req_str.replace(f'#{mark}#',func_data)
else:
logger.info('字符串中没有要替换的mark')
logger.info(f'返回的字符串为str:\n{req_str}')
return req_str #返回替换后的字符串
定义一个前置sql处理的模块,执行前置sql并将查询数据存储到全局变量类中:
from handle_replace_mark import replace_mark_by_data
from handle_database import DatabaseOperate
from handle_config import SystemEnv
from loguru import logger
handle_database = DatabaseOperate()
def exeure_sql_set_gobalattr(sql_str:str)->None:
"""
执行前置sql语句,如果是查询操作,那么设置为全局变量
全局变量名与查询sql语句中select后面的字段名保持一致;或者与field字段的列表元素保持一致
:param sql_str :excel中sql列的值
:param return :
"""
#提取前置sql
sql = replace_mark_by_data(sql_str)
if isinstance(eval(sql),dict):
sql = eval(sql)
dict_data = handle_database.search_in_mongodb(SystemEnv.MONGODB.get('uri'),sql.get('database'),sql.get('muster'),sql.get('sql'),*sql.get('field')) #默认返回一条数据
for key,value in dict_data[0].items():
setattr(SystemEnv,key,value)
logger.info(f'设置的全局变量为:{key},值:{value}')
else:
#执行sql
if sql.upper().startswith('SELECT'):
dict_data = handle_database.search_in_mysql('MYSQL',sql=sql) #默认返回一条数据
for key,value in dict_data.items():
setattr(SystemEnv,key,value)
logger.info(f'设置的全局变量为:{key},值:{value}')
else:
logger.info('执行数据库更新操作')
handle_database.modify_mysql('MYSQL',sql=sql)
SystemEnv是我们提前定义好的一个全局变量类,用于读取conf.py中环境配置。
我们在执行这个前置sql的时候,设置的全局变量属性为encrypt_secret,所以excel中的占位符要这样写#encrypt_secret#
未完待续。。。。。。。