fixture - scope in interface automation - pytest
introduce
There is little introduction to fixture in the article. Students can search the detailed explanation of fixture or look at the source code
Before that, bloggers used the unittest unit test framework to write interface automation, which is also very useful. However, after learning about the fixture and allure of pytest, there was a real fragrance warning!!
First of all, the fixture source code contains several cores, and I picked out a part of the source code
def fixture( fixture_function: Optional[_FixtureFunction] = None, *, scope: "Union[_Scope, Callable[[str, Config], _Scope]]" = "function", params: Optional[Iterable[object]] = None, autouse: bool = False, ids: Optional[ Union[ Iterable[Union[None, str, float, int, bool]], Callable[[Any], Optional[object]], ] ] = None, name: Optional[str] = None, )
1,scope 2,params 3,autouse 4,ids
This article explains the first scope in detail. Because it is too detailed and non concise, it is suitable for Xiaobai to watch
Scope: controls the scope of the fixture
scope contains four functions
1,function
Each function will be called. Usage: add @ pytest.fixture() to the fixture function There is no need to add function in brackets. If it is not transmitted, it is function by default
2,class
Each class is called once, and the method under each class is the concept of fusion Usage: add @ pytest.fixture('class') to the fixture function
3,module
Each py file is called once. The methods and classes inside are the concepts of class and function Usage: add @ pytest.fixture('module ') to the fixture function
4,session
Multiple py files are called once, and each py file is the concept of module Usage: add @ pytest.fixture('session ') to the fixture function
Explain in detail
When the function calls the fixture function, it is preceded
1, function
In the following code, you can see that we set a fixture function function, and then each function in pytest can call fixture function
import pytest @pytest.fixture() def getsql_project(): #Add the @ pytest.fixture() decorator above the fxture we need to set project_id = 335 project_id2 = 332 print('Verify the execution of the preceding') return project_id,project_id2 def test_set_project1(getsql_project): #When we use the fixture function, we just call it in parentheses. print('first id yes',getsql_project[0]) def test_set_project2(getsql_project): print('the second id yes', getsql_project[1]) if __name__ == '__main__': pytest.main(["-s","test_fixture.py"])
The returned results are as follows
============================= test session starts ============================= collecting ... collected 2 items test_fixture_scope.py::test_set_project1 Verify the execution of the preceding PASSED [ 50%]first id yes 335 test_fixture_scope.py::test_set_project2 Verify the execution of the preceding PASSED [100%]the second id yes 332 ============================== 2 passed in 0.08s ============================== Process finished with exit code 0
As you can see, each method calls the fixture function once
2, class
A class can only be triggered once
import pytest @pytest.fixture(scope='class') def getsql_project(): #Add the @ pytest.fixture() decorator above the fxture we need to set project_id = 335 project_id2 = 332 print('Verify the execution of the preceding') return project_id,project_id2 class Test_fixture: def test_set_project1(self,getsql_project): #When we use the fixture function, we just call it in parentheses. print('first id yes',getsql_project[0]) def test_set_project2(self,getsql_project): print('the second id yes', getsql_project[1]) if __name__ == '__main__': pytest.main(["-s","test_fixture.py"])
Return results
============================= test session starts ============================= collecting ... collected 2 items test_fixture_scope.py::Test_fixture::test_set_project1 test_fixture_scope.py::Test_fixture::test_set_project2 ============================== 2 passed in 0.09s ============================== Process finished with exit code 0 Verify the execution of the preceding PASSED [ 50%]first id yes 335 PASSED [100%]the second id yes 332
It can be seen that the verification of whether the pre execution is performed is only performed once, which means that both of our methods call the fixture function, which is actually performed only once
3, module
A py file can only be executed once
Let's first take a look. We have multiple classes, and each class calls the next fixture function
import pytest @pytest.fixture(scope='module') def getsql_project(): #Add the @ pytest.fixture() decorator above the fxture we need to set project_id = 335 project_id2 = 332 print('Verify the execution of the preceding') return project_id,project_id2 class Test_fixture: def test_set_project1(self,getsql_project): #When we use the fixture function, we just call it in parentheses. print('First class id1',getsql_project[0]) def test_set_project2(self,getsql_project): print('First class id2', getsql_project[1]) if __name__ == '__main__': pytest.main(["-s","test_fixture.py"]) class Test_fixture2: def test_set_project3(self,getsql_project): #When we use the fixture function, we just call it in parentheses. print('Second class id1',getsql_project[0]) def test_set_project4(self,getsql_project): print('Second class id2', getsql_project[1]) if __name__ == '__main__': pytest.main(["-s","test_fixture.py"])
Return the result (you can see whether the verification is pre executed It is executed twice, because each class defined by us is executed once, so it is executed twice)
============================= test session starts ============================= collecting ... collected 4 items test_fixture_scope.py::Test_fixture::test_set_project1 test_fixture_scope.py::Test_fixture::test_set_project2 test_fixture_scope.py::Test_fixture2::test_set_project3 Verify the execution of the preceding PASSED [ 25%]First class id1 335 PASSED [ 50%]First class id2 332 test_fixture_scope.py::Test_fixture2::test_set_project4 ============================== 4 passed in 0.09s ============================== Process finished with exit code 0 Verify the execution of the preceding PASSED [ 75%]Second class id1 335 PASSED [100%]Second class id2 332
Here's the point
At this point, we will replace class with module
@pytest.fixture(scope='module')
Return result (in the whole py file, no matter multiple class calls, it is only run once)
============================= test session starts ============================= collecting ... collected 4 items test_fixture_scope.py::Test_fixture::test_set_project1 test_fixture_scope.py::Test_fixture::test_set_project2 test_fixture_scope.py::Test_fixture2::test_set_project3 Verify the execution of the preceding PASSED [ 25%]First class id1 335 PASSED [ 50%]First class id2 332 test_fixture_scope.py::Test_fixture2::test_set_project4 ============================== 4 passed in 0.08s ============================== Process finished with exit code 0 PASSED [ 75%]Second class id1 335 PASSED [100%]Second class id2 332
4, session
Generally, our fixtures are unloaded under the confitest.py file in the directory. If two py files call the fixture function under confitest.py, if the fixture is in session form, multiple pYS can use the data returned by this function, but they will not be called repeatedly.
Create a new confitest.py file and put our fixture function in it
import pytest @pytest.fixture(scope='module') def getsql_project(): #Add the @ pytest.fixture() decorator above the fxture we need to set project_id = 335 project_id2 = 332 print('Verify the execution of the preceding') return project_id,project_id2
Then multiple pYS call getsql at the same time_ project It is actually called only once
test_fixture_scope.py::Test_fixture::test_set_project1 test_fixture_scope.py::Test_fixture::test_set_project2 test_fixture_scope.py::Test_fixture2::test_set_project3 Verify the execution of the preceding PASSED [ 25%]First class id1 335 PASSED [ 50%]First class id2 332 test_fixture_scope.py::Test_fixture2::test_set_project4 ============================== 4 passed in 0.08s ============================== Process finished with exit code 0 PASSED [ 75%]Second class id1 335 PASSED [100%]Second class id2 332