04-14pytest的fixture详解

04-13pytest的基本使用方法

引言

有了unittest这个经典的测试框架做基础,那么学习其他任何的测试框架都变得有章法可循了。

pytest测试框架也是由unittest改编而来,所以许多地方都是一脉相承。

我相信许多读者再看了unittest的文章之后,已不需要耗费脑细胞就可以把pytest的使用掌握了。你是不是也是其中一个呢?

正文:

Fixture

fixture是测试脚手架的意思。还记得在unittest的文章说起的 厨房脚手架。

avatar

上有 抽油烟机顶 ,下游烧火的灶台 ,中间就是厨师的摇摆空间。

在pytest中,fixture的作用得到了改进,不再那么固定和笨重,已经变得 可以移动。

avatar

从图中我们可以形象的知道新的脚手架具有了4个轮子,体积也更轻便了,看起来更新颖。

而老的脚手架的基本功能,它也具有,有大锅,有灶台台面,还有烟囱。

它可以当成函数的参数

.\test_funcationargument.py

import pytest

"""
脚手架
---这是一个关于函数参数的fixture
"""
@pytest.fixture()
def asargument():
    print("这是一个关于函数参数的fixture",'\n',__name__)
    return __name__

def test_asargument(asargument):
    print(asargument)
    assert asargument is not  None ,"获取为空"

运行结果

(testops) >pytest  -s -v test_funcationargument.py
========================================================================= test session starts ==========================================================================
platform win32 -- Python 3.7.1, pytest-5.2.2, py-1.8.0, pluggy-0.13.0 -- d:\python\virtualenvs\testops\scripts\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.7.1', 'Platform': 'Windows-10-10.0.18362-SP0', 'Packages': {'pytest': '5.2.2', 'py': '1.8.0', 'pluggy': '0.13.0'}, 'Plugins': {'html': '2.0.0', '
metadata': '1.8.0'}}
rootdir: D:\Coding\Project\testops\Stage5\07pytest\fixture
plugins: html-2.0.0, metadata-1.8.0
collected 1 item                                                                                                                                                        

test_funcationargument.py::test_asargument 这是一个关于函数参数的fixture
 fixture.test_funcationargument
fixture.test_funcationargument
PASSED

========================================================================== 1 passed in 0.02s ===========================================================================

它可以当成依赖来注入
# content  ./confest.py
import pytest
import smtplib

@pytest.fixture(scope="module")
def smtp_connection():
    re_r =smtplib.SMTP("smtp.qq.com",587,timeout=5)
    print(re_r)
    return re_r

# content ./test_module.py
def test_ehlo(smtp_connection):
    response,msg = smtp_connection.ehlo()
    print(response,msg)
    assert response==250
    assert b"smtp.qq.com" in msg
    assert 0 # for demo purposes

def test_noop(smtp_connection):

    response ,msg = smtp_connection.noop()
    print(response,msg)
    assert response == 250
    assert 0 # for demo purposes

总结:

1、创建:conftest.py文件里面的函数前加:@pytest.fixture @pytest.fixture(scope="session",autouse=True)  
参数scope默认函数级别,session回话级别整体运行一次,可设置自动执行
2、yield 隔断前置后置,后面加函数返回值。
3、调用:函数或类前加 @pytest.mark.usefixture("函数名")         
fixture函数名作为参数传给用例目的:用于公共数据准备和清理。
4 fixture里面有个scope参数可以控制fixture的作用范围:session > module > class > function

思考与延伸

1 fixture 的scope源码块
def fixture(
    callable_or_scope=None,
    *args,
    scope="function",
    params=None,
    autouse=False,
    ids=None,
    name=None
):
    """Decorator to mark a fixture factory function.

    This decorator can be used, with or without parameters, to define a
    fixture function.

    The name of the fixture function can later be referenced to cause its
    invocation ahead of running tests: test
    modules or classes can use the ``pytest.mark.usefixtures(fixturename)``
    marker.

    Test functions can directly use fixture names as input
    arguments in which case the fixture instance returned from the fixture
    function will be injected.

    Fixtures can provide their values to test functions using ``return`` or ``yield``
    statements. When using ``yield`` the code block after the ``yield`` statement is executed
    as teardown code regardless of the test outcome, and must yield exactly once.

    :arg scope: the scope for which this fixture is shared, one of
                ``"function"`` (default), ``"class"``, ``"module"``,
                ``"package"`` or ``"session"`` (``"package"`` is considered **experimental**
                at this time).

                This parameter may also be a callable which receives ``(fixture_name, config)``
                as parameters, and must return a ``str`` with one of the values mentioned above.

                See :ref:`dynamic scope` in the docs for more information.

    :arg params: an optional list of parameters which will cause multiple
                invocations of the fixture function and all of the tests
                using it.
                The current parameter is available in ``request.param``.

    :arg autouse: if True, the fixture func is activated for all tests that
                can see it.  If False (the default) then an explicit
                reference is needed to activate the fixture.

    :arg ids: list of string ids each corresponding to the params
                so that they are part of the test id. If no ids are provided
                they will be generated automatically from the params.

    :arg name: the name of the fixture. This defaults to the name of the
                decorated function. If a fixture is used in the same module in
                which it is defined, the function name of the fixture will be
                shadowed by the function arg that requests the fixture; one way
                to resolve this is to name the decorated function
                ``fixture_<fixturename>`` and then use
                ``@pytest.fixture(name='<fixturename>')``.
posted @ 2019-11-06 16:09  小猿取经-林海峰老师  阅读(132)  评论(0编辑  收藏  举报