目录[-]
目录:
- 引言
- 复杂的企业级应用需求
- 如何利用pytest框架实现高内聚低耦合
——————————————————————————————————————
1.引言
不论是小型团队或是中大型企业的测试团队,在项目运行到中后期时,都会用上自动化进行接口测试验证已有功能,保证项目的健壮性及可靠性,更重要的一点,测试时间越长,越容易造成测试人员对项目脱敏,比如上个迭代还好用的功能,这个版本就不需要测试了,但是有可能在迭代过程中,新的代码影响了旧的代码,下面讲一个真实的案例。
笔者以前在做车载测试时,其他项目组遇到过一个重大生产事故,一位用户投诉,在导航页面,双指缩放/放大地图导致导航crash进而导致中控重启,中控是前装的设备,并且当前这个定制的导航版本已经装配到几百辆车厂的汽车上了,出现该问题后,很快就锁定到,是由于,缩放地图重新渲染时造成了内存泄漏,多次操作后引发内存崩溃进而导航crash,而中控系统缺少守护进程和恢复机制,导致遇到导航crash时,粗暴的进行了重启恢复,而这一个小小的操作竟能引发这么大的问题,让车企蒙受巨大损失。
版本迭代了几十次,任何人都没有办法保证测试人员可以每个版本都做到完全测试,甚至后期,只是保证迭代的功能准确就算是完成了任务,为了避免人工出现的纰漏,以及提高工作效率,使用自动化测试更加可靠。
——————————————————————————————————————
2.复杂的企业级应用需求
笔者以前还有个项目,使用敏捷开发,创建订单的主要流程有12条之多,在进行过第一次完整的功能测试后(持续一个月),笔者先用Jmeter模拟了这12条流程并配置在Jenkins自动执行,但是这样的写法,只能保证一个测试人员维护脚本,并且还要同时维护多个项目,所以后期挑选了更合适的方法进行集成,下面说明一下这个项目的要求。
项目分多种环境、包括测试环境、预生产、生产环境;角色多样,主流程包含需求方、供应商、管理后台;业务流程线性,但依赖不同角色交替执行任务,如需求方创建询盘单并邀请供应商报价,供应商得到询盘单号并提交报价单(有可能多个供应商提交)、需求方获取报价单后选择定标或二次报价、需求方定标后新建订单、供应商获取订单编号并进行订单报价、需求方付款给平台监管、供应商开始生产、供应商生产完毕后通知需求方验货、需求方验货后通知平台打款、平台打款给供应商、供需双方评价本次交易,这里涉及到3个角色的交互。
有了这么多限制,再使用Jmeter工具,就会出现很大的问题:
- 它没有办法做一个通用的类,让所有项目都应用它的配置,只能每一个项目建一个文件并维护,后期需要在Jenkins配置几个甚至十几个项目的任务。
- Jmeter非常依赖配置文件,且配置文件多数就是在软件里配置,如果配置在Jenkins上,修改配置文件、调试就会很困难。
- 缺少交互,整个测试组,只依靠少部分人维护脚本,不利于测试群体的能力提升
综上所述,使用更加灵活的Python框架pytest就比较合适了,下面先输出代码,再解释为什么使用它。
——————————————————————————————————————
3.如何利用pytest框架做到高内聚低耦合
核心设计原则:采用Pytest框架+分层Fixture注入的方式,解决多环境、多角色的问题,提升可维护性。创建一个基类,需求方、供应商、平台端继承自基类,这样也区分了角色,减少了重复代码。
目录设计:
Project_root/
----fixtures/
----__init__.py
----client_fixtures.py # 客户端登录脚手架
----inquiry_quote_flow.py # 询盘单+报价单完整流程
----cases/
----test_business_flow.py # 测试用例
----base/
----base.py # 基类
----conftest.py # 导入所有Fixture(脚手架)
————————
conftest.py:导入所有Fixture
# 导入所有Fixture
pytest_plugins = [
"fixtures.client_fixtures",
"fixtures.inquiry_quote_flow", # 合并后的流程文件
"fixtures.order_flow"
]
base.py:基类,封装账号登录、接口请求方法
class APIClient:
"""通用基类"""
def __init__(self, base_url, username, password):
self.base_url = base_url
# 创建通用 session 实例
self.session = requests.Session()
self.session.headers.update({'User-Agent': 'XXX'})
# 登录
self._login(username, password)
# 登录后更新 headers ,加上token
self.headers = {'Authorization': f'Bearer {self.token}'}
self.session.headers.update(self.headers)
def _login(self, username, password):
# 发送请求
login_url=f"{self.base_url}/login"
data = {"name": username, "pwd": password}
response = self.req("POST", login_url, json=data)
self.token = response.json()["token"]
def req(self, method, endpoint, **kwargs):
"""通用post请求,根据传入的session的对应方法"""
url = f"{self.base_url}/{endpoint}"
response = self.session.request(method, url, **kwargs)
return response
client_fixtures.py:账号登录脚手架,引用base基类,如图中,分别返回需求方、供应商的session数据,用于后续流程使用
import pytest
from base.base import APIClient
@pytest.fixture(scope="session")
def xf_client():
return APIClient(base_url="http://xxx/yyy", username="buyer", password="pwd")
@pytest.fixture(scope="session")
def gf_client():
return APIClient(base_url="http://aaa/bbb", username="supplier", password="pwd")
inquiry_quote_flow.py:询盘—定标流程,继承自client_fixtures.py里的方法获取session,提交接口请求。
cases目录下的文件,都是测试用例
# 询盘—定标全流程
# 第一步,需方创建询盘单
@pytest.fixture(scope="session")
def create_XF_id(xf_client):
response = xf_client.req(method="POST",endpoint="api/aaa",json={"enterprise":"56"})
xf_id = response.json()["id"]
yield xf_id
# 第二步,供方查询询盘单并报价
@pytest.fixture(scope="session")
def create_GF_id(gf_client,create_XF_id):
# 询盘单id,从create_XF_id传递来的参数
# print(create_XF_id)
response = gf_client.req(method="POST",endpoint="api/bbb",json={"XF_ID":create_XF_id})
# 供方id
gf_id = response.json()["id"]
yield gf_id
test_business_flow.py:测试类,用于测试cases文件夹里的“测试用例”,此时才算是一个完整的流程。
import pytest
class TestInquiryQuoteFlow:
"""测试询盘报价完整流程"""
def test_inquiry_creation(self, create_XF_id):
"""测试询盘创建"""
assert create_XF_id is not None
assert len(create_XF_id) > 10 # 假设ID有一定长度
缺少方案:
- 没有添加统一的执行文件:run_tests.py,用以执行全部测试类
- 没有添加log日志
- 没有生成pytest-html或Allure测试报告,当然也缺少邮件推送功能
- 未配置Jenkins、SVN Server 等
以上内容,在博客的其他文章里有详细的记录,不在这里赘述。
SVN Server:可以给测试组的人员配置读/写权限,基类、配置文件、日志、测试用例和测试类,可以配置给对应测试人员,而测试人员在本地可以通过tortoise更新类,SVN Server 触发Jenkins 部署有两种方法,有增量更新时部署、定时部署,这两种方法都可以使用,在之前的博客也写过。提高了测试组人员的积极性,每个测试员工可以维护自己项目,而且流程更加规范化,在每次迭代上线前,跑一次自动化脚本,提高测试报告的可靠性。
企业级CI/CD应用,对监控、安全、流程规范等更加严格,使用SVN架构,对角色权限可控,核心代码和流程包括数据配置文件等,限制读写权限进而达到安全的目的,在已有代码的基础上,加上log日志和生成测试报告,更加体现专业程度。
—————————————————————————————————————
END