Ultra-detailed pytest tutorial (2) before and after methods and fixture mechanisms

foreword

In the previous article, we introduced the basic use of pytest. This article is dedicated to explaining the pre- and post-step processing of use case execution in pytest. implementation, or through xunit-style pre- and post-approaches. Next, let's take a look at how to use it in detail.

1. The front and rear methods of xunit style

1. Front and back methods of function use cases

Define the use case in the form of a function in the module, you can define the front and rear methods of the function use case through setup_function and teardown_function, the use case is as follows:

def setup_function(function):
    print("函数用例前置方法执行")

  
def teardown_function(function):
    print("函数用例后置方法执行")


def test_01():
    print('----用例方法01------')

operation result:

C:\testcases>pytest -s
========================= test session starts =========================
platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0 
cachedir: .pytest_cache
rootdir: C:\testcases
plugins:  testreport-1.1.2
collected 1 item                                                      
test_demo.py
函数用例前置方法执行
----用例方法01------ .
函数用例后置方法执行
========================= 1 passed in 0.27s =========================

2. The front and back methods of the use cases in the test class

  • Class-level pre- and post-methods
  • The pre- and post-methods setup_class and teardown_class at the test class level in pytest are executed before the use cases in the test class are executed, and after all the use cases in the test class are executed. The specific usage is as follows:
  • class TestDome: def test_01(self): print('----test case: test_01------') def test_02(self): print('----test case: test_02----- -') @classmethod def setup_class(cls): print("Test class pre-method ---setup_class---") @classmethod def teardown_class(cls): print("Test class post-method ---teardown_class-- -")
  • Pre- and post-methods at the use-case level
  • The setup_method and teardown_method of the use case level in the test class in pytest are executed before the use case in the test class is executed, and after all the use cases in the test class are executed. The specific usage is as follows:
  • class TestDome: def test_01(self): print('----test case: test_01------') def test_02(self): print('----test case: test_02----- -') @classmethod def setup_class(cls): print("Test class pre-method ---setup_class---") @classmethod def teardown_class(cls): print("Test class post-method ---teardown_class-- -") def setup_method(function): print("Test case pre-method---setup_method---") def teardown_method(function): print("Test case post-method---teardown_method---")

operation result:

C:\testcases>pytest -s
==================== test session starts ====================
platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0
rootdir: C:\testcases
plugins:  testreport-1.1.2
collected 2 items                                                                                                                                 
test_demo.py 
测试类前置方法---setup_class---
测试用例前置方法---setup_method---
----测试用例:test_01------.
测试用例后置方法---teardown_method---
测试用例前置方法---setup_method---
----测试用例:test_02------.
测试用例后置方法---teardown_method---
测试类后置方法---teardown_class---

==================== 2 passed in 0.30s =======================

3. Front and back methods at the module level

There are also two functions in pytest, setup_module and teardown_module, which are used to set the front and rear methods of the module level. They are defined in the module and will be executed before and after all use cases in the entire module are executed. The specific usage is as follows:


class TestDome:

    def test_01(self):
        print('----测试用例:test_01------')


class TestDome2:

    def test_02(self):
        print('----测试用例:test_02------')
   
  
def setup_module(module):
    print("测试模块的前置方法---setup_module---")


def teardown_module(module):
    print("测试模块的前置方法---teardown_module---")

operation result:

C:\testcases>pytest -s
====================== test session starts ====================== 
platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0
rootdir: C:\testcases
plugins:testreport-1.1.2
collected 2 items                                                                   
test_demo.py 测试模块的前置方法---setup_module---
----测试用例:test_01------
.----测试用例:test_02------
.测试模块的前置方法---teardown_module---
====================== 2 passed in 0.27s ====================== 

2. Fixture mechanism

Earlier we introduced the xunit-style front and rear methods in pytest. Next, let's take a look at the use of the more powerful fixture mechanism (test fixture) in pytest.

1. Level and definition of test fixtures

Test fixtures need to be defined using the pytest.fixture decorator. Test fixtures in pytest have the following levels: use case level, test class level, module level, package level, and session level. Next, let's take a look at the fixture definition syntax.

The fixture definition can specify the level of the fixture through the parameter scope. If the fixture level is not specified, the default value of scope is function (use case level)

Use case level: scope = function

Test class level: scope = class

Module level: scope = module

Package level: scope = package

Session level: scope = session

@pytest.fixture(scope='指定夹具的级别')
def work():
    # 前置执行脚本
    yield 
    # 后置执行脚本

The test fixture is essentially a generator function. When the producer function uses next to iterate, it will return data when it executes to yeild, pause the execution, and wait for the next iteration before continuing to execute. The pytest fixture is the mechanism of the generator used , execute the front and rear code separately in the test fixture through yeild.

Points to note: Fixtures can only be used within the range of defined fixtures. If a fixture is defined within a class, it can only be used by test cases within that class. But if a fixture is defined in the global scope of a module, then every test case in that module, even if it is defined in a class, can use it.

Now that we know how to define fixtures, let's take a look at how to use them.

2. Use of fixtures

After the test fixtures are defined, the test function specifies which fixtures to execute before executing the test case by declaring them as parameters.

When pytest starts running a test, it looks at the parameters defined by the test function, and then searches for a test fixture with the same name as those parameters. Once pytest finds them, it runs the fixtures, receives their returns (if any), and passes those returns as arguments to the test function.

Note: When we use the fixture, if the pre-script of the fixture is executed and there is data to be transferred to the use case, the data to be transferred can be written after yield. In the use case or method of using the fixture, you can pass the defined parameter To get the data returned by yeild (use case introduction in Chapter 2.3)

2.1. Using Fixtures in Use Cases

Whether it is a test case defined in the form of a function or a test case defined in the form of a method in a test class, it is the same when used. Just define a formal parameter with the same name as the fixture to be used.

import pytest

# 定义一个用例级别的夹具
@pytest.fixture
def my_fixture():
    print('------my_fixture---用例前置执行脚本--------')
    yield
    print('------my_fixture---用例后置执行脚本--------')

# 函数用例 指定测试夹具
def test_func__01(my_fixture):
    print("测试用例----test_func__01----")


class TestDome:
    # 函数用例 指定测试夹具
    def test_02(self, my_fixture):
        print('----测试用例:test_02------')
  
     # 函数用例 指定测试夹具
    def test_03(self):
        print('----测试用例:test_03------')

operation result

C:\testcases>pytest -s
======================== test session starts ========================
platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0
rootdir: C:\testcases
plugins: testreport-1.1.2
collected 2 items  
test_demo.py 
------my_fixture---前置执行脚本--------
测试用例----test_func__01----.
------my_fixture---后置执行脚本--------
------my_fixture---前置执行脚本--------
----测试用例:test_02------.
------my_fixture---后置执行脚本--------
----测试用例:test_03------
======================== 2 passed in 0.27s ========================

The above two use cases, test_func__01 and test_02, specified test fixtures when they were defined, while test_03 did not specify the fixtures to be executed. When the use cases were executed, the library saw the use cases that specified the fixtures and executed the corresponding fixtures.

2.2. Test classes and modules specify fixtures

Above we specify a test fixture for a single test case by adding formal parameters to the use case method. If there are many test cases in a test class or many use cases in a module, the same test fixture must be specified, and we can specify test fixtures for the test class or test module through usefixtures.

Assign fixtures to all cases in the test class

# TestDome这个测试类的所有测试用例均执行my_fixture这个夹具
@pytest.mark.usefixtures('my_fixture这个夹具')
class TestDome:
    # 函数用例 指定测试夹具
    def test_02(self):
        print('----测试用例:test_01------')

    # 函数用例 指定测试夹具
    def test_03(self):
        print('----测试用例:test_02------')

A fixture to specify all test executions of a module at the test module level using pytestmark

# test_demo.py

# 当前模块中所有的用例,均执行my_fixture这个测试夹具
pytestmark = pytest.mark.usefixtures('my_fixture')

# 函数用例 指定测试夹具
def test_func__01(my_fixture):
    print("测试用例————test_func__01——————")

  
class TestDome:
    # 函数用例 指定测试夹具
    def test_02(self):
        print('----测试用例:test_01------')

    # 函数用例 指定测试夹具
    def test_03(self):
        print('----测试用例:test_02------')

2.3. Reference the fixture in the fixture

One of pytest's greatest strengths is its extremely flexible fixture system. Through the test fixture, we can split the extremely complex front and rear dependencies into simpler single-function test fixtures, and organize the complex dependency environments required by different use cases by referencing other fixtures in the fixture. Next, we will show you how to use it through a case.

import pytest
# 用户注册的夹具
@pytest.fixture
def register_user():
    print('---用户注册的夹具前置执行----')
    # ...注册代码省略,注册的用户信息如下
    user_info = {'user': 'lemonban', 'pwd': '123456'}
    yield user_info
    print('---用户注册的夹具后置执行----')


# 用户登录的夹具,通过定义形参来使用register_user这个夹具
@pytest.fixture
def user_login(register_user):
    print('---用户登录的夹具前置执行----')
    # 获取register_user结局前置脚本执行完,yeild传递出来的数据
    user_info = register_user
    # ...登录代码省略,下面为登录得到的token
    token = 'sdjasjdask'
    yield token
    print('---用户登录的夹具后置执行----')

# 函数用例 指定使用测试夹具user_login
def test_func__01(user_login):
    token = user_login
    print("测试用例夹具user_login传递过来的token:",token)
    print("测试用例---test_func__01---")

operation result

C:\testcases>pytest -s
======================== test session starts ========================
platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0
rootdir: C:\testcases
plugins: testreport-1.1.2
collected 1 item  
test_demo.py 
---用户注册的夹具前置执行----
夹具register_user传递过来的用户信息: {'user': 'lemonban', 'pwd': '123456'}
---用户登录的夹具前置执行----
测试用例夹具user_login传递过来的token: sdjasjdask
测试用例---test_func__01---.
---用户登录的夹具后置执行----
---用户注册的夹具后置执行----

2.4. Automatic use of fixtures

When defining the test fixture, we can add the parameter autouse=True to the decorator of the fixture to make the fixture an automatically executed fixture. The specific cases are as follows:

import pytest


@pytest.fixture(autouse=True)
def my_fixture():
    print('------my_fixture---前置执行脚本--------')
    yield
    print('------my_fixture---后置执行脚本--------')


class TestDome:
    # 函数用例 指定测试夹具
    def test_02(self):
        print('----测试用例:test_01------')

    # 函数用例 指定测试夹具
    def test_03(self):
        print('----测试用例:test_02------')


class TestDome2:
    # 函数用例 指定测试夹具
    def test_03(self):
        print('----测试用例:test_03------')

Results of the:

C:\testcases>pytest -s
======================== test session starts ========================
platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0
rootdir: C:\testcases
plugins: testreport-1.1.2
collected 3 items    
test_demo.py
------my_fixture---前置执行脚本--------
----测试用例:test_01------.
------my_fixture---后置执行脚本--------
------my_fixture---前置执行脚本--------
----测试用例:test_02------.
------my_fixture---后置执行脚本--------
------my_fixture---前置执行脚本--------
----测试用例:test_03------.
------my_fixture---后置执行脚本--------
======================== 3 passed in 0.29s ========================

From the above execution results, we can see that the test fixture my_fixture is automatically executed before each use case is executed.

3、conftest.py

In the testing of a project, in most cases there will be multiple classes, modules, or packages that will use the same test fixture. In this case, if we define the test fixtures in a certain module, sharing cannot be achieved. In this case, we can put the test fixtures that need to be shared into a separate conftest.py file, so that multiple can achieve multiple test modules shared

ps : When pytest runs the test, if there is conftest.py in the project, then pytest will automatically load the content in the conftest.py module. You can see conftest as the plug-in module that pytest will automatically load. Subsequent tutorials will involve conftest Define the hooks function of pytest in .py

Next, let's look at a case where conftest.py defines a test fixture

Define the test fixture my_fixture in conftest.py

# conftest.py

import pytest

@pytest.fixture
def my_fixture():
    print('------my_fixture---前置执行脚本--------')
    yield
    print('------my_fixture---后置执行脚本--------')

The use case in test_demo1.py uses the fixture defined in conftest.py

# test_demo1.py
class TestDome:
    # 函数用例 指定测试夹具
    def test_02(self,my_fixture):
        print('----测试用例:test_01------')

    # 函数用例 指定测试夹具
    def test_03(self,my_fixture):
        print('----测试用例:test_02------')

The use case in test_demo2.py uses the fixture defined in conftest.py

# test_demo2.py
class TestDome2:
    # 函数用例 指定测试夹具
    def test_03(self,my_fixture):
        print('----测试用例:test_03------')

Results of the:

C:\testcases>pytest -s
======================== test session starts ========================
platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0
rootdir: C:\testcases
plugins: testreport-1.1.2
collected 3 items
test_demo.py 
------my_fixture---前置执行脚本--------
----测试用例:test_01------.
------my_fixture---后置执行脚本--------
------my_fixture---前置执行脚本--------
----测试用例:test_02------.
------my_fixture---后置执行脚本--------
test_demo2.py 
------my_fixture---前置执行脚本--------
----测试用例:test_03------.
------my_fixture---后置执行脚本--------
======================== 3 passed in 0.29s ========================

In the above case, we can find that the use cases in est_demo.py and est_demo2.py can successfully use the test cases in conftest.py.

In the next article, I will explain to you the pytest tutorial (3) use cases


 

Guess you like

Origin blog.csdn.net/a448335587/article/details/128268279