天天看点

Pytest框架之 - fixture

上篇讲了预处理方法setup和teardown可以实现在执行用例前或结束后加入一些操作, 但这种都是针对整个脚本全局生效的, 如果只是几个特定的用例需要,

Pytest

fixture

修饰器时用来标记固定的工厂函数,在其他函数、模块、类或整个工程调用它时会被激活并优先执行,通常会被用于完成预置处理和重复操作

fixture优势

. 命名方式灵活,不局限于setup和teardown这几个命名
. conftest.py 配置里可以实现数据共享,不需要import就能自动找到fixture
. scope="function"    可以实现多个testCase共享前后置
. scope="class"       可以实现多个class共享前后置
. scope="module"      可以实现多个.py共享前后置
. scope="package"     可以实现多个package共享前后置
. scope="session"     可以实现整个session共享前后置
. 参数化的实现
           

fixture参数

@pytest.fixture(scope="function", params=None, autouse=False, ids=None, name=None)

scope:被标记方法的作用域 默认function
    "function": 默认参数,作用于每个测试方法,每个test都运行一次 
    "class": 作用于整个类,每个class的所有test只运行一次 
    "module": 作用于整个模块,每个module的所有test只运行一次 
    "package": 作用于整个package,每个package只运行一次
    "session": 作用于整个session,每个session只运行一次 
autouse: 是否自动运行,默认为False不运行(需要引用才执行),设置为True作用域内自动运行
params: list类型,提供参数数据(参数化),供调用标记方法的函数使用 
ids: 参数是配合fixture的params参数用的,如果没有设置params参数,那么ids毫无意义;ids参数是给每一项params参数设置自定义名称用的;params参数值包含的列表有多少项值,那么ids参数就必须对应有多少项值
name: 装饰器的名称,同一模块的fixture相互调用建议写个不同的name
           

引用

#!/usr/bin/python3
# coding=utf-8
# Author: 文
###########################   @pytest.fixture()在测试类里面,通过参数引用   ###########################
import pytest

class Test_One():
    @pytest.fixture()
    def default(self):
        print("-------> default")

    def test_1(self, default_01):    # 函数名直接作为参数引用使用 作用域:只在该方法前执行
        print("-------> test_1")

    def test_2(self):
        print("-------> test_2")

if __name__ == "__main__":
    pytest.main(["-s", "test_two.py::Test_One"])

#############    @pytest.fixture()在测试类之外,通过装饰器@pytest.mark.usefixtures引用    #############
import pytest

@pytest.fixture()
def default():
    print("-------> default")

@pytest.mark.usefixtures("default")  # 作用域:装饰类则该类中所有方法全部执行,装饰方法则只执行该方法
class Test_Two():
    def test_01(self):
        print("------> test_01")

    def test_02(self):
        print("------> test_02")

if __name__ == "__main__":
    pytest.main(["-s", "test_two.py::Test_Two"])
           

参数scope与作用域

scope = function     =>    setup_class之后每个setup之前执行

scope = class           =>    setup_class之后第一个setup之前执行

scope = module      =>     整个.py模块文件第一个setup_class之前执行

scope = package     =>     整个package第一个执行

scope = session       =>     整个session第一个执行

#!/usr/bin/python3
# coding=utf-8
# Author: 文

import pytest

@pytest.fixture(scope="function")
def default_01():
    print("-------> default_01")

@pytest.fixture(scope="class")
def default_02():
    print("-------> default_02")

@pytest.fixture(scope="module")
def default_03():
    print("-------> default_03")

@pytest.fixture(scope="session")
def default_04():
    print("-------> default_04")

@pytest.mark.usefixtures("default_01", "default_02", "default_03", "default_04")
class Test_Two():
    def setup(self):
        print("-------> setup")

    def setup_class(self):
        print("-------> setup_class")

    def test_01(self):
        print("------> test_01")

    def test_02(self):
        print("------> test_02")

if __name__ == "__main__":
    pytest.main(["-s", "test_two.py::Test_Two"])
           

参数autouse

autouse默认为False不运行(需要手动引用才执行),设置为True作用域内自动运行

#!/usr/bin/python3
# coding=utf-8
# Author: 文

import pytest

class Test_Three():
    @pytest.fixture(autouse=True)   # autouse=True自动执行
    def autouse_01(self):
        print("-------> 自动执行")

    @pytest.fixture(autouse=False)  # autouse=False手动引用才执行
    def autouse_02(self):
        print("-------> 引用执行")

    def test_001(self, autouse_02):
        print("------> test_001")

    def test_002(self):
        print("------> test_002")

if __name__ == "__main__":
    pytest.main(["-s", "test_two.py::Test_Three"])
           

参数params(参数化)与ids

参数params参数化, ids为给每一项params参数设置自定义名称(可为空)

#!/usr/bin/python3
# coding=utf-8
# Author: 文

import pytest

@pytest.fixture(params=['a', 'b', 'c'], ids=["ids_1", "ids_2", "ids_3"])
def parameterization(request):      # 传入参数request 系统封装参数
    return request.param            # 取列表中单个值,默认的取值方式

class Test_Four():
    def test_0001(self, parameterization):  # 获得返回值 request.param
        print("------> test_001")
        print(parameterization)

    def test_0002(self):
        print("------> test_002")

if __name__ == "__main__":
    pytest.main(["-s", "test_two.py::Test_Four"])
           

执行结果如下:

============================= test session starts =============================
platform win32 -- Python ., pytest-., py-., pluggy-.
rootdir: E:\xxx, configfile: pytest.ini, testpaths: ./testCase
collected  items

testCase/test_two.py::Test_Four::test_0001[ids1] ------> test_001
a
PASSED
testCase/test_two.py::Test_Four::test_0001[ids2] ------> test_001
b
PASSED
testCase/test_two.py::Test_Four::test_0001[ids3] ------> test_001
c
PASSED
testCase/test_two.py::Test_Four::test_0002 ------> test_002
PASSED

==============================  passed in s ==============================
           

参数name

name参数是给fixtrue设置名称

#!/usr/bin/python3
# coding=utf-8
# Author: 文

import pytest

class Test_Five():
    @pytest.fixture(name='name_01')        # name参数给fixture设置名称
    def name(self):
        print('------> name')

    def test_01(self, name_01):            # 使用name参数名来引用 -> name_01
        print("------> test_01")

if __name__=='__main__':
    pytest.main(["-s", "test_two.py::Test_Five::test_01"])
           

关键字yield

@pytest.fixture()

中,关键字

yield

之前的代码为用例的前置处理方法  关键字

yield

之后的代码为用例的后置处理方法

#!/usr/bin/python3
# coding=utf-8
# Author: 文

import pytest

class Test_Three():
    @pytest.fixture()
    def autouse(self):
        print("-------> yield之前的代码为用例的前置处理")
        yield
        print("-------> yield之后的代码为用例的后置处理")

    def test_01(self, autouse):
        print("------> test_01")

if __name__ == "__main__":
    pytest.main(["-s", "test_two.py::Test_Three"])
           

执行结果如下:

F:\Python3.\python.exe E:/xxx/test_two.py
============================= test session starts =============================
platform win32 -- Python ., pytest-., py-., pluggy-.
rootdir: E:\xxx, configfile: pytest.ini
plugins: html-., metadata-.
collected  item
test_two.py -------> yield之前的代码为用例的前置处理
------> test_01
.-------> yield之后的代码为用例的后置处理
==============================  passed in s ==============================
Process finished with exit code 
           
Pytest框架之 - fixture

 ~ 不积跬步无以至千里

继续阅读