目录:
- pytest配置文件
- pytest插件
- pytest测试用例执行顺序自定义pytest-ordering
- pytest测试用例并行运行与分布式运行
- pytest内置插件hook体系
- pytest插件开发
1.pytest配置文件
pytest.ini 是什么?
- pytest.ini 是 pytest 的配置文件
- 可以修改 pytest 的默认行为
- 不能使用任何中文符号,包括汉字、空格、引号、冒号等等
pytest.ini
- 修改用例的命名规则
- 配置日志格式,比代码配置更方便
- 添加标签,防止运行过程报警告错误
- 指定执行目录
- 排除搜索目录
pytest 配置- 改变运行规则(pytest放置在项目根路径下)
[pytest]
;执行check_开头和 test_开头的所有的文件,后面一定要加*
python_files = check_* test_*
;执行所有的以Test和Check开头的类
python_classes = Test* Check*
;执行所有以test_和check_开头的方法
python_functions = test_* check_*
pytest 配置- 添加默认参数
[pytest]
;执行check_开头和 test_开头的所有的文件,后面一定要加*
python_files = check_* test_*
;执行所有的以Test和Check开头的类
python_classes = Test* Check*
;执行所有以test_和check_开头的方法
python_functions = test_* check_*
;pytest 配置- 添加默认参数
addopts = -v -s --alluredir=./results
pytest 配置- 指定/忽略执行目录
[pytest]
;执行check_开头和 test_开头的所有的文件,后面一定要加*
python_files = check_* test_*
;执行所有的以Test和Check开头的类
python_classes = Test* Check*
;执行所有以test_和check_开头的方法
python_functions = test_* check_*
;pytest 配置- 添加默认参数
addopts = -v -s --alluredir=./results
;设置执行的路径
;testpaths = bilibili baidu
;忽略某些文件夹/目录
norecursedirs = result logs datas test_demo*
pytest 配置- 日志
[pytest]
;执行check_开头和 test_开头的所有的文件,后面一定要加*
python_files = check_* test_*
;执行所有的以Test和Check开头的类
python_classes = Test* Check*
;执行所有以test_和check_开头的方法
python_functions = test_* check_*
;pytest 配置- 添加默认参数
addopts = -v -s --alluredir=./results
;设置执行的路径
;testpaths = bilibili baidu
;忽略某些文件夹/目录
norecursedirs = result logs datas test_demo*
;日志开关 true false
log_cli = true
;日志级别
log_cli_level = info
;打印详细日志,相当于命令行加 -vs
addopts = --capture=no
;日志格式
log_cli_format = %(asctime)s [%(levelname)s] %(message)s (%(filename)s:%(lineno)s)
;日志时间格式
log_cli_date_format = %Y-%m-%d %H:%M:%S
;日志文件位置
log_file = ./log/test.log
;日志文件等级
log_file_level = info
;日志文件格式
log_file_format = %(asctime)s [%(levelname)s] %(message)s (%(filename)s:%(lineno)s)
;日志文件日期格式
log_file_date_format = %Y-%m-%d %H:%M:%S
2.pytest插件
pytest 插件分类
- 外部插件:pip install 安装的插件
- 本地插件:pytest 自动模块发现机制(conftest.py 存放的)
- 内置插件:代码内部的_pytest 目录加载
pytest常用的插件
pip install pytest-ordering 控制用例的执行顺序(重点)
pip install pytest-xdist 分布式并发执行测试用例(重点)
pip install pytest-dependency 控制用例的依赖关系 (了解)
pip install pytest-rerunfailures 失败重跑(了解)
pip install pytest-assume 多重较验(了解)
pip install pytest-random-order 用例随机执行(了解)
pip install pytest-html 测试报告(了解)
3.pytest测试用例执行顺序自定义pytest-ordering
pytest 执行顺序控制
场景:
对于集成测试,经常会有上下文依赖关系的测试用例。
比如 10 个步骤,拆成 10 条 case,这时候能知道到底执行到哪步报错。
用例默认执行顺序:自上而下执行
解决:
可以通过 setup,teardown 和 fixture 来解决。也可以使用对应的插件。
安装:pip install pytest-ordering
用法:@pytest.mark.run(order=2)
注意:多个插件装饰器(>2)的时候,有可能会发生冲突
代码示例一:
import pytest
@pytest.mark.run(order=2)
def test_foo():
assert True
@pytest.mark.run(order=1)
def test_bar():
assert True
代码示例二:
import pytest
@pytest.mark.third
def test_three():
assert True
@pytest.mark.seconed
def test_two():
assert True
@pytest.mark.first
def test_one():
assert True
4.pytest测试用例并行运行与分布式运行
est 并行与分布式执行
场景 1:
测试用例 1000 条,一个用例执行 1 分钟,一个测试人员执行需要 1000 分钟。
通常我们会用人力成本换取时间成本,加几个人一起执行,时间就会 缩短。
如果 10 人一起执行只需要 100 分钟,这就是一种分布式场景。
场景 2:
假设有个报名系统,对报名总数统计,数据同时进行修改操作的时候有可能出现问题,
需要模拟这个场景,需要多用户并发请求数据。
解决:
使用分布式并发执行测试用例。分布式插件:pytest-
xdist
安装及运行: pip install pytest-xdist
注意: 用例多的时候效果明显,多进程并发执行,同时支持 allure
pytest -n auto
5.pytest内置插件hook体系
pytest hook 介绍
- 是个函数,在系统消息触时被系统调用
- 自动触发机制
- Hook 函数的名称是确定的
- pytest 有非常多的勾子函数
- 使用时直接编写函数体
代码示例:
conftest.py
from typing import Optional
def pytest_collection_modifyitems(session,config,items:list):
for item in items:
item.name = item.name.encode('utf-8').decode('unicode-escape')
item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')
def pytest_runtest_setup(item: "Item") -> None:
print('hook : setup')
def pytest_runtest_teardown(item: "Item", nextitem: Optional["Item"]) -> None:
print('hook : teardown')
test_order.py
def test_demo1():
print('test hook')
运行结果:
查看hook函数:
.pytest hook函数的执行顺序:文字版顺序:
root
└── pytest_cmdline_main
├── pytest_plugin_registered
├── pytest_configure
│ └── pytest_plugin_registered
├── pytest_sessionstart
│ ├── pytest_plugin_registered
│ └── pytest_report_header
├── pytest_collection
│ ├── pytest_collectstart
│ ├── pytest_make_collect_report
│ │ ├── pytest_collect_file
│ │ │ └── pytest_pycollect_makemodule
│ │ └── pytest_pycollect_makeitem
│ │ └── pytest_generate_tests
│ │ └── pytest_make_parametrize_id
│ ├── pytest_collectreport
│ ├── pytest_itemcollected
│ ├── pytest_collection_modifyitems
│ └── pytest_collection_finish
│ └── pytest_report_collectionfinish
├── pytest_runtestloop
│ └── pytest_runtest_protocol
│ ├── pytest_runtest_logstart
│ ├── pytest_runtest_setup
│ │ └── pytest_fixture_setup
│ ├── pytest_runtest_makereport
│ ├── pytest_runtest_logreport
│ │ └── pytest_report_teststatus
│ ├── pytest_runtest_call
│ │ └── pytest_pyfunc_call
│ ├── pytest_runtest_teardown
│ │ └── pytest_fixture_post_finalizer
│ └── pytest_runtest_logfinish
├── pytest_sessionfinish
│ └── pytest_terminal_summary
└── pytest_unconfigure
简单的例子
def pytest_runtest_setup(item):
# 执行测试用例前执行的setup方法
print("setting up", item)
def pytest_runtest_call(item):
# 调用执行测试的用例
print("pytest_runtest_call")
def pytest_runtest_teardown(item):
# 执行测试用例后执行的teardown
print("pytest runtest teardown",item)
总结
- 1、hook 函数名字固定
- 2、hook 函数会被自动执行
- 3、执行是有先后顺序的
- 4、pytest 定义了很多 hook 函数,可以在不同阶段实现不同的功能
6.pytest插件开发
pytest 编写自己的插件
Pytest 编写插件 1 - 修改默认编码
pytest_collection_modifyitems 收集上来的测试用例实现定制化功能
解决问题:
- 自定义用例的执行顺序
- 解决编码问题 (中文的测试用例名称)
- 自动添加标签
conftest.py
from typing import Optional
def pytest_collection_modifyitems(session, config, items: list):
print(items)
for item in items:
item.name = item.name.encode('utf-8').decode('unicode-escape')
item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')
def pytest_runtest_setup(item: "Item") -> None:
print('hook : setup')
def pytest_runtest_teardown(item: "Item", nextitem: Optional["Item"]) -> None:
print('hook : teardown')
test_order.py
import pytest
@pytest.mark.parametrize('name', ['百度', '测试'])
def test_demo1(name):
print(f'name:{name}')
运行结果:
Pytest 编写插件 1 - 修改默认编码 (含有中文的测试用例名称,改写编码格式:)
def pytest_collection_modifyitems(session, config, items):
for item in items:
item.name = item.name.encode('utf-8').decode('unicode-escape')
item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')
Pytest 编写插件 2 - 添加命令行参数
conftest.py
import pytest
import yaml
# 定义一个命令行参数
def pytest_addoption(parser):
mygroup = parser.getgroup("hdc") # group 将下面所有的 option都展示在这个group下。
mygroup.addoption("--env", # 注册一个命令行选项
default='test', # 参数的默认值
dest='env', # 存储的变量,为属性命令,可以使用Option对象访问到这个值,暂用不到
help='set your run env' # 帮助提示 参数的描述信息
)
mygroup.addoption("--env1", # 注册一个命令行选项
default='test1', # 参数的默认值
dest='env1', # 存储的变量,为属性命令,可以使用Option对象访问到这个值,暂用不到
help='set your run env' # 帮助提示 参数的描述信息
)
# 如何针对传入的不同参数完成不同的逻辑处理
@pytest.fixture(scope='session')
def cmdoption(request):
myenv = request.config.getoption("--env", default='test')
if myenv == 'test':
datapath = 'datas/test/data.yml'
elif myenv == 'dev':
datapath = 'datas/dev/data.yml'
with open(datapath) as f:
datas = yaml.safe_load(f)
return myenv, datas
test_order.py
def test_addoption(cmdoption):
print(cmdoption)
运行结果:
项目结构:
打包发布到 pypi
- 发布到:www.pypi.org
- 代码上传到:github
打包项目构成
- 源码包
- setup.py
- 测试包
setup.py 配置
from setuptools import setup, find_packages
setup(
name='pack',
url='https://github.com/',
version='1.0',
author="tom",
author_email='123456@qq.com',
description='set your encoding and logger',
long_description='Show Chinese for your mark.parametrize(). Define logger variable for getting your log',
classifiers=[ # 分类索引 ,pip 对所属包的分类
'Framework :: Pytest',
'Programming Language :: Python',
'Topic :: Software Development :: Testing',
'Programming Language :: Python :: 3.8',
],
license='proprietary',
packages=find_packages(), # ['pytest_encode'],
keywords=[
'pytest', 'py.test', 'pytest_encode',
],
# 需要安装的依赖
install_requires=[
'pytest'
],
# 入口模块 或者入口函数
entry_points={
'pytest11': [
'pytest_encode = pytest_encode.main',
]
},
zip_safe=False
)
打包命令
依赖包安装:
pip install setuptools python 的包管理工具,负责 安装和发布,尤其是安装拥有信赖关系的包。
pip install wheel 生成 *.whl 格式的安装包,本质上也是一个压缩包
打包命令:
python setup.py sdist bdist_wheel
发布命令
py -m pip install --upgrade twine ## 安装 twine 工具
py -m twine upload --repository testpypi dist/* ## 上传代码
python打包官网:Packaging Python Projects — Python Packaging User Guide