您现在的位置是:首页 >技术交流 >pytest-编写插件网站首页技术交流
pytest-编写插件
简介pytest-编写插件
0 、文档
1、钩子函数分类
pytest中的钩子函数按功能一共分为6类:引导钩子,初始化钩子、用例收集钩子、用例执行钩子、报告钩子、调试钩子。
1.4 测试运行钩子
所有与运行测试相关的钩子都会接收一个pytest.Item对象。
- pytest_runtestloop(session: Session) 调用以开始运行测试用例循环(用例收集完成后执行)。
- pytest_runtest_protocol(item: Item, nextitem: Optional[Item])
用于实现runtest_setup/call/teardown协议,包括收集异常和调用报告hook。
runtest 协议:
参数
- Item:执行的用例
- nextitem: 指定的下一条执行的测试用例
pytest默认的runtest协议为如下三个阶段:
1、设置阶段:
这个阶段主要执行用例:前置夹具
- call = pytest_runtest_setup(item)
- report = pytest_runtest_makereport(item, call)
- pytest_runtest_logreport(report)
- pytest_exception_interact(call, report)
2、调用阶段
这个阶段负责执行测试用例- call = pytest_runtest_call(item)
- report = pytest_runtest_makereport(item, call)
- pytest_runtest_logreport(report)
- pytest_exception_interact(call, report)
3、拆解阶段
这个阶段主要执行用例:后置夹具- call = pytest_runtest_teardown(item, nextitem)
- report = pytest_runtest_makereport(item, call)
- pytest_runtest_logreport(report)
- pytest_exception_interact(call, report)
- pytest_runtest_logstart(nodeid: str, location: Tuple[str,
Optional[int], str]) 在用例setup之前调用。 - pytest_runtest_logfinish(nodeid: str, location: Tuple[str,
Optional[int], str])在用例teardown之后调用。 - pytest_runtest_setup(item: Item) 在用例执行之前调用。
- pytest_runtest_call(item: Item) 调用以执行用例。
- pytest_runtest_teardown(item: Item, nextitem: Optional[Item])
在用例执行完成后调用。 - pytest_runtest_makereport(item: Item, call: CallInfo[None])
在runtest_setup/call/teardown之后执行,用于返回当前运行的结果。 - pytest_pyfunc_call(pyfuncitem: Function) 调用基础测试功能。
2、本地编写插件:conftest.py
⚠️conftest.py文件可以有多个,并且只在当前package下生效)使用而无需导入,
推荐使用根目录下的conftest.py
from datetime import datetime
def pytest_configure():
"""
配置加载完毕之后执行,所有测试用例执行之前执行
"""
print(f"{datetime.now()} pytest开始执行")
def pytest_unconfigure():
"""
配置卸载完毕之后执行,所有测试用例执行之后执行
"""
print(f"{datetime.now()} pytest开始结束")
任意运行某条case:
3、外部插件:setuptools
- 根目录下创建setup.py文件
import setuptools
from setuptools import setup
setup(
name="demo", # 包名称
author="cxs",
description="用于替换pnc账号", # 程序的简单描述
long_description="", # 程序的详细描述
packages=setuptools.find_packages(), # 需要处理的包目录(通常为包含 __init__.py 的文件夹)
py_modules="", # 需要打包的 Python 单文件列表
setup_requires=["pytest-runner", ...], # 指定运行 setup.py 文件本身所依赖的包
tests_require=["pytest", ...], # 在测试时需要使用的依赖包
)
- 新建一个package,暂叫demo,该package下新建download.py,内容如下:
from concurrent.futures import ThreadPoolExecutor
import requests
def download_all(func, sites):
with ThreadPoolExecutor(max_workers=5) as executor:
executor.map(func, sites)
def download(url):
response = requests.get(url)
print(response.status_code)
return response
if __name__ == '__main__':
sites = ["https://www.baidu.com/", "https://codetop.cc/home",
"https://leetcode.cn/problemset/all/"]
download_all(download, sites)
- 执行
python3 setup.py sdist
; 会生成dist文件,该文件内有个.tar.gz的安装包,使用pip进行安装
- python中即可使用此包
4、实战
# -*- coding: utf-8 -*-
import pytest
import requests
import json
from _pytest.reports import TestReport
from datetime import datetime
data = {
"passed": 0,
"failed": 0,
}
url = "xxx"
headers = {
"Content-Type": "application/json;charset=utf-8"
}
def pytest_runtest_logreport(report: TestReport):
"""
统计用例执行成功/失败数
"""
if report.when == "call":
data[report.outcome] += 1
def pytest_collection_finish(session: pytest.Session):
"""
用例加载完成之后执行,包含了全部用例
"""
data["total"] = len(session.items)
def pytest_configure(config):
"""
配置加载完毕之后执行,所有测试用例执行之前执行
"""
data["start_time"] = datetime.now()
def pytest_unconfigure():
"""
配置卸载完毕之后执行,所有测试用例执行之后执行
"""
data["end_time"] = datetime.now()
data["duration"] = data["end_time"] - data["start_time"]
data["passed_rate"] = f'{data["passed"] / data["total"]:.2f}%'
content = f"""
测试时间:{data["end_time"]}
用例数量:{data["total"]}
执行时长:{data["duration"]}
测试通过:{data["passed"]}
测试失败:{data["failed"]}
测试通过率:{data["passed_rate"]}
测试报告地址:"https://www.osgeo.cn/pytest/reference.html#test-running-runtest-hooks"
"""
d = {"text":"pytest自动化测试通知:",
"attachments":
[
{
"title": "Star Wars III",
"text": content,
"color": "#ffa500"
}
]
}
res = requests.post(url=url, data=json.dumps(d), headers=headers).json()
执行结果如图:
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。