自动化测试框架Pytest介绍(5)——前置和后置之fixture

        

目录

1、fixture参数说明

1.1参数详细说明

1.2利用yield实现后置

1.3params和ids参数的代码实例

2、fixture在用例中的调用

3、不同scope的代码实例


        在第4篇中,我们讲了前置和后置的各种setup和teardown,但是在实际应用中,有可能有的用例需要用到用例的前置,而有的用例又不需要,这样用setup和teardown实现起来就比较麻烦了。pytest提供了fixture的方法,让使用者自己灵活应用。

1、fixture参数说明

1.1参数详细说明

@pytest.fixture(scope="function",autouse=False, params=["fixture1","fixture2","fixture13"],ids=[1,2,3])

scope :作用域,默认为function:测试用例级别,class:测试类、module:模块、package:包、session:测试会话。

        比较常用的是function,在没用例判断是否调用

        session,在所有用例执行前执行前置,所有用例执行结束后执行后置,并且可以跨文件

autouser:是否自主执行,默认是False,如果设为True就跟各种setup和teardown的效果一样了。

params和ids配套使用,params是参数化,像前置函数传递列表作为参数,根据列表中元素的个数,该前置会被调用多次,调用该前置的测试用例也会执行多次。ids是为参数取别名,当参数很长时便于识别。

1.2利用yield实现后置

在fixture修饰的函数里面用yield实现对应的后置函数

1.3params和ids参数的代码实例

'''
前置传入列表参数
对应的前置函数要获取参数需要用request,获取参数要用request.param,注意这里是param表示是params中的元素
'''
from BaseLog import logger
import pytest

fixture_params = ["我是参数我虽然很长但是没有意义fixture1","我是参数我虽然很长但是没有意义fixture2","我是参数我虽然很长但是没有意义fixture13"]
@pytest.fixture(scope="function",autouse=False, params=fixture_params)
def fix_function(request):
    #特别注意这里需要一个参数request,并且调用参数是request.param,而不是request.params
    print ("这里是fix_function,",request.param)
    #用yield实现后置函数
    yield
    print("这里是fix_function的后置")

def test_case1(fix_function):
    #测试函数
    Expected = 2
    Actual = 2
    print("我是test_case1")
    assert Expected == Actual

if __name__ =="__main__":
    # -s:显示用例中的输出
    # -v:输出更详细的用例执行信息
    # __file__:本文件
    pytest.main(["-vs","BASE/file_test.py"])
    

执行结果,可以看出前置、后置、测试用例都根据传入的参数执行多次,另外可以看到在执行结果中测试用例里面显示了传入的参数

[Running] python -u "d:\Test\Android_Test\BASE\file_test.py"
============================= test session starts =============================
platform win32 -- Python 3.10.9, pytest-7.2.1, pluggy-1.0.0 -- D:\Python310\python.exe
cachedir: .pytest_cache
rootdir: d:\Test\Android_Test
plugins: rerunfailures-11.1.1, xdist-3.2.0
collecting ... collected 3 items

BASE/file_test.py::test_case1[\u6211\u662f\u53c2\u6570\u6211\u867d\u7136\u5f88\u957f\u4f46\u662f\u6ca1\u6709\u610f\u4e49fixture1] 这里是fix_function, 我是参数我虽然很长但是没有意义fixture1
我是test_case1
PASSED这里是fix_function的后置

BASE/file_test.py::test_case1[\u6211\u662f\u53c2\u6570\u6211\u867d\u7136\u5f88\u957f\u4f46\u662f\u6ca1\u6709\u610f\u4e49fixture2] 这里是fix_function, 我是参数我虽然很长但是没有意义fixture2
我是test_case1
PASSED这里是fix_function的后置

BASE/file_test.py::test_case1[\u6211\u662f\u53c2\u6570\u6211\u867d\u7136\u5f88\u957f\u4f46\u662f\u6ca1\u6709\u610f\u4e49fixture13] 这里是fix_function, 我是参数我虽然很长但是没有意义fixture13
我是test_case1
PASSED这里是fix_function的后置


======================== 3 passed in 0.03s =========================

[Done] exited with code=0 in 0.761 seconds

上面的执行结果参数很长看起来不方便,这时就可以用ids

'''
前置传入列表参数
对应的前置函数要获取参数需要用request,获取参数要用request.param,注意这里是param表示是params中的元素
'''
from BaseLog import logger
import pytest

fixture_params = ["我是参数我虽然很长但是没有意义fixture1","我是参数我虽然很长但是没有意义fixture2","我是参数我虽然很长但是没有意义fixture13"]
fixture_ids = ["fixture1","fixture2","fixture3"]
#给参数取别名
@pytest.fixture(scope="function",autouse=False, params=fixture_params,ids=fixture_ids)
def fix_function(request):
    #特别注意这里需要一个参数request,并且调用参数是request.param,而不是request.params
    print ("这里是fix_function,",request.param)
    #用yield实现后置函数
    yield
    print("这里是fix_function的后置")

def test_case1(fix_function):
    #测试函数
    Expected = 2
    Actual = 2
    print("我是test_case1")
    assert Expected == Actual

if __name__ =="__main__":
    # -s:显示用例中的输出
    # -v:输出更详细的用例执行信息
    # __file__:本文件
    pytest.main(["-vs","BASE/file_test.py"])
    

执行结果如下,我们可以看到测试用例里面的参数用别名取代了。需要注意但是ids的参数要跟params的对应起来。

[Running] python -u "d:\Test\Android_Test\BASE\file_test.py"
============================= test session starts =============================
platform win32 -- Python 3.10.9, pytest-7.2.1, pluggy-1.0.0 -- D:\Python310\python.exe
cachedir: .pytest_cache
rootdir: d:\Test\Android_Test
plugins: rerunfailures-11.1.1, xdist-3.2.0
collecting ... collected 3 items

BASE/file_test.py::test_case1[fixture1] 这里是fix_function, 我是参数我虽然很长但是没有意义fixture1
我是test_case1
PASSED这里是fix_function的后置

BASE/file_test.py::test_case1[fixture2] 这里是fix_function, 我是参数我虽然很长但是没有意义fixture2
我是test_case1
PASSED这里是fix_function的后置

BASE/file_test.py::test_case1[fixture3] 这里是fix_function, 我是参数我虽然很长但是没有意义fixture13
我是test_case1
PASSED这里是fix_function的后置

======================== 3 passed =========================

[Done] exited with code=0 in 0.677 seconds

2、fixture在用例中的调用

fixture在用例中的调用有三种方式,分别是当参数传入测试用例、用装饰@pytest.mark.usefixtures(fixture_name)、fixture中的参数autouse=True

用参数传入的代码示意

from BaseLog import logger
import pytest


@pytest.fixture(scope="function",autouse=False)
def fix_function(request):
    #特别注意这里需要一个参数request,并且调用参数是request.param,而不是request.params
    print ("这里是fix_function,",request.param)
    #用yield实现后置函数
    yield
    print("这里是fix_function的后置")
    
#以参数的形式传入
def test_case1(fix_function):
    #测试函数
    Expected = 2
    Actual = 2
    print("我是test_case1")
    assert Expected == Actual

if __name__ =="__main__":
    # -s:显示用例中的输出
    # -v:输出更详细的用例执行信息
    # __file__:本文件
    pytest.main(["-vs","BASE/file_test.py"])

用 @pytest.mark.usefixtures(fixture_name)装饰

from BaseLog import logger
import pytest


@pytest.fixture(scope="function",autouse=False)
def fix_function():
    #特别注意这里需要一个参数request,并且调用参数是request.param,而不是request.params
    print ("这里是fix_function")
    #用yield实现后置函数
    yield
    print("这里是fix_function的后置")

#以@pytest.mark.usefixtures
@pytest.mark.usefixtures("fix_function")
def test_case1():
    #测试函数
    Expected = 2
    Actual = 2
    print("我是test_case1")
    assert Expected == Actual

if __name__ =="__main__":
    # -s:显示用例中的输出
    # -v:输出更详细的用例执行信息
    # __file__:本文件
    pytest.main(["-vs","BASE/file_test.py"])

 scope=True

from BaseLog import logger
import pytest


@pytest.fixture(scope="function",autouse=True)
def fix_function():
    #特别注意这里需要一个参数request,并且调用参数是request.param,而不是request.params
    print ("这里是fix_function")
    #用yield实现后置函数
    yield
    print("这里是fix_function的后置")


def test_case1():
    #测试函数
    Expected = 2
    Actual = 2
    print("我是test_case1")
    assert Expected == Actual

if __name__ =="__main__":
    # -s:显示用例中的输出
    # -v:输出更详细的用例执行信息
    # __file__:本文件
    pytest.main(["-vs","BASE/file_test.py"])

如上3段代码执行结果都一样

[Running] python -u "d:\Test\Android_Test\BASE\file_test.py"
============================= test session starts =============================
platform win32 -- Python 3.10.9, pytest-7.2.1, pluggy-1.0.0 -- D:\Python310\python.exe
cachedir: .pytest_cache
rootdir: d:\Test\Android_Test
plugins: rerunfailures-11.1.1, xdist-3.2.0
collecting ... collected 1 item

BASE/file_test.py::test_case1 这里是fix_function
我是test_case1
PASSED这里是fix_function的后置


============================== 1 passed in 0.03s ==============================

[Done] exited with code=0 in 0.638 seconds

3、不同scope的代码实例

通过如下代码和运行结果就能理解不同scope如何应用了

测试文件file_test.py

from BaseLog import logger
import pytest

# scope="session",一般建议用autouse=True,无论执行的时候是执行模块还是某个测试用例,在测试执行的前后默认调用一次
@pytest.fixture(scope="session",autouse=True)
def fix_session():
    print ("这里是fix_session")
    yield 
    print ("这里是yield fix_session")

@pytest.fixture(scope="class")
def fix_class():
    print ("这里是fix_class")
    yield
    print ("这里是fix_class yield")

@pytest.fixture(scope="function")
def fix_function():
    print ("这里是fix_function")
    yield
    print ("这里是fix_function yield")

# scope="module",一般建议用autouse=True,无论执行的时候是执行模块还是某个测试用例,模块运行时默认调用一次
@pytest.fixture(scope="module",autouse=True)
def fix_module():
    print ("这里是fix_module")
    yield
    print("这里是fix_module yield")

def test_case1(fix_function):
    #测试函数
    Expected = 2
    Actual = 2
    print("我是test_case1")
    assert Expected == Actual

def test_case2():
    #测试函数
    Expected = 1
    Actual = 2
    print("我是test_case2")
    assert Expected != Actual

# scope=class的在测试类前面显示装饰,在测试类中前置和后置运行一次
@pytest.mark.usefixtures("fix_class")
# scope=function的在测试类前面显示装饰,在测试类中每个测试用例前置和后置运行一次
@pytest.mark.usefixtures("fix_function")
class TestClass:    

    def test_case3(self):
        #测试函数
        Expected = 1
        Actual = 2
        print("在TestClass里面的test_case3")
        assert Expected != Actual

    def test_case4(self):
        #测试函数
        Expected = 1
        Actual = 2
        print("在TestClass里面的test_case4")
        assert Expected <= Actual


if __name__ =="__main__":
    # -s:显示用例中的输出
    # -v:输出更详细的用例执行信息
    # __file__:本文件
    pytest.main(["-vs","BASE"])
    

BASE目录下另外文件test_log2.py

from BaseLog import logger
import pytest

def test_caselog():
    assert 1
    print("这是在test_log2中的test_caselog")

if __name__ =="__main__":
    # -s:显示用例中的输出
    # -v:输出更详细的用例执行信息
    # __file__:本文件
    pytest.main(["-vs","BASE"])
    

运行结果,可以看到scope=session的后置跨模块了

[Running] python -u "d:\Test\Android_Test\BASE\file_test.py"
============================= test session starts =============================
platform win32 -- Python 3.10.9, pytest-7.2.1, pluggy-1.0.0 -- D:\Python310\python.exe
cachedir: .pytest_cache
rootdir: d:\Test\Android_Test
plugins: rerunfailures-11.1.1, xdist-3.2.0
collecting ... collected 5 items

BASE/file_test.py::test_case1 这里是fix_session
这里是fix_module
这里是fix_function
我是test_case1
PASSED这里是fix_function yield

BASE/file_test.py::test_case2 我是test_case2
PASSED
BASE/file_test.py::TestClass::test_case3 这里是fix_class
这里是fix_function
在TestClass里面的test_case3
PASSED这里是fix_function yield

BASE/file_test.py::TestClass::test_case4 这里是fix_function
在TestClass里面的test_case4
PASSED这里是fix_function yield
这里是fix_class yield
这里是fix_module yield

BASE/test_log2.py::test_caselog 这是在test_log2中的test_caselog
PASSED这里是yield fix_session


============================== 5 passed in 0.05s ==============================

[Done] exited with code=0 in 0.825 seconds

你可能感兴趣的:(pytest框架介绍,pytest)