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:
yield
replacesreturn
to pass parameters- functions as code division. The code before yield functions as
setup
, and the code after yield functions asteardown
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
yield
Parameters 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:fixture
yield
@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_2
After the execution is completed, execute the code following yield
print("清空脏数据")
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. setup
teardown
pytest
yield
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 sequence
yield
Previous 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.
fixture
yield
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! !