1

Pytest进阶使用 - 北冥有鱼。

 1 year ago
source link: https://www.cnblogs.com/joker108/p/16795760.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

fixture

  • 命令灵活:对于setup,teardown可以省略

  • 数据共享:在conftest.py配置里写方法可以实现数据共享,不需要import导入,可以跨文件共享

  • scope的层次及神奇的yield组合相当于各种setup和teardown

  • 实现参数化

测试用例执行时,有的用例需要登录才能执行,有些用例不需要登录。

setup和teardown无法满足这种情况,但是fixture可以。默认scope(范围):function

    • 导入pytest

    • 在登录的函数上添加@pytest.fixture()

    • 在要使用的测试方法中传入(登录函数名称)

    • 不传入的就不登录,直接执行测试方法。

fixture作用域

取值 范围 说明
function 函数级 每一个函数或方法都会调用
class 类级别 每个测试类只执行一次
module 模块级 每个.py文件调用一次
package 包级 每个python包只调用一次(暂不支持)
session 会话 每次会话只需要运行一次,会话内所有方法及类,模块都共享这个方法
  • session是在整个项目中只执行一次的代码

yield关键字

你已经可以将测试方法【前要执行的或依赖的】解决了,那测试方法后销毁清除数据要如何进行?

通过在fixture函数中加入yield关键字,yield是调用第一次返回结果,第二次执行它下面的语句返回。

@pytest.fixture(scope=module)

在登录的方法中加yield,之后加销毁清除的步骤

import pytest
 
@pytest.fixture()
def login():
    # setup
    token = '1235236fdg'
    print("登录功能")
    yield token# 相当于return 返回none
    # teardown
    print("退出登录操作")
 
def test_search():
    print("搜索功能")
 
def test_cart(login):
    print(f"token:{login}")
    print("购物车")

你与其他工程师合作一起开发时,公共的模块要在不同文件中,要在大家都访问的到的地方

使用conftest.py这个文件进行数据共享,并且它可以放在不同位置起着不同的范围共享作用

    • conftest文件名不能换

    • 放在项目下是全局的数据共享

    • 系统执行到参数login时先从本模块中查找是否有这个名字的变量之类的

    • 之后在conftest.py中找是否含有

将登录模块带@pytest.fixture写在conftest.py

不想原测试方法有任何改动,或全部都自动实现自动应用,没特例,也都不需要返回值时可以选择自动应用的方法

使用fixture中的参数autouse=True实现

在方法上面加@pytest.fixture(autouse=Ture)

测试离不开数据,为了数据灵活,一般数据都是通过参数传的

使用fixture中的固定参数request传递

在fixture中添加@pytest.fixture(params=[1,2,3,'linda'])

在方法参数写request,方法体里面使用request.param接受参数

@pytest.fixture(params=['hogwarts','joker'])
def demo_params(request):
    print(f'用户名为:{request.param}')
    return request.param


def test_demo(demo_params):
    print(f"数据为:{demo_params}")
  • 注意:fixture的参数是params,而调用的时候是request.param,没有s
  • 模拟setup,teardown(一个用例可以引用多个fixture)

  • yield的用法

  • 作用域(session,module,类级别,方法级别)

  • 自动执行(autouse参数)

  • conftest.py用法,一般会把fixture写在conftest.py文件中

  • 实现参数化

pytest.ini文件

  • pytest.ini是pytest的配置文件

  • 可以修改pytest的默认行为

  • 不能使用中文符号,包括汉字,空格 ,引号,冒号等

  • 修改用例的命名规则

  • 配置日志格式,比代码配置方便很多

  • 添加标签,防止运行过程报警告错误

  • 指定执行目录

  • 排除搜索目录

改变pytest运行规则

[pytest]
;执行check_开头的所有文件
python_files = check_* test_*
;执行所有的以Test和Check开头的类
python_classes = Test* Check*
;执行所有以test_和check_开头的方法
python_functions = check_* test_*
  • 注意:win系统的pytest.ini文件不能写中文,注释也不行

pytest配置-添加默认参数

addopts = -v -s --alluredir=./results

指定/忽略执行目录

;设置执行得路径
;testpaths = bilibili baidu
;忽略某些文件夹/目录
norecursedirs = result logs datas test_demo*
  • pytest插件分类

    • 外部插件:pip install 安装的插件

    • 本地插件:pytest自动模块发现机制(conftest.py存放的)

    • 内置插件:代码内部的_pytest目录加载(hook函数)

官网:https://pypi.org/

2962965-20221016104040289-2065120904.png

每一种测试框架收集测试用例的顺序是不一样的

pytest执行顺序控制

对于集成测试,经常会有上下文依赖关系的测试用例。如十个步骤,拆分成十个case,这时候能知道到底执行到哪步报错。

用例默认执行顺序:自上而下执行

可以通过setup,teardown和fixture来解决,也可以使用pytest-ordering插件来解决

  • 安装:pip install pytest-ordering

  • 用法:@pytest.mark.run(order=2)

  • 注意:多个插件装饰器(>2)的时候,有可能会发生冲突

并行与分布式并发执行(xdist)

  • 测试用例1000条,一个用例执行1分钟,一个测试人员需要1000分钟,通常我们会用人力成本换取时间成本,加几个人一起执行,时间就会缩短。这就是一种分布式场景。
  • 假设有个报名系统,对报名总数进行统计,数据同时进行修改操作的时候有可能出现问题,需要模拟这个场景,需要多用户并发请求数据
  • 使用分布式并发执行测试用例,分布式插件:pytest-xdist

  • 安装:pip install pytest-xdist

  • 注意:用例多的时候效果明显,多进程并发执行,同时支持allure

hook函数

  • 是个函数,在系统消息触发时被系统调用

  • 自动触发机制

  • Hook函数的名称是确定的

  • pytest有非常多的hook函数

  • 使用时直接编写函数体

  • 执行是有先后顺序的

  • 可以在不同阶段实现不同的功能

pytest执行过程

2962965-20221016103756161-34427585.png

执行顺序:

2962965-20221016103915709-741648896.png

pytest编写插件1-修改默认编码

pytest_collection_modifyitems收集上来的测试用例实现定制化功能

解决问题:

  • 自定义用例的执行顺序

  • 解决编码问题(中文的测试用例名称)

  • 自动添加标签

from typing import List


# 修改编码的hook函数
def pytest_collection_modifyitems(
    session: "Session", config: "Config", items: List["Item"]
) -> None:
    # items里的name是测试用例的名字,nodeid是测试用例的路径
    print(items)
    for item in items:
        # 如果想改变unicode编码格式的话,需要先encode成utf-8格式的,再decode成unicode-escape就可以了
        item.name = item.name.encode('utf-8').decode('unicode-escape')
        item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')

编写插件2-添加命令行参数

# 定义命令行参数的hook函数
def pytest_addoption(parser):
    # group 将下面所有的option都展示在这个group组下
    mygroup = parser.getgroup('hogwarts')
    mygroup.addoption('--env',  # 注册一个命令行选项
                      default='test',  # 参数的默认值
                      dest='env',  # 存储的变量,为属性命令,可以使用option对象访问到这个值
                      help='set your run env')  # 帮助提示,参数的描述信息


@pytest.fixture(scope='session')
def cmd_option(request):
    # request获取命令行的参数,config拿到pytest相关配置,getoption拿到命令行参数
    return request.config.getoption('--env')
2962965-20221016103959164-1210248251.png

打包项目构成:

  • setup.py

from setuptools import setup, find_packages

setup(
    name='pytest_encode',
    url='',
    version='1.0',  # 版本
    author='joker',  # 作者
    author_email='',  # 邮箱
    description='set your encoding and logger',  # 描述用法
    long_description='Show Chinese for you mark.parametrize().',  # 完整描述
    classifiers=[  # 分类索引,pip所属包的分类,方便在pip官网中搜索
        'Framework :: Pytest',
        'Programming Language :: Python',
        'Topic :: Software Development :: Testing',
        'Programming Language :: Python :: 3.8',

    ],
    license='proprietary',  # 程序授权信息
    packages=find_packages(),  # 通过导入的方式发现当前项目下所有的包
    keywords=[  # 便于pip进行分类
        'pytest', 'py.test', 'pytest_encode'
    ],
    # 需要安装的依赖
    install_requires=[
        'pytest'
    ],
    # 入口模块,或者入口函数(最重要的)
    entry_points={
        'pytest11': [
            'pytest_encode = pytest_encode.main'
        ]
    },
    zip_safe=False
    # 针对win系统,不设置成false会出错
)

依赖包安装:

  • pip install setuptools python的包管理工具,负责安装和发布,尤其是安装拥有依赖关系的包

  • pip install wheel 生成 *.whl格式的安装包,本质上也是一个压缩包

打包命令:(切到setup.py所在的目录下执行)

python setup.py sdist bdist_wheel

dist目录下.whl的文件,可以通过pip install 下载

  • python3 -m pip install --user --upgrade twine ## 安装twine工具

  • python3 -m twine upload --repository testpypi dist/* ## 上传代码


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK