Detailed explanation of fixture test fixture of pytest framework

 

1. Advantages of fixtures
The fixture test fixture of the pytest framework is equivalent to the setup and teardown of the unittest framework, but its functions are more powerful and flexible.

The naming method is flexible, not limited to the setup and teardown of unittest
. Data sharing can be realized. Multiple modules can be shared across files. The front and rear positions
can be realized. Multiple modules can be used across files to use one session to complete multiple use cases.
Functions that unittest cannot achieve, such as It is impossible to pass parameters and data between test cases and test cases in unittest, but fixture can solve this problem
2. Fixture definition and call
key code: @pytest.fixture(), used to declare that the function is to process the pre-post Set the test fixture function. Usage is as follows:

@pytest.fixture()
def my_fixture():	# 记住这个夹具名
    print("我的测试夹具")

The test fixture has been defined, so how to call the test case? There are three ways:

Method 1: Pass the fixture name as a parameter to the test case, you can pass multiple fixtures, and execute in sequence
Method 2: Decorator: @pytest.mark.usefixtures(fixture_name) is used on the class, which means that all test cases of this class will Calling this fixture is used on the use case, which means that only this use case can call this fixture to use multiple fixtures, and execute them in sequence. If the fixture has a return value, the return value cannot be obtained with this decorator, and it cannot be passed to the use case. For data, you can only use method 1
and method 3: the fixture sets autouse=True to call automatically, and when the fixture has a return value, the return value cannot be obtained

import pytest
 
 
@pytest.fixture()
def my_fixture():	# 记住这个夹具名
    print("我的测试夹具")
 
# 方式一
def test_fix1(my_fixture):
    print("这是测试用例1111")
    print("-------分割线------")
 
 
# 方式二
# 类中应用
@pytest.mark.usefixtures("my_fixture")
class TestLogin:
 
    def test_fix2(self):
        print("这是测试用例2222")
        print("-------分割线------")
 
    def test_fix3(self):
        print("这是测试用例3333")
        print("-------分割线------")
 
# 测试用例应用
@pytest.mark.usefixtures("my_fixture")
def test_fix4():
    print("这是测试用例4444")
    print("-------分割线------")
 
 
# 方式三
def test_fix5():  # 未声明使用测试夹具
    print("这是测试用例5555")
 
 
if __name__ == "__ma__":
    pytest.main()

operation result:

Testing started at 23:12 ...
C:\software\python\python.exe ...
 
test.py 我的测试夹具
.这是测试用例1111
-------分割线------
我的测试夹具
.这是测试用例2222
-------分割线------
我的测试夹具
.这是测试用例3333
-------分割线------
我的测试夹具
.这是测试用例4444
-------分割线------
.这是测试用例5555
                                                              [100%]
 
============================== 5 passed in 0.02s ==============================
 
Process finished with exit code 0

​ Why is the test fixture not used in method 3, because the automatic call of the test fixture has not been set yet. There is a parameter autouse (meaning automatic use) in the fixture. The default is False. When it is set to True, the use case will automatically call the fixture function, so that you don’t need to pass parameters every time when writing a use case.

@pytest.fixture(autouse=True)	# 设置用例自动调用该fixture
def my_fixture():
    print("我的测试夹具")

3. Fixture scope
There is also a setUpClass and tearDownClass in unittest, which act on the class. Before each test case class is executed, it is pre-executed, and after the use case class is executed, it is executed after the execution. The fixture of pytest also has this The scope of the application is wider and more flexible.

​ Key code: @pytest.fixture(scope='scope of action'), the parameters are as follows:

function: default scope, every test case
is run once The whole process is only executed once​ Priority: session > package > module > class > function, the one with the higher priority will be instantiated before the lower fixture.



​ Fixtures of the same scope follow the order of declarations in the function, and follow the dependencies between fixtures. For example, fixture_B dependent in fixture_A is instantiated first, and then instantiated in fixture_A

​ We used the default scope when we used the example of fixture in the previous example. Here is an example of the scene where the scope is class:

# 因为用于演示,因此测试夹具直接写在py文件中
import pytest
from selenium import webdriver
 
 
@pytest.fixture(scope='class')
def my_fixture():
    """前置条件"""
    print("前置条件-启动浏览器")
    driver = webdriver.Chrome()
    yield driver
    driver.quit()
    print("后置条件-关闭浏览器")
 
 
class TestCase:
 
    def test_case01(self, my_fixture):    # 这里通过参数传入my_fixture函数,用例执行前会先去执行my_fixture
        driver = my_fixture    # my_fixture不需要加括号
        driver.get('http://www.baidu.com')
        print('第一个用例')
        assert 1 == 1
 
    def test_case02(self, my_fixture):    # 这里通过参数传入my_fixture函数,用例执行前会先去执行my_fixture
        driver = my_fixture    # my_fixture不需要加括号
        driver.get('http://www.cnblogs.com/')
        print('第二个用例')
        assert 1 == 1
 
 
if __name__ == '__ma__':
    pytest.main(['test.py', '-s'])

The running results are as follows. It can be seen from the running results that the entire class only opens the browser once.

C:\software\python\python.exe D:/learn/test.py
============================= test session starts =============================
platform win32 -- Python 3.7.3, pytest-5.2.2, py-1.8.0, pluggy-0.13.0
rootdir: D:\learn
plugins: html-2.0.0, metadata-1.8.0
collected 2 items
 
test.py 前置条件-启动浏览器
第一个用例
.第二个用例
.后置条件-关闭浏览器
 
 
============================== 2 passed in 9.76s ==============================
 
Process finished with exit code 0

​ Another parameter autouse of the fixture was also mentioned earlier. When autouse=True, the use case will automatically execute the test fixture, but the return value of the fixture cannot be obtained, and the driver returned by the above example cannot be passed to the use case.

​ If you want the use case to automatically execute the test fixture and hope that the driver and other parameters can be returned to the use case, you can try to store the value in a temporary variable when using the yield keyword in the test fixture to return the value, and then let the use case fetch the temporary variable The value in , here is no example, the following is a simple example of autouse=True: (the yield keyword will be explained in the following chapters)

# 因为用于演示,因此测试夹具直接写在py文件中
import pytest
from selenium import webdriver
 
 
@pytest.fixture(scope='class', autouse=True)	# 所有类自动执行该测试夹具
def my_fixture():
    """前置条件"""
    print("前置条件-启动浏览器")
    driver = webdriver.Chrome()
    yield driver
    driver.quit()
    print("后置条件-关闭浏览器")
 
 
class TestCase:
 
    def test_case01(self):	# 不需要传入测试夹具
        print('第一个用例')
        assert 1 == 1
 
    def test_case02(self):
        print('第二个用例')
        assert 1 == 1
 
 
if __name__ == '__ma__':
    pytest.main(['test.py', '-s'])

Finally:  In order to give back to the die-hard fans, I have compiled a complete software testing video learning tutorial for you. If you need it, you can get it for free 【保证100%免费】

                              How to obtain the full set of materials: Click the small card below to get it yourself
 

Guess you like

Origin blog.csdn.net/2301_76643199/article/details/132149009