前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Pytest(十) pytest Fixture(三)

Pytest(十) pytest Fixture(三)

作者头像
雷子
发布2022-04-06 08:36:17
7090
发布2022-04-06 08:36:17
举报
文章被收录于专栏:雷子说测试开发

系列分享

Pytest系列(一)初次了解

Pytest(二)执行规则以及编写执行多条用例

Pytest(三)Pytest执行命令

Pytest(四)Pytest断言

Pytest(五)标记函数

Pytest(六)跳过测试

Pytest(七) pytest之参数化

Pytest(八) pytest Fixture(一)

Pytest(九) pytest Fixture(二)


重命名

固件的名称默认为定义时的函数名,如果不想使用默认,可以通过 name 选项指定名称:

代码语言:javascript
复制
@pytest.fixture(name='name')
def calculate_average():
    return 28


def test_age(name):
    assert name == 28
if __name__ == '__main__':
    pytest.main()

执行结果

固件参数化

在之前我们介绍了参数化,固件也是函数,我们也可以对固件进行参数化,

假设现在有一批 API 需要测试对不同数据库的支持情况(对所有数据库进行相同操作),最简单的方法就是针对每个数据库编写一个测试用例,但这包含大量重复代码,如数据库的连接、关闭,查询等。

使用固件抽离出数据库的通用操作,每个 API 都能复用这些数据库固件,同时可维护性也得到提升。

代码语言:javascript
复制
import pytest
@pytest.fixture(params=[
    ('redis', '6379'),
    ('elasticsearch', '9200')
])
def param(request):
    return request.param


@pytest.fixture(autouse=True)
def db(param):
    print('\nSucceed to connect %s:%s' % param)

    yield

    print('\nSucceed to close %s:%s' % param)


def test_api():
    assert 1 == 1

执行结果

与函数参数化使用 @pytest.mark.parametrize 不同,固件在定义时使用 params 参数进行参数化。

固件参数化依赖于内置固件 request 及其属性 param。

内置固件

tmpdir & tmpdir_factory

用于临时文件和目录管理,默认会在测试结束时删除。

代码语言:javascript
复制
tmpdir 只有 function 作用域,只能在函数内使用。

使用 tmpdir.mkdir() 创建目临时录,tmpdir.join() 创建临时文件(或者使用创建的目录)

代码语言:javascript
复制
def test_tmpdir(tmpdir):
    a_dir = tmpdir.mkdir('mpdir')
    a_file = a_dir.join('file.txt')

    a_file.write('hello, pytest!')

    assert a_file.read() == 'hello, pytest!'

执行结果:

tmpdir_factory 可以在所有作用域使用,包括 function, class, module, session

代码语言:javascript
复制
@pytest.fixture(scope='module')
def my_tmpdir_factory(tmpdir_factory):
    a_dir = tmpdir_factory.mktemp('mpdir')
    a_file = a_dir.join('file.txt')
    a_file.write('hello, pytest!')
    return a_file

pytestconfig

使用 pytestconfig,可以很方便的读取命令行参数和配置文件。

下面示例演示命令行参数解析:首先在 conftest.py 中使用函数 pytest_addoption (特定的 hook function ):

代码语言:javascript
复制
def pytest_addoption(parser):
    parser.addoption('--host', action='store',
                     help='host of db')
    parser.addoption('--port', action='store', default='8888',
                     help='port of db')

然后就可以在测试函数中通过 pytestconfig 获取命令行参数:

代码语言:javascript
复制
def test_option1(pytestconfig):
    print('host: %s' % pytestconfig.getoption('host'))
    print('port: %s' % pytestconfig.getoption('port'))

pytestconfig 其实是 request.config 的快捷方式,所以也可以自定义固件实现命令行参数读取。

代码语言:javascript
复制
# conftest.py
def pytest_addoption(parser):
    parser.addoption('--host', action='store',
                     help='host of db')
    parser.addoption('--port', action='store', default='8888',
                     help='port of db')
@pytest.fixture
def config(request):
    return request.config
# test_config.py
def test_option2(config):
    print('host: %s' % config.getoption('host'))
    print('port: %s' % config.getoption('port'))

执行:

代码语言:javascript
复制
pytest  test_11.py  --host=123 -s

结果:

capsys

capsys 用于捕获 stdout 和 stderr 的内容,并临时关闭系统输出

代码语言:javascript
复制
def ping(output):
    print('Pong...', file=output)


def test_stdout(capsys):
    ping(sys.stdout)
    out, err = capsys.readouterr()
    assert out == 'Pong...\n'
    assert err == ''


def test_stderr(capsys):
    ping(sys.stderr)
    out, err = capsys.readouterr()
    assert out == ''
    assert err == 'Pong...\n'

monkeypatch

代码语言:javascript
复制
from SomeOtherProduct.SomeModule import SomeClass

def speak(self):
    return "ook ook eee eee eee!"

SomeClass.speak = speak

ytest 内置 monkeypatch 提供的函数有:

setattr(target, name, value, raising=True),设置属性;

delattr(target, name, raising=True),删除属性;

setitem(dic, name, value),字典添加元素;

delitem(dic, name, raising=True),字典删除元素;

setenv(name, value, prepend=None),设置环境变量;

delenv(name, raising=True),删除环境变量;

syspath_prepend(path),添加系统路径;

chdir(path),切换目录。

其中 raising 用于通知 pytest 在元素不存在时是否抛出异常;prepend 如果设置,环境变量将变为 value+prepend+<old value> 。

测试过程中修改了环境变量:

代码语言:javascript
复制
def test_config_monkeypatch(tmpdir, monkeypatch):
    monkeypatch.setenv('HOME', tmpdir.mkdir('home'))

    dump_config(config)
    path = os.path.expanduser('~/.conf.json')
    expected = json.load(open(path, 'r', encoding='utf-8'))
    assert expected == config

recwarn

recwarn 用于捕获程序中 warnings 产生的警告。

代码语言:javascript
复制
def warn():
    warnings.warn('Deprecated function', DeprecationWarning)
def test_warn(recwarn):
    warn()
    assert len(recwarn) == 1
    w = recwarn.pop()
    assert w.category == DeprecationWarning

也可以使用 pytest.warns() 捕获警告

代码语言:javascript
复制
def test_warn2():
    with pytest.warns(None) as warnings:
        warn()

    assert len(warnings) == 1
    w = warnings.pop()
    assert w.category == DeprecationWarning
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 雷子说测试开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档