Pytest前置后置(夹具)

一、前言

在执行测试用例时,为了保证测试用例的稳定性,在执行用例前需要准备数据,然后用例执行完毕后,再销毁数据,这样能保证每次执行用例的结果一样,也就是所谓的幂等性。

对于pytest测试框架,它提供了夹具的多种使用方法,其中有类似于unittestsetUp()、tearDown(),也有创新型的fixture方法。具体如下:

二、pytestsetup

1、module作用域

  • setup_module:在模块用例执行前运行一遍,其中的方法,一般使用得较少
  • teardown_module:在模块用例执行后再运行一遍,其中的方法,一般使用得较少
import pytest


def setup_module():
    print("这是setup_module:在模块执行前运行一遍")


def teardown_module():
    print("这是teardown_module:在模块执行后运行一遍")
    

class TestMyCode:

    def setup_class(self):
        print("这是setup_class:在类中使用,类执行之前运行一次")

    def setup(self):
        print("\n这是setup:在类中使用,在每一个方法之前执行一次,在每一个方法之后执行一次")

    def teardown(self):
        print("\n这是teardown:在类中使用,在每一个方法之前执行一次,在每一个方法之后执行一次")

    def teardown_class(self):
        print("这是teardown_class:在类中使用,类执行之后运行一次")

    def test_setup_001(self):
        print("==========执行测试用例:test_setup_001==========")
        assert True

    def test_setup_002(self):
        print("==========执行测试用例:test_setup_002==========")
        assert True

结果:

2、class作用域

  • setup_class:在类中使用,类中所有用例执行之前运行一次,其中的方法

  • teardown_class:在类中使用,类中所有用例执行之后运行一次,其中的方法,比如

class TestMyCode:

    def setup_class(self):
        print("这是setup_class:在类中使用,类执行之前运行一次")

    def setup_method(self):
        print("\n这是setup_method:在类中使用,在每一个方法之前执行一次,在每一个方法之后执行一次")

    def teardown_method(self):
        print("\n这是teardown_method:在类中使用,在每一个方法之前执行一次,在每一个方法之后执行一次")

    def teardown_class(self):
        print("这是teardown_class:在类中使用,类执行之后运行一次")

    def test_setup_001(self):
        print("==========执行测试用例:test_setup_001==========")
        assert True

    def test_setup_002(self):
        print("==========执行测试用例:test_setup_002==========")
        assert True

结果:

3、function作用域

  • setup_function:不在类中使用,且只对类外的函数式测试用例生效

  • teardown_function:不在类中使用,且只对类外的函数式测试用例生效,比如:

def setup_function():
    print("这是setup_function:不在类中使用,且只对类外的函数式测试用例生效,在用例之前运行一遍")


def teardown_function():
    print("这是teardown_function:不在类中使用,且只对类外的函数式测试用例生效,在用例执行之后运行一遍")


def test_setup_003():
    print("==========执行类外的测试用例:test_setup_003==========")
    assert True

结果:

4、method作用域

  • setup_methodteardown_method:在类中使用,在每一个方法之前执行一次,在每一个方法之后执行一次
  • setupteardown:在类中使用,在每一个方法之前执行一次,在每一个方法之后执行一次

三、pytestfixture

除了以上的方法之外,pytest还提供了fixture的方法,能更优雅的执行前置后置操作,将操作方法与用例相隔离,不过需要注意的是@pytest.fixture(scope="function")中,scope对应不通的值,fixture方法作用域也不通,具体如下所示。

  • @pytest.fixture()默认的级别为function:在每一个用例方法之前执行一次yeild前的方法,在用例执行完毕后再执行yeild后的方法。

    注意:@pytest.fixture()@pytest.fixture(scope="function")相同。

  • @pytest.fixture(scope="class"):在每一个类方法之前执行一次yeild前的方法,在类中用例执行完后,再执行yeild后的方法。

  • @pytest.fixture(scope="module"):在每一个模块之前执行一次yeild前的方法,在模块用例执行完后,再执行yeild后的方法。

  • @pytest.fixture(scope="session"):在每一个模块之前执行一次yeild前的方法,在模块用例执行完后,再执行yeild后的方法。

1、用例脚本中的fixture方法

import pytest


def login():
    print("\n这是登录操作")


def logout():
    print("\n退出系统操作")


@pytest.fixture(scope="function")
def handle():
    login()
    yield "这是返回值"
    logout()


class TestMyCode:

    def test_setup_001(self, handle):
        print("==========执行测试用例:test_setup_001==========")
        print(handle)
        assert True

    def test_setup_002(self, handle):
        print("==========执行测试用例:test_setup_002==========")
        print(handle)
        assert True

结果:

2、conftest中的fixture方法

通常做法是将fixture方法统一放在conftest.py文件中,用例与夹具方法隔离,更优雅,更容易管理。

#conftest.py

def login():
    print("\n这是登录操作")


def logout():
    print("\n退出系统操作")


@pytest.fixture(scope="function")
def handle():
    login()
    yield "这是返回值"
    logout()

脚本文件:

#用例脚本文件

class TestMyCode:

    def test_setup_001(self, handle):
        print("==========执行测试用例:test_setup_001==========")
        print(handle)
        assert True

    def test_setup_002(self, handle):
        print("==========执行测试用例:test_setup_002==========")
        print(handle)
        assert True

结果:

四、pytestaddfinalizer

在用例执行完毕后,还需要执行其他操作的,除了使用带有yieldfixture函数,还可以直接添加终结器addfinalizer

@pytest.fixture()
def clear_data(request):
    print("\n这个fixture在每个case前执行一次")
    def demo_finalizer2():
        print("\n在每个case完成后执行的teardown2")
    def demo_finalizer1():
        print("\n在每个case完成后执行的teardown1")


    #注册demo_finalizer为终结函数
    request.addfinalizer(demo_finalizer1)
    request.addfinalizer(demo_finalizer2)



class TestMyCode:

    def test_setup_001(self, handle, clear_data):
        print("==========执行测试用例:test_setup_001==========")
        print(handle)
        assert True

    def test_setup_002(self, handle):
        print("==========执行测试用例:test_setup_002==========")
        print(handle)
        assert True

从结果看出,与yield是一致的。要注意的是,多个终结器的情况下,执行的顺序是与注册 request.addfinalizer时候相反的

posted @ 2022-05-27 17:34  xyztank  阅读(756)  评论(0编辑  收藏  举报