一、pytest 插件
1.1 插件分类
- 外部插件:
pip install
安装的插件 - 本地插件:
pytest
自动模块发现机制(conftest.py
存放的) - 内置插件:代码内部的
_pytest
目录加载
1.2 常用插件
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 测试报告(了解)
二、pytest 执行顺序控制
-
场景:
- 对于集成测试,经常会有上下文依赖关系的测试用例。
- 比如10个步骤,拆成10条case,这时能知道到底执行到哪步报错。
- 用例默认执行顺序:自上而下执行。
-
解决:
- 可以通过
setup
,teardown
和fixture
来解决; - 也可以使用对应的插件。
- 可以通过
-
安装:
pip install pytest-ordering
-
用法:
@pytest.mark.run(order=2)
-
注意:
- 多个插件装饰器(>2)时,可能会发生冲突。
三、pytest测试用例并行运行与分布式
3.1 pytest并行与分布式执行
-
场景1:
- 测试用例1000条,一条用例执行1分钟,一个测试人员执行需要1000分钟。
- 通常我们会用人力成本换取时间成本,加几个人一起执行,时间就会缩短。
- 如果10个人一起执行只需要100分钟,这就是一种分布式场景。
-
场景2:
- 假设有个报名系统,对报名总数统计,数据同时进行修改操作的时候,有可能会出现问题,需要模拟这个场景,就需要多用户并发请求数据。
-
解决:
- 使用分布式并发执行测试用例;
- 分布式插件:
pytest-xdist
; - 安装运行:
pip install pytest-xdist
-
注意:
- 用例多的时候效果明显,多进程并发执行,同时支持allure。
3.2 分布式执行测试用例的原则
- 用例之间是独立的,不要有依赖关系;
- 用例执行没有顺序,随机顺序都能正常运行;
- 每个用例都能重复运行,运行结果不会影响其他用例。
四、pytest内置插件hook体系
4.1 pytest hook 介绍
-
hook
是个函数,在系统消息触发时被系统调用; - 自动触发机制;
-
hook
函数的名称是确定的; -
pytest
有非常多的hook
函数; - 使用时直接编写函数体。
4.2 pytest hook执行顺序
site-package/_pytest/hookspec.py
pytest_addoption : 添加命令行参数,运时会先读取命令行参数
pytest_collection_modifyitems : 收集测试用例,收集之后(改编码,改执行顺序)
pytest_collection_finish:收集之后的操作
pytest_runtest_setup:在调用 pytest_runtest_call 之前调用
pytest_runtest_call:调用执行测试的用例
pytest_runtest_makereport:运行测试用例,返回setup,call,teardown的执行结果
4.3 简单示例
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)
4.4 总结
-
-
hook
函数名字固定;
-
-
-
hook
函数会被自动执行;
-
-
- 执行是有先后顺序的;
-
-
pytest
定义了很多hook
函数,可以在不同阶段实现不同的功能。
-
五、pytest编写自己的插件
5.1 修改默认编码
-
pytest_collection_modifyiterms
收集上来的测试用例,实现定制化功能。 -
解决问题:
- 自定义用例的执行顺序;
- 解决编码问题(中文的测试用例名称);
- 自动添加标签。
-
含有中文的测试用例名称,改写编码格式:
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')
5.2 添加命令行参数
def pytest_addoption(parser):
mygroup = parser.getgroup("hogwarts") #group 将下面所有的 option都展示在这个group下。
mygroup.addoption("--env", #注册一个命令行选项
default='test', # 参数的默认值
dest='env', # 存储的变量,为属性命令,可以使用Option对象访问到这个值,暂用不到
help='set your run env' # 帮助提示 参数的描述信息
)
@pytest.fixture(scope='session')
def cmdoption(request):
return request.config.getoption("--env")
5.3 打包发布
-
打包发布到pypi:
- 发布到:www.pypi.org
- 代码上传到:github
-
打包项目构成:
- 源码包;
- setup.py;
- 测试包。
5.4 setup.py配置
构建文件 setup.py 代码路径:
https://ceshiren.com/t/topic/14156
from setuptools import setup,find_packages
setup(
name='pytest_encode',
url='https://github.com/xxx/pytest-encode',
version='1.0',
author="xixi",
author_email='418974188@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
)
5.5 打包命令
依赖包安装:
pip install setuptools python 的包管理工具,负责 安装和发布,尤其是安装拥有信赖关系的包。
pip install wheel 生成 *.whl 格式的安装包,本质上也是一个压缩包
打包命令:
python setup.py sdist bdist_wheel
5.6 发布命令
python3 -m pip install --user --upgrade twine ## 安装 twine 工具
python3 -m twine upload --repository testpypi dist/* ## 上传代码