测试学习记录,仅供参考!
项目实战演练-封装方法
从yaml文件读取接口信息发起请求
1、 修改项目根目录 unit_tools 软件包文件下"sendrequests.py"文件内容;
-
先导包引入 unit_tools 软件包下"handle_data"软件包"yaml_handler.py"文件中的 "read_yaml" 读取 yaml 文件数据方法;
-
再测试验证调用读取 yaml 文件数据方法读取到指定的目标信息;
-
然后自定义各个变量拿到所需要的数据值;
-
最后实例化 SendRequests 类,调用类里面的方法,依次传入请求地址 url、请求方式 method、请求头和请求参数;
引入模块--导包
import requests
from requests import utils
import re
from unit_tools.handle_data.yaml_handler import read_yaml使用类的方式去封装--定义一个类 SendRequests
class SendRequests:
# 使用 init 创建构造函数
def init(self):
# 占位符
pass# 类方法 加上 @classmethod 就是一个类方法 # 类方法不能去访问实例 初始化构造函数里面的属性,只能访问类的属性--需要把 self 改为 cls @classmethod # 定义一个方法 _text_encode --传一个接口返回的文本格式 res_text def _text_encode(cls, res_text): """ 处理接口返回值出现unicode编码时 例如:\\u767b :param res_text: :return: """ # 调用 re.search --去搜索这个文本(匹配正则表达式),第二个参数是接口的返回值res_text match = re.search(r"\\u[0-9a-fA-F]{4}", res_text) # 判断匹配的结果是否存在 if match: # 当匹配的结果存在时,把接口的返回值进行处理转换--先把它转码然后再解码 result = res_text.encode().decode('unicode_escape') else: # 若不存在,则直接把接口的返回值传过来 result = res_text # 最后return return result # 直接封装一个 send_request 方法--给它传一个可变数量的参数 **kwargs def send_request(self, **kwargs): # 创建一个会话--使用 requests.Session() 调用这个类并把它的结果返回出去 # 把创建的这个会话对象返回赋值给 session session = requests.Session() # 定义一个变量response并赋值为空 response = None # 这里最好再添加一个异常处理 try: # 直接session.调用request()把可变数量参数**kwargs给它传进来,返回赋值给 response response = session.request(**kwargs) # 通过调用requests这个模块--通过接口的返回值 response.cookies # 通过接口的返回对象获取cookies--定义变量set_cookie去接收 set_cookie = requests.utils.dict_from_cookiejar(response.cookies) # 判断是否有这个cookie if set_cookie: print(f'获取到Cookies: {set_cookie}') # 调用self._text_encode方法--结果返回值response.text res = self._text_encode(response.text) print(res) # 连接异常 requests.exceptions.ConnectionError except requests.exceptions.ConnectionError: print("接口请求异常,可能是request的链接数过多或者速度过快导致程序报错!") # 请求异常 except requests.exceptions.RequestException as e: print(f'请求异常,请检查系统或数据是否正常!错误信息为:{e}') # 把发起接口请求的结果返回出去 return response # 再定义一个方法 execute_api_request--再来封装一个方法 # 这里传的参数比较多,一部分是data.yaml配置文件中的字段,最终根据request里面所需要的参数 # api_name, url, method, header--yaml配置文件;case_name--自定义; # cookie默认为空,file文件上传,这里也传空;最后再传可变数量参数 **kwargs def execute_api_request(self, api_name, url, method, header, case_name, cookie=None, file=None, **kwargs): """ 发起接口请求 :param api_name: 接口名称--后续打印日志会用到 :param url: 接口地址 :param method: 请求方法 :param header: 请求头 :param case_name: 测试用例名称--后续打印日志会用到 :param cookie: cookie :param file: 文件上传 :param kwargs: 未知数量的关键字参数 :return: """ # 直接使用self.调用上面封装的方法send_request() # 传参格式,这里的关键字务必跟request里面的关键字参数一致 # 关键字要接收的参数值是 上面定义的这个函数execute_api_request中的 参数, # 需要哪个传给哪个,一一对应即可--再把未知数量传参**kwargs给放进来 # timeout=10--接口超时设置10秒;verify=False--忽略HTTPS证书校验,默认verify=None # 最后把结果给返回出去并赋值给 response response = self.send_request(method=method, url=url, headers=header, cookies=cookie, files=file, timeout=10, verify=False, **kwargs) # 使用 return 直接返回结果 return response这里使用登录接口进行测试验证
if name == 'main':
# 调用引用的模块里面的read_yaml()方法--相对路径 .././datas/login.yaml
# 再拿到列表中的第一组元素--ps:不确定时可以打印出来详细查看
data = read_yaml('.././datas/login.yaml')[0]
# 地址--可以看到列表里面又嵌套了一个字典--使用键值对的方式取相对应的 key 值
url = data['baseInfo']['url']
# 请求方法 同样依次取 key 值
method = data['baseInfo']['method']
# 请求头 同样依次取 key 值--一般都会需要请求头,除非特殊处理
header = data['baseInfo']['header']
# 入参--找到与baseInfo同级的testCase进行取值--testCase里面是一个列表--它里面只有一组数据--取对应值data
req_data = data['testCase'][0]['data']# 查看校验封装的方法能不能正常运行--SendRequests() 实例化这个类--把结果返回出去给自定义的变量对象 send send = SendRequests() # 这里传上面刚刚定义的变量 地址 url、请求方式 method、表头 header、入参 req_data # 这里请求头在接口中已特殊处理过,一般情况下都是需要正常传递的 res = send.execute_api_request(api_name=None, url=url, method=method, header=None, case_name=None, data=req_data) print(res)
2、此时运行 sendrequests.py 文件,可以看到控制台信息有提示"请求异常",这是因为 yaml 文件中对应的 url 信息(url: /dar/user/login)只写了接口地址,请求地址 url 里面没有传服务器 IP 地址;

如若不清楚所读取目标文件数据信息,可自行调试打印查看其目标数据是什么格式,是怎么的数据信息;查看成功后别忘记"注释掉"或者"删除";
if __name__ == '__main__':
# 调用引用的模块里面的read_yaml()方法--相对路径 .././datas/login.yaml
# 再拿到列表中的第一组元素--ps:不确定时可以打印出来详细查看
data = read_yaml('.././datas/login.yaml')[0]
print(f'项目根目录datas目录文件login.yaml文件中数据信息data: {data}')
# 地址--可以看到列表里面又嵌套了一个字典--使用键值对的方式取相对应的 key 值
url = data['baseInfo']['url']
print(f'请求地址url: {url}')
# 请求方法 同样依次取 key 值
method = data['baseInfo']['method']
print(f'请求方式method: {method}')
# 请求头 同样依次取 key 值--一般都会需要请求头,除非特殊处理
header = data['baseInfo']['header']
print(f"请求头header: {header}")
# 入参--找到与baseInfo同级的testCase进行取值--testCase里面是一个列表--它里面只有一组数据--取对应值data
req_data = data['testCase'][0]['data']
print(f"请求参数req_data: {req_data}")
# 查看校验封装的方法能不能正常运行--SendRequests() 实例化这个类--把结果返回出去给自定义的变量对象 send
send = SendRequests()
# 这里传上面刚刚定义的变量 地址 url、请求方式 method、表头 header、入参 req_data
# 这里请求头在接口中已特殊处理过,一般情况下都是需要正常传递的
res = send.execute_api_request(api_name=None, url=url, method=method, header=None, case_name=None,
data=req_data)
print(res)

3、再次修改 sendrequests.py 文件内容,目前暂时使用字符串进行拼接,后续如有需要可以再写入配置文件里面;
# 引入模块--导包
import requests
from requests import utils
import re
from unit_tools.handle_data.yaml_handler import read_yaml
# 使用类的方式去封装--定义一个类 SendRequests
class SendRequests:
# 使用 __init__ 创建构造函数
def __init__(self):
# 占位符
pass
# 类方法 加上 @classmethod 就是一个类方法
# 类方法不能去访问实例 初始化构造函数里面的属性,只能访问类的属性--需要把 self 改为 cls
@classmethod
# 定义一个方法 _text_encode --传一个接口返回的文本格式 res_text
def _text_encode(cls, res_text):
"""
处理接口返回值出现unicode编码时 例如:\\u767b
:param res_text:
:return:
"""
# 调用 re.search --去搜索这个文本(匹配正则表达式),第二个参数是接口的返回值res_text
match = re.search(r"\\u[0-9a-fA-F]{4}", res_text)
# 判断匹配的结果是否存在
if match:
# 当匹配的结果存在时,把接口的返回值进行处理转换--先把它转码然后再解码
result = res_text.encode().decode('unicode_escape')
else:
# 若不存在,则直接把接口的返回值传过来
result = res_text
# 最后return
return result
# 直接封装一个 send_request 方法--给它传一个可变数量的参数 **kwargs
def send_request(self, **kwargs):
# 创建一个会话--使用 requests.Session() 调用这个类并把它的结果返回出去
# 把创建的这个会话对象返回赋值给 session
session = requests.Session()
# 定义一个变量response并赋值为空
response = None
# 这里最好再添加一个异常处理
try:
# 直接session.调用request()把可变数量参数**kwargs给它传进来,返回赋值给 response
response = session.request(**kwargs)
# 通过调用requests这个模块--通过接口的返回值 response.cookies
# 通过接口的返回对象获取cookies--定义变量set_cookie去接收
set_cookie = requests.utils.dict_from_cookiejar(response.cookies)
# 判断是否有这个cookie
if set_cookie:
print(f'获取到Cookies: {set_cookie}')
# 调用self._text_encode方法--结果返回值response.text
res = self._text_encode(response.text)
print(res)
# 连接异常 requests.exceptions.ConnectionError
except requests.exceptions.ConnectionError:
print("接口请求异常,可能是request的链接数过多或者速度过快导致程序报错!")
# 请求异常
except requests.exceptions.RequestException as e:
print(f'请求异常,请检查系统或数据是否正常!错误信息为:{e}')
# 把发起接口请求的结果返回出去
return response
# 再定义一个方法 execute_api_request--再来封装一个方法
# 这里传的参数比较多,一部分是data.yaml配置文件中的字段,最终根据request里面所需要的参数
# api_name, url, method, header--yaml配置文件;case_name--自定义;
# cookie默认为空,file文件上传,这里也传空;最后再传可变数量参数 **kwargs
def execute_api_request(self, api_name, url, method, header, case_name, cookie=None, file=None, **kwargs):
"""
发起接口请求
:param api_name: 接口名称--后续打印日志会用到
:param url: 接口地址
:param method: 请求方法
:param header: 请求头
:param case_name: 测试用例名称--后续打印日志会用到
:param cookie: cookie
:param file: 文件上传
:param kwargs: 未知数量的关键字参数
:return:
"""
# 直接使用self.调用上面封装的方法send_request()
# 传参格式,这里的关键字务必跟request里面的关键字参数一致
# 关键字要接收的参数值是 上面定义的这个函数execute_api_request中的 参数,
# 需要哪个传给哪个,一一对应即可--再把未知数量传参**kwargs给放进来
# timeout=10--接口超时设置10秒;verify=False--忽略HTTPS证书校验,默认verify=None
# 最后把结果给返回出去并赋值给 response
response = self.send_request(method=method, url=url, headers=header, cookies=cookie, files=file, timeout=10,
verify=False, **kwargs)
# 使用 return 直接返回结果
return response
# 这里使用登录接口进行测试验证
if __name__ == '__main__':
# 调用引用的模块里面的read_yaml()方法--相对路径 .././datas/login.yaml
# 再拿到列表中的第一组元素--ps:不确定时可以打印出来详细查看
data = read_yaml('.././datas/login.yaml')[0]
# 地址--可以看到列表里面又嵌套了一个字典--使用键值对的方式取相对应的 key 值
# url = data['baseInfo']['url']
url = 'http://127.0.0.1:8787' + data['baseInfo']['url']
# 请求方法 同样依次取 key 值
method = data['baseInfo']['method']
# 请求头 同样依次取 key 值--一般都会需要请求头,除非特殊处理
header = data['baseInfo']['header']
# 入参--找到与baseInfo同级的testCase进行取值--testCase里面是一个列表--它里面只有一组数据--取对应值data
req_data = data['testCase'][0]['data']
# 查看校验封装的方法能不能正常运行--SendRequests() 实例化这个类--把结果返回出去给自定义的变量对象 send
send = SendRequests()
# 这里传上面刚刚定义的变量 地址 url、请求方式 method、表头 header、入参 req_data
# 这里请求头在接口中已特殊处理过,一般情况下都是需要正常传递的
res = send.execute_api_request(api_name=None, url=url, method=method, header=None, case_name=None,
data=req_data)
print(res)
再次修改后运行就没有问题了,请求成功,能够获取到所需要的响应结果信息;

如若运行 sendrequests.py 文件时,会报连接异常"接口请求异常,可能是request的链接数过多或者速度过快导致程序报错!",得启动测试项目接口服务;

把所需要的字段写入到指定的目标文件中
在获取响应结果数据信息成功后,需要把对应的 "token"值和"userId"值写入指定的文件中(目标文件自定义,例如:项目根目录下的 yaml 文件 extract.yaml ),操作步骤如下:
-
继续引入 unit_tools 软件包下 handle_data 软件包 yaml_handler.py 文件中的 "write_yaml" 写入 yaml 文件数据方法;就是读取和写入方法均导入了;
-
再接着把响应结果返回值字符串格式转换为 JSON 格式,转换成功后获取对应的 token 值和 userId 值(这里 token 值是随机的,而 userId 值则是固定的,具体建议可根据实际接口返回);
-
最后使用 write_yaml 方法写入到目标指定文件里面;
引入模块--导包
import requests
from requests import utils
import re
from unit_tools.handle_data.yaml_handler import read_yaml, write_yaml使用类的方式去封装--定义一个类 SendRequests
class SendRequests:
# 使用 init 创建构造函数
def init(self):
# 占位符
pass# 类方法 加上 @classmethod 就是一个类方法 # 类方法不能去访问实例 初始化构造函数里面的属性,只能访问类的属性--需要把 self 改为 cls @classmethod # 定义一个方法 _text_encode --传一个接口返回的文本格式 res_text def _text_encode(cls, res_text): """ 处理接口返回值出现unicode编码时 例如:\\u767b :param res_text: :return: """ # 调用 re.search --去搜索这个文本(匹配正则表达式),第二个参数是接口的返回值res_text match = re.search(r"\\u[0-9a-fA-F]{4}", res_text) # 判断匹配的结果是否存在 if match: # 当匹配的结果存在时,把接口的返回值进行处理转换--先把它转码然后再解码 result = res_text.encode().decode('unicode_escape') else: # 若不存在,则直接把接口的返回值传过来 result = res_text # 最后return return result # 直接封装一个 send_request 方法--给它传一个可变数量的参数 **kwargs def send_request(self, **kwargs): # 创建一个会话--使用 requests.Session() 调用这个类并把它的结果返回出去 # 把创建的这个会话对象返回赋值给 session session = requests.Session() # 定义一个变量response并赋值为空 response = None # 这里最好再添加一个异常处理 try: # 直接session.调用request()把可变数量参数**kwargs给它传进来,返回赋值给 response response = session.request(**kwargs) # 通过调用requests这个模块--通过接口的返回值 response.cookies # 通过接口的返回对象获取cookies--定义变量set_cookie去接收 set_cookie = requests.utils.dict_from_cookiejar(response.cookies) # 判断是否有这个cookie if set_cookie: print(f'获取到Cookies: {set_cookie}') # 调用self._text_encode方法--结果返回值response.text res = self._text_encode(response.text) print(res) # 连接异常 requests.exceptions.ConnectionError except requests.exceptions.ConnectionError: print("接口请求异常,可能是request的链接数过多或者速度过快导致程序报错!") # 请求异常 except requests.exceptions.RequestException as e: print(f'请求异常,请检查系统或数据是否正常!错误信息为:{e}') # 把发起接口请求的结果返回出去 return response # 再定义一个方法 execute_api_request--再来封装一个方法 # 这里传的参数比较多,一部分是data.yaml配置文件中的字段,最终根据request里面所需要的参数 # api_name, url, method, header--yaml配置文件;case_name--自定义; # cookie默认为空,file文件上传,这里也传空;最后再传可变数量参数 **kwargs def execute_api_request(self, api_name, url, method, header, case_name, cookie=None, file=None, **kwargs): """ 发起接口请求 :param api_name: 接口名称--后续打印日志会用到 :param url: 接口地址 :param method: 请求方法 :param header: 请求头 :param case_name: 测试用例名称--后续打印日志会用到 :param cookie: cookie :param file: 文件上传 :param kwargs: 未知数量的关键字参数 :return: """ # 直接使用self.调用上面封装的方法send_request() # 传参格式,这里的关键字务必跟request里面的关键字参数一致 # 关键字要接收的参数值是 上面定义的这个函数execute_api_request中的 参数, # 需要哪个传给哪个,一一对应即可--再把未知数量传参**kwargs给放进来 # timeout=10--接口超时设置10秒;verify=False--忽略HTTPS证书校验,默认verify=None # 最后把结果给返回出去并赋值给 response response = self.send_request(method=method, url=url, headers=header, cookies=cookie, files=file, timeout=10, verify=False, **kwargs) # 使用 return 直接返回结果 return response这里使用登录接口进行测试验证
if name == 'main':
# 调用引用的模块里面的read_yaml()方法--相对路径 .././datas/login.yaml
# 再拿到列表中的第一组元素--ps:不确定时可以打印出来详细查看
data = read_yaml('.././datas/login.yaml')[0]
# 地址--可以看到列表里面又嵌套了一个字典--使用键值对的方式取相对应的 key 值
# url = data['baseInfo']['url']
url = 'http://127.0.0.1:8787' + data['baseInfo']['url']
# 请求方法 同样依次取 key 值
method = data['baseInfo']['method']
# 请求头 同样依次取 key 值--一般都会需要请求头,除非特殊处理
header = data['baseInfo']['header']
# 入参--找到与baseInfo同级的testCase进行取值--testCase里面是一个列表--它里面只有一组数据--取对应值data
req_data = data['testCase'][0]['data']# 查看校验封装的方法能不能正常运行--SendRequests() 实例化这个类--把结果返回出去给自定义的变量对象 send send = SendRequests() # 这里传上面刚刚定义的变量 地址 url、请求方式 method、表头 header、入参 req_data # 这里请求头在接口中已特殊处理过,一般情况下都是需要正常传递的 res = send.execute_api_request(api_name=None, url=url, method=method, header=None, case_name=None, data=req_data) # 这里res的结果返回值response.text--它打印的是一个text属于字符串,字符串不能通过key值去取--所以需要先转换成一个json格式 res_json = res.json() # 转换成功之后即可获取它的token值 token = res_json['token'] # 获取它的userId user_id = res_json['userId'] # 调用write_yaml()方法写入文件 write_yaml({'token': token, 'userId': user_id})

运行 sendrequests.py 文件成功后,查看需要写入到的指定目标(extract.yaml)文件;
如若多次执行 sendrequests.py 文件,则会多次写入,出现重复的数据,后续可考虑优化;

未完待续。。。