1. 封装request运行方法
我们将测试数据写到yaml文件中,通常会使用pytest框架parametrize参数化的方式读取yaml文件数据生成测试用例,于是我们可以根据这个思路来开发。
# utils/request_session.py
import requests
import re
from requests import Response
class ParserError(Exception):
pass
class HttpSession(requests.Session):
def __init__(self, base_url: str=None, timeout=10):
super().__init__()
self.base_url = base_url
self.timeout = timeout
@staticmethod
def check_url(base_url: str, url: str) -> str:
""" 拼接base_url 和 url 地址"""
if re.compile(r"(http)(s?)(://)").match(url):
return url
elif base_url:
if re.compile(r"(http)(s?)(://)").match(base_url):
return f"{base_url.rstrip('/')}/{url.lstrip('/')}"
else:
raise ParserError("base url do yo mean http:// or https://!")
def send_request(self, method, url, base_url=None, **kwargs) -> Response:
"""判断是否有传base_url, 没有则用公共的base_url"""
url = self.check_url(base_url, url) if base_url else self.check_url(self.base_url, url)
return self.request(method, url, timeout=self.timeout, verify=False, **kwargs)
# 获取yaml文件的模块,utils/read_file.py
import yaml
from pathlib import Path
def read_yaml(file_path: Path):
"""
读取 yaml 数据,转 python 类型
:param file_path:
:return: dict
"""
with open(file_path, 'r', encoding='utf-8') as fp:
data = yaml.safe_load(fp)
return data
if __name__ == '__main__':
file_path = Path(__file__).parent.parent.joinpath('data', 'login.yml')
res = read_yaml(file_path)
print(res.items())
print(type(res)) # -->dict
1.1 配置base_url
通常我们不会将base_url写进yaml文件中,yaml文件中也只是放url的相对路径。
全局环境地址切换使用 base_url 来实现,先安装插件:> pip install pytest-base-url
项目根目录新增 pytest.ini 文件,写入以下内容:
[pytest]
filterwarnings =
ignore::DeprecationWarning
ignore::urllib3.exceptions.InsecureRequestWarning
base_url=http://124.20.143.221:8201
2. 根据关键字运行用例
如何根据关键字去运行用例呢,这里的核心思想就是使用反射机制
来运行关键字。
2.1 什么是反射
反射的本质是通过字符串去调用某对对象的方法/属性,或者调用模块中的函数等。python中提供了四个重要的方法.
- getattr获取对象属性/对象方法
- hasattr判断对象是否有对应的属性及方法
- delattr删除指定的属性
- setattr为对象设置内容
2.2 getattr获取对象属性/方法
如下代码块,里面有属性和方法,我们正常调用是先实例化再调用对象和方法。
class Page:
name = "hello"
des = "world"
def click():
print("click button")
def clear(self):
print("clear")
def fill(self, text):
print(f"input text: {text}")
if __name__ == '__main__':
p = Page()
print(p.name)
print(p.click())
当我们想批量操作的时候,比如只需要知道关键字"click","clear","fill" 就可以调用对应的方法了.
p = Page()
# 获取对象属性
name = getattr(p, "name")
print(name)
# 调用对象方法
getattr(p, "click")()
# 方法带参数
getattr(p, "fill")("hello world")
我们在调用之前事先不知道有对应方法,所以先判断后调用,hasattr判断对象是否有对应的属性及方法。
p = Page()
# 先判断后调用
if hasattr(p, "click"):
getattr(p, "click")()
delattr 删除指定的属性: delattr(p, "click") print(p.click)
setattr 为对象设置内容, 可以动态添加属性和方法: setattr(p, 'age', 22) print(getattr(p, 'age'))
`
了解了这个原理后,我们就可以来编写我们的模块
# utils/run.py
"""利用反射运行关键字"""
class RunByKey:
def __init__(self, session):
self.session = session
@staticmethod
def name(value):
print(f'用例名称:{value}')
def request(self, value: dict):
print(f"执行request: {value}")
res = self.session.send_request(**value)
return res
def run(self, data: dict):
for key, value in data.items():
if hasattr(self, key):
res = getattr(self, key)(value)
print(f"=========当前的key:{key}")
if key == "request":
print(f"执行结果:{res.text}")
else:
print(f"关键字未定义: {key}")
接下来我们编写test_login.py来运行这个yaml文件中的用例。我们yaml文件中写了2条测试用例,base_url在pytest.ini中已经定义了
test_login:
name: 登录成功
request:
url: /api/v1/auth/login
method: POST
json:
username: "admin"
password: "Admin@22"
test_login2:
name: 登录失败
request:
url: /api/v1/auth/login
method: POST
json:
username: "admin"
password: "Admin@2233"
import pytest
from utils import read_file
from pathlib import Path
from utils.request_session import HttpSession
from utils.run import RunByKey
# 获取文件路径
file_path = Path(__file__).parent.joinpath('data', 'login.yml')
@pytest.mark.parametrize('name, value', read_file.read_yaml(file_path).items())
def test_login(name, value, base_url):
print(f"测试用例名称: {name}")
print(f"测试数据: {value}") # data ---dict
print(f"base_url: {base_url}")
s = HttpSession(base_url=base_url)
run = RunByKey(s)
run.run(value)
运行结果如下图所示:
现在可以使用关键字来运行yaml文件的测试用例了,但是呢,这是各个参数都是写死的传入,如果我们需要引入变量,该怎么传入呢,后面将会解决这个问题。