Gao fushuai in unit testing, Pytest framework, hand-in-hand teaching, high-order usage practice

Posted by stewart on Thu, 20 Jan 2022 22:19:16 +0100

Previous remarks

In the introduction of the last article, we introduced the basic use of pytest. This article specifically explains the pre-processing and post-processing of use case execution in pytest. The pre-processing and post-processing of use case execution in pytest can be realized either by test fixture or by xunit style pre-processing and post-processing methods. Next, let's see how to use it.

1, Front back approach in xunit style

1. Pre post method of function use case

Use cases are defined in the form of functions in the module, which can be defined through setup_function and teardown_function to define the pre and post methods of function use cases. The use cases are as follows:

def setup_function(function):    print("Function use case pre method execution")  def teardown_function(function):    print("Function use case post method execution")def test_01():    print('----Use case method 01------')

Operation results:

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_cacherootdir: C:\testcasesplugins:  testreport-1.1.2collected 1 item                                                      test_demo.py Function use case pre method execution----Use case method 01------ .Function use case post method execution========================= 1 passed in 0.27s =========================

2. Pre and post methods of test cases in test classes

Class level pre and post methods

Pre and post method setup of test class level in pytest_ Class and teardown_class, which is executed before the execution of the use cases in the test class and after the execution of all the use cases in the test class. 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 method at use case level

Pre and post method setup of use case level in test class in pytest_ Method and teardown_method, which is executed before the execution of the use cases in the test class and after the execution of all the use cases in the test class. The specific use 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("Pre test case method---setup_method---")    def teardown_method(function):        print("Post test case method---teardown_method---")

Operation results

C:\testcases>pytest -s==================== test session starts ====================platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0rootdir: C:\testcasesplugins:  testreport-1.1.2collected 2 items                                                                                                                                 test_demo.py Test class pre method---setup_class---Pre test case method---setup_method-------Test case: test_01------.Post test case method---teardown_method---Pre test case method---setup_method-------Test case: test_02------.Post test case method---teardown_method---Test class post method---teardown_class---==================== 2 passed in 0.30s =======================

3. Pre post method at module level

pytest also has setup_module and teardown_module, two functions used to set module level pre and post methods, are defined in the module and will be executed before and after the execution of all use cases in the whole module. The specific usage is as follows:

class TestDome:    def test_01(self):        print('----Test case: test_01------')class TestDome2:    def test_02(self):        print('----Test case: test_02------')     def setup_module(module):    print("Pre test method of test module---setup_module---")def teardown_module(module):    print("Pre test method of test module---teardown_module---")

Operation results

C:\testcases>pytest -s====================== test session starts ====================== platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0rootdir: C:\testcasesplugins:testreport-1.1.2collected 2 items                                                                   test_demo.py Pre test method of test module---setup_module-------Test case: test_01------.----Test case: test_02------.Pre test method of test module---teardown_module---====================== 2 passed in 0.27s ====================== 

2, fixture mechanism

Earlier, we introduced the xunit style pre post method 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 fixture

The test fixture requires pytest The fixture is defined by the decorator. The test folder in pytest has the following levels: use case level, test class level, module level, package level and session level. Next, let's look at the fixture definition syntax.

Fixture definition can specify the level of 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='Specifies the level of the fixture')def work():    # Pre execution script    yield     #Post execution script

The test fixture is essentially a generator function. When using next to iterate, the producer function will return data to yeild, pause execution, and wait for the next iteration before continuing execution. pytest fixture uses the generator mechanism to separate the pre and post codes in the test fixture through yeild.

Note: the fixture can only be used within the scope of defining the fixture. If the fixture is defined in a class, it can only be used by test cases in that class. However, if the fixture is defined in the global scope of the module, it can be used for each test case in the module, even if it is defined in a class.

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

2. Use of fixtures

After the test fixture is defined, the test function specifies the fixture to be executed before executing the use case by declaring them as parameters.

When pytest starts running a test, it looks at the formal parameters defined by the test function, and then searches for test fixtures with the same name as these parameters. Once pytest finds them, it runs the fixtures, receives their returns, if any, and passes them as parameters 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 the yield. In the use case or method using the fixture, the data returned by yeild can be obtained through the defined formal parameters (the use case is introduced in Chapter 2.3)

2.1. Use fixture in use case

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. You can directly define a formal parameter with the same name as the fixture to be used.

import pytest# Define a use case level fixture@pytest.fixturedef my_fixture():    print('------my_fixture---Use case pre execution script--------')    yield   print('------my_fixture---Post use case execution script--------')# Function case specifies the test fixture def test_func__01(my_fixture):    print("test case----test_func__01----")class TestDome:    # Function case specifies the test fixture    def test_02(self, my_fixture):        print('----Test case: test_02------')       # The function case specifies the test fixture def test_03(self): print('--- test case: test_03 ------')

Operation results

C:\testcases>pytest -s======================== test session starts ========================platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0rootdir: C:\testcasesplugins: testreport-1.1.2collected 2 items  test_demo.py ------my_fixture---Pre execution script--------test case----test_func__01----.------my_fixture---Post execution script--------------my_fixture---Pre execution script------------Test case: test_02------.------my_fixture---Post execution script------------Test case: test_03------======================== 2 passed in 0.27s ========================

Test above_ func__ 01 and test_02 these two use cases specify the test fixture when defining, and test_03, no fixture is specified for execution. When executing the use case, the library sees the use case with the specified fixture and executes the corresponding fixture.

2.2 designated fixtures for test classes and modules

Above, we specify the 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 test cases in a module, the same test fixture should be specified. If necessary, we can specify the test fixture for the test class or test module through use fixtures.

Assign fixtures to all use cases in the test class

# TestDome All test cases of this test class are executed my_fixture This fixture@pytest.mark.usefixtures('my_fixture This fixture')class TestDome:    # Function case specifies the test fixture    def test_02(self):        print('----Test case: test_01------')    # The function case specifies the test fixture def test_03(self): print('--- test case: test_02 ------')

Use {pytestmark} at the test module level} to specify the fixture to be executed by all use cases of the module

# test_demo.py# All use cases in the current module are executed my_fixture This test fixture pytestmark = pytest.mark.usefixtures('my_fixture')# Function case specifies the test fixture def test_func__01(my_fixture):    print("Test case———— test_func__01---")  class TestDome:    # Function case specifies the test fixture    def test_02(self):        print('----Test case: test_01------')    # The function case specifies the test fixture def test_03(self): print('--- test case: test_02 ------')

2.3. Reference fixture in fixture

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

import pytest# User registered fixture@pytest.fixturedef register_user():    print('---User registered fixture pre execution----')    # ...The registration code is omitted, and the registered user information is as follows    user_info = {'user': 'lemonban', 'pwd': '123456'}    yield user_info    print('---User registered fixture post execution----')# User logged in fixture,Use by defining formal parameters register_user This fixture@pytest.fixturedef user_login(register_user):    print('---Pre execution of fixture logged in by user----')    # obtain register_user After the execution of the ending pre script, yeild Transmitted data    user_info = register_user    # ...The login code is omitted, and the following is the login result token    token = 'sdjasjdask'    yield token    print('---Fixture post execution after user login----')# Function use cases specify the use of test fixtures_ logindef test_func__01(user_login):    token = user_ Login print("token passed by user_login in the test case:", token) print("test case --- test_func_01 ---")

Operation results

C:\testcases>pytest -s======================== test session starts ========================platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0rootdir: C:\testcasesplugins: testreport-1.1.2collected 1 item  test_demo.py ---User registered fixture pre execution----fixture register_user User information transmitted: {'user': 'lemonban', 'pwd': '123456'}---Pre execution of fixture logged in by user----Test case fixture user_login Passed on token: sdjasjdask test case---test_func__01---.---Fixture post execution after user login-------User registered fixture post execution----

2.4 automatic fixture

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

import pytest@pytest.fixture(autouse=True)def my_fixture():    print('------my_fixture---Pre execution script--------')    yield    print('------my_fixture---Post execution script--------')class TestDome:    # Function case specifies the test fixture    def test_02(self):        print('----Test case: test_01------')    # Function case specifies the test fixture    def test_03(self):        print('----Test case: test_02------')class TestDome2:    # The function case specifies the test fixture def test_03(self): print('--- test case: test_03 ------')

Execution results:

C:\testcases>pytest -s======================== test session starts ========================platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0rootdir: C:\testcasesplugins: testreport-1.1.2collected 3 items    test_demo.py------my_fixture---Pre execution script------------Test case: test_01------.------my_fixture---Post execution script--------------my_fixture---Pre execution script------------Test case: test_02------.------my_fixture---Post execution script--------------my_fixture---Pre execution script------------Test case: test_03------.------my_fixture---Post execution script--------======================== 3 passed in 0.29s ========================

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

3,conftest.py

In the test of a project, in most cases, multiple classes, modules, or packages will use the same test fixture. In this case, if we define the test fixture in a module, sharing cannot be realized. In this case, we can put the test fixture to be shared into a separate conf test Py file, so that multiple test modules can be shared

PS: when pytest runs the test, if there is confitest in the project Py, then pytest will automatically load conf test The contents of the PY module can be seen from confitest. The plug-in module that pytest will automatically load will be covered in subsequent tutorials hooks function of pytest defined in PY

Next, let's look at a conf test Case of Py defining test fixture

In conf test Define test fixture in PY_ fixture

# conftest. pyimport  pytest@pytest.fixturedef  my_ Fixture (): Print ('------- my_fixture ---- pre execution script --------') yield print ('------- my_fixture ---- post execution script --------')

In test_ demo1. The use case of Py , uses , conf test Fixture defined in PY

# test_demo1.pyclass TestDome:    # Function case specifies the test fixture    def test_02(self,my_fixture):        print('----Test case: test_01------')    # The function case specifies the test fixture def test_03(self,my_fixture): print('--- test case: test_02 ------')

In test_ demo2. The use case of Py , uses , conf test Fixture defined in PY

# test_demo2.pyclass TestDome2:    # The function case specifies the test fixture def test_03(self,my_fixture): print('--- test case: test_03 ------')

Execution results:

C:\testcases>pytest -s======================== test session starts ========================platform win32 -- Python 3.7.3, pytest-5.4.2, py-1.8.0, pluggy-0.13.0rootdir: C:\testcasesplugins: testreport-1.1.2collected 3 itemstest_demo.py ------my_fixture---Pre execution script------------Test case: test_01------.------my_fixture---Post execution script--------------my_fixture---Pre execution script------------Test case: test_02------.------my_fixture---Post execution script--------test_demo2.py ------my_fixture---Pre execution script------------Test case: test_03------.------my_fixture---Post execution script--------======================== 3 passed in 0.29s ========================

In the above cases, we can find that_ demo. Py and test_ demo2. The use cases in. Py can successfully use conf test Py.

welfare

Welfare release, from introduction to actual combat, from e-books to real interview questions, should be the most comprehensive and complete war preparation warehouse for [software testing] friends. This warehouse has also accompanied me through the most difficult journey. I hope it can also help you.

If you need this learning material, can you scan the two-dimensional CSDN official certification below through wechat [100% free access].

 

 

Topics: Python unit testing