看一下pytest-repeat插件代码:
import warnings
from unittest import TestCase
import pytest
def pytest_addoption(parser): #pytest添加命令行参数
parser.addoption(
'--count',
action='store',
default=1,
type=int,
help='Number of times to repeat each test')
parser.addoption(
'--repeat-scope',
action='store',
default='function',
type=str,
choices=('function', 'class', 'module', 'session'),
help='Scope for repeating tests')
def pytest_configure(config): #添加markers
config.addinivalue_line(
'markers',
'repeat(n): run the given test function `n` times.')
class UnexpectedError(Exception):
pass
@pytest.fixture
def __pytest_repeat_step_number(request): #自定义一个fixture
marker = request.node.get_closest_marker("repeat")
print('marker:{},config.count:{}'.format(marker,request.config.option.count))
count = marker and marker.args[0] or request.config.option.count
if count > 1:
try:
return request.param
except AttributeError:
if issubclass(request.cls, TestCase):
warnings.warn(
"Repeating unittest class tests not supported")
else:
raise UnexpectedError(
"This call couldn't work with pytest-repeat. "
"Please consider raising an issue with your usage.")
@pytest.hookimpl(trylast=True)
def pytest_generate_tests(metafunc): #调用pytest钩子函数,根据获取count参数话执行count次数
count = metafunc.config.option.count
m = metafunc.definition.get_closest_marker('repeat') #获取pytest.marker.repeat
if m is not None:
count = int(m.args[0])
if count > 1:
metafunc.fixturenames.append("__pytest_repeat_step_number")
def make_progress_id(i, n=count):
return '{0}-{1}'.format(i + 1, n)
scope = metafunc.config.option.repeat_scope
metafunc.parametrize(
'__pytest_repeat_step_number',
range(count),
indirect=True,
ids=make_progress_id,
scope=scope
)
可以看到pytest插件与conftest代码一致,调用pytest内置插件,即钩子函数做的一些封装上传到pypi包管理,下面介绍下怎么打个三方包,目录参考如下:
main.py:
def pytest_addoption(parser):
mygroup = parser.getgroup('encode')
mygroup.addoption("--isencode", # 注册一个命令行选项
default='true', # 参数的默认值 true,false
dest='ec', # 存储的变量
help='set is or not encode' # 帮助提示 参数的描述信息
)
def pytest_collection_modifyitems(session, config, items):
if config.getoption('ec') == 'true':
for item in items:
item.name = item.name.encode('utf-8').decode('unicode-escape')
item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')
?setup.py:
from setuptools import setup
setup(
name='pytest_encode',
url='https://github.com/xxx/pytest-encode',
version='1.1',
author="xixi",
author_email='1217097415@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=['pytest_encode'], #官方介绍是依赖包,我这边测试填了可找到源代码,不填找不到,且源代码目录与pytest_encode一致,而且打包目录也必须与pytest_encode一致,参考上面目录
keywords=[
'pytest', 'py.test', 'pytest_encode',
],
# 需要安装的依赖
install_requires=[
'pytest'
],
# 入口模块 或者入口函数,pytest11固定写法,pytest根据pytest11入口加载第三方插件
entry_points={
'pytest11': [
'pytest-encode = pytest_encode.main',
]
},
zip_safe=False
)
打包命令:
python setup.py sdist bdist_wheel
生成文件目录:
?安装命令:
pip install dist/pytest_encode-1.1-py3-none-and.whl
安装之后,运行pytest测试用例可以看看运行效果,参数化中文不会显示编码,直接显示中文,测试demo代码如下:
import pytest
@pytest.mark.parametrize('name,number',[('数学',10),('英语',20)])
# @pytest.mark.repeat(2)
def test_hook(request,name,number):
'''测试hook函数'''
print('test_hook:{}-{}'.format(name,number))
上传包:
- python3 -m pip install --user --upgrade twine
- python3 -m twine upload --repository testpypi dist/*
|