Accept it, and you will successfully win 15koffer's interface automation testing framework tutorial pytest-yield and final function after just one week of study.

 

We have already learned the simple usage offixture function, but in factfixture also provides two very elegant and efficient writing methods to complete the test before execution. The processing operations and post-execution processing operations are implemented using yield or addfinalizer.

yield

The keyword yield in fixture has two main functions:

  • yieldreplacesreturn to pass parameters
  • functions as code division. The code before yield functions as setup, and the code after yield functions as teardown
yield and return

In the fixture function of pytest, you can use yield instead of return to return. The example is as follows:

import pytest

@pytest.fixture(autouse=True)
def fixture_one():
    print("执行fixture_one")
    yield 1
    
def test_e(fixture_one):
    print("执行test_e")
    print(fixture_one)
    assert fixture_one == 1


if __name__ == '__main__':
    pytest.main(["-s"])

The running results are as follows:

test_case_4.py::test_e 
执行fixture_one
PASSED                                            [100%]执行test_e
1


============================== 1 passed in 0.12s ==============================

We can see from the running results that fixture_one will return 1 and pass it to test_e, and return has exactly the same effect. But if you just use it this way, it is meaningless, because using return is enough. Therefore, in actual use, we usually add the code after yield. teardown

yield and teardown

yield does not pass parameters

For fixture functions that do not need to return data in the previous operation, addyield, then the code before yield is the operation before the use case executes (i.e. setup), and the code after yield Perform subsequent operations (i.e. teardown) for the use case. Examples include:

import pytest

@pytest.fixture()
def fixture_demo():
    # setup
    print("\n连接数据库")
    yield
    # teardown
    print("清空脏数据")

def test_case(fixture_demo):
    print("执行test_case")
    assert True


if __name__ == '__main__':
    pytest.main(["-s"])

The running results are as follows:

From the results, we can see that the setup part is executed first, then the test case is executed, and finally the teardown part is executed.

yield to pass parameters

yieldParameters can be passed to test cases.

Suppose there is a scenario where the return parameter of 接口1 needs to be used as the request parameter of 接口2, that is, 接口2 Dependent on 接口1, we need to write a test case to test 接口2. At this time, we can write the request of 接口1 in the frontend , if it is a unittest frame, the code is as follows:

import unittest
import requests

class TestDemo(unittest.TestCase):

    def setup(self):
        print("请求接口1")
        self.res_1 = requests.get(url=url_1, params=params_1)

    def test_api_2(self):
        print("验证接口2")
        # 将接口1的返回值self.res_1作为请求参数,请求接口2
        res = requests.post(url=url_2, data=self.res_1)
        # 断言
        self.assertEqual(res, "接口2预期的返回结果")

    def teardown(self):
        print("清空脏数据")

Using+ in the pytest framework can be written as follows:fixtureyield

@pytest.fixture()
def get_api_1_result():
    # setup
    res_1 = requests.get(url=url_1, params=params_1)
    yield res_1
    # teardown
    print("清空脏数据")
    

def test_api_2(get_api_1_result):
    print("验证接口2")
    # 将接口1的返回值res_1作为请求参数,请求接口2
    res = requests.post(url=url_2, data=get_api_1_result)
    # 断言
    assert res == "接口2预期的返回结果"

Among them, the fixture will first passyield, returnres_1, and pass it into the test casetest_api_2,. , that is, execute test_api_2After the execution is completed, execute the code following yieldprint("清空脏数据")

Through the above comparison of , and the passing of parameters in unittest, we can intuitively see that How to use in , the code here is only an example. setupteardownpytestyield

The execution order of yield

Sometimes we encounter a fixture function calling another or multiple fixture functions, and these functions may contain yield. Let's look at the example first. The code is as follows:

import pytest

@pytest.fixture
def fixture_1():
    print("\n执行fixture_1")
    yield 1
    print("\n执行fixture_1的teardown代码")

@pytest.fixture
def fixture_2(fixture_1):
    print("\n执行fixture_2")
    yield 2
    print("\n执行fixture_2的teardown代码")

@pytest.fixture
def fixture_add(fixture_1, fixture_2):
    print("\n执行fixture_add")
    result = fixture_1 + fixture_2
    yield result
    print("\n执行fixture_add的teardown代码")

    
def test_demo(fixture_add):
    print("\n执行测试函数test_demo")
    assert fixture_add == 3


if __name__ == '__main__':
    pytest.main(["-s"])

The running results are as follows:

rootdir: E:\blog\python接口自动化\apiAutoTest, configfile: pytest.ini
plugins: html-2.1.1, metadata-1.10.0, ordering-0.6, rerunfailures-9.1.1
collecting ... collected 1 item

test_case_4.py::test_demo 
执行fixture_1

执行fixture_2

执行fixture_add
PASSED                                         [100%]
执行测试函数test_demo

执行fixture_add的teardown代码

执行fixture_2的teardown代码

执行fixture_1的teardown代码


============================== 1 passed in 0.12s ==============================

It can be seen from the results:

Before the test_demo test function is executed: fixture_1 is executed first, then fixture_2 is executed, and finally fixture_add is executed. Note that at this time, the code before yield is executed;

After the test_demo test function is executed: fixture_add is executed first, then fixture_2 is executed, and finally fixture_1 is executed. Note that at this time, the code after yield is executed.

Therefore, when a fixture function calls another or multiple fixture functions, and the fixture function containsyield, when the tested function is called The execution sequence is as follows:

  • Before the test function is executed, pytest will call sequentially according to the linear relationship between fixture functions, that is, execute them in sequenceyieldPrevious code.

  • After the test function is executed, pytest will execute in the reverse direction according to the previous order in the function The code after. fixtureyield

finalizer

finalizer is the terminator (terminator function), which has the same function as teardown in unittest. The terminator code is executed after the test case is executed.

In pytest, in addition to using yield for teardown, fixtures can also use request.addfinalizer()definitionfinalizer for post-processing.

To useaddfinalizer, you need to pass in request when defining the fixture function and define it in the form of an inline function. One or more final functions can be defined.

Define a single final function

Examples are as follows:

import pytest

@pytest.fixture
def fixture_demo(request):
    print("\nsetup:每个case开始前执行一次")

    # 定义终结函数
    def finalizer_demo():
        print("\nteardown:每个case完成后执行一次")

    # 将finalizer_demo注册为终结函数
    request.addfinalizer(finalizer_demo)


def test_2(fixture_demo):
    print("\n执行test_2")

def test_1(fixture_demo):
    print("\n执行test_1")


if __name__ == '__main__':
    pytest.main()

The running results are as follows:

rootdir: E:\blog\python接口自动化\apiAutoTest, configfile: pytest.ini
plugins: html-2.1.1, metadata-1.10.0, ordering-0.6, rerunfailures-9.1.1
collecting ... collected 2 items

test_module_02\test_case_3.py::test_2 
setup:每个case开始前执行一次
PASSED                             [ 50%]
执行test_2

teardown:每个case完成后执行一次

test_module_02\test_case_3.py::test_1 
setup:每个case开始前执行一次
PASSED                             [100%]
执行test_1

teardown:每个case完成后执行一次


============================== 2 passed in 0.03s ==============================

It can be seen from the results that the addfinalizer function will be executed after the test case is executed, and the effect is consistent with the code after executing yield.

Define multiple final functions

Examples are as follows:

import pytest

@pytest.fixture
def fixture_demo(request):
    print("\nsetup:每个case开始前执行一次")

    # 定义终结函数
    def finalizer_demo_1():
        print("\nteardown1:每个case完成后执行一次")

    def finalizer_demo_2():
        print("\nteardown2:每个case完成后执行一次")

    # 注册为终结函数
    request.addfinalizer(finalizer_demo_1)
    request.addfinalizer(finalizer_demo_2)


def test_2(fixture_demo):
    print("\n执行test_2")

def test_1(fixture_demo):
    print("\n执行test_1")


if __name__ == '__main__':
    pytest.main()

The running results are as follows:

rootdir: E:\blog\python接口自动化\apiAutoTest, configfile: pytest.ini
plugins: html-2.1.1, metadata-1.10.0, ordering-0.6, rerunfailures-9.1.1
collecting ... collected 2 items

test_module_02\test_case_3.py::test_2 
setup:每个case开始前执行一次
PASSED                             [ 50%]
执行test_2

teardown2:每个case完成后执行一次

teardown1:每个case完成后执行一次

test_module_02\test_case_3.py::test_1 
setup:每个case开始前执行一次
PASSED                             [100%]
执行test_1

teardown2:每个case完成后执行一次

teardown1:每个case完成后执行一次


============================== 2 passed in 0.02s ==============================

As can be seen from the results, after the test function in the above example is executed, finalizer_demo_2 is executed first, and then finalizer_demo_1 is executed.

So, when there aremultiple final functions executed, the execution order and registration order are Opposite.

Summarize

In actual projects, you can choose according to the situation, but in general, it is recommended to use yield, because this way the code is more concise and efficient, more readable and easier to maintain.

 Recommended tutorials related to automated testing:

The latest automated testing self-study tutorial in 2023 is the most detailed tutorial for newbies to get started in 26 days. Currently, more than 300 people have joined major companies by studying this tutorial! ! _bilibili_bilibili

2023 latest collection of Python automated test development framework [full stack/practical/tutorial] collection essence, annual salary after learning 40W+_bilibili_bilibili

Recommended tutorials related to test development

The best in the entire network in 2023, the Byte test and development boss will give you on-site teaching and teach you to become a test and development engineer with an annual salary of one million from scratch_bilibili_bilibili

postman/jmeter/fiddler test tool tutorial recommendation

The most detailed collection of practical tutorials on JMeter interface testing/interface automated testing projects. A set of tutorials for learning jmeter interface testing is enough! ! _bilibili_bilibili

To teach yourself how to capture packets with fiddler in 2023, please be sure to watch the most detailed video tutorial on the Internet [How to Learn to Capture Packets with Fiddler in 1 Day]! ! _bilibili_bilibili

In 2023, the whole network will be honored. The most detailed practical teaching of Postman interface testing at Station B can be learned by novices_bilibili_bilibili

  Summarize:

 Optical theory is useless. You must learn to follow along and practice it in order to apply what you have learned to practice. At this time, you can learn from some practical cases.

If it is helpful to you, please like and save it to give the author an encouragement. It also makes it easier for you to search quickly next time.

If you don’t understand, please consult the small card below. The blogger also hopes to learn and improve with like-minded testers.

At the appropriate age, choose the appropriate position and try to give full play to your own advantages.

My path to automated test development is inseparable from plans at each stage, because I like planning and summarizing.

Test development video tutorials and study notes collection portal! !

おすすめ

転載: blog.csdn.net/m0_70618214/article/details/134839746