In the last article, I shared the basic usage of pytest. This article further introduces other practical features and advanced techniques of pytest.
Pytest can be used@pytest. Fixture decorator is used to decorate a method. The method name of the decorated method can be passed into the test method as a parameter. You can use this method to complete the initialization before the test, or you can return data to the test function.
Usually, setup and teardown are used to initialize resources. If there is such a scenario, test case 1 needs to rely on the login function, test case 2 does not need the login function, and test case 3 needs the login function. Teardown cannot implement this scenario setup. You can use the pytest fixture function to add a@pytest. Fixture decorator. The method with this decorator can be passed into the method in the form of parameters for execution.
For example, in the login method, add@pytest. After the decorator fixture, pass the name of the use case method to the method in the form of parameters. The method will first execute the login method, and then execute its own use case steps. If the login method is not passed in, it will not execute the login operation, and directly execute the existing steps.
Create a file named “test_fixture.py” with the following code:
In the above code, the test case test_ Case1 and test_ Case3 adds the login method name as the parameter, and pytest will find and call it@pytest. The login function of fixture tag, and the test results are as follows:
As can be seen from the above results, test_ Case1 and test_ Case3 executes the login method before running, test_ Case2 does not implement this method.
There is a parameter scope in the fixture. The scope can control the scope of the fixture. It is divided according to the size of the scope: session > module > class > function. The specific scope of action is as follows:
- Function function or method level will be called
- Class class level call once
- Module module level call once
- Session is called once by multiple files (it can be called across.Py files, and each.Py file is a module)
For example, there are multiple test cases in the whole module. You need to open the browser before all the cases are executed, and close the browser after all the cases are executed. The opening and closing operations are only performed once. If you re execute the opening operation every time, it will take up a lot of system resources. In addition to setup_ module,teardown_ Module can be implemented, and you can also set the fixture decorator at the module level（@pytest. Fixture (scope= “module”)).
Fixture parameter scope= ‘module’, the function of module is that the whole module will take effect.
Create a file named test_ fixture_ scope. Py, the code is as follows:
@pytest. If fixture() does not write parameters, the default parameter is scope= ‘function’. When scope= ‘module’, in the current All use cases in the PY script are executed only once before starting. Scope is cleverly combined with yield, which is equivalent to setup and teardown methods. You can also use@pytest. mark. Usefixtures decorator, pass in the prefix function name as the parameter.
The operation results are as follows:
From the above running results, we can see that the combination of scope= “module” and yield is equivalent to setup_ Module and teardown_ Module method. Before the whole module runs, it calls the printout “open browser” in front of yield in the open () method, and after the whole run, it calls the print statement “execute teardown!” And “close browser”. Yield to wake up the teardown execution. If the use case is abnormal, it will not affect the teardown execution after yield. Can use@pytest. mark. Usefixtures decorator to pass in methods.
If the fixture scope is at the session level, it can span Py module calls, that is, when we have multiple Py file, if multiple use cases only need to call fixture once, you can write scope= ‘session’ to confitest Py file. Write to conf test Py file can call the methods in it globally. There is no need to import confitest Py this file. Use conf test Py rules:
1.conftest. The file name py is fixed and cannot be changed.
2.conftest. Py and the running case are in the same package, and init Py file
3. There is no need to import confitest when using Py, pytest will automatically recognize this file
4. Put it under the root directory of the project and it can be called globally. Put it under a package and it is valid in this package.
When running all the use cases under the whole project, open the browser only once. Close the browser after executing all the use cases. You can create a confitest under this project Py file, put the method of opening the browser operation under this file, and add a decorator@pytest. Fixture (scope= “session”) can realize browser reuse of all test cases of the whole project. The case directory structure is as follows:
Create directory test_ Scope, and create three files conftest py，test_ Scope1.py and test_ scope2.py。
conftest. Py file defines public methods, and pytest will automatically read confitest Py, the code is as follows:
Create test_ Scope1.py file, the code is as follows:
Create the file “test_scope2.py” with the following code:
Open CMD and enter the directory test_ Scope/, execute the following command:
The implementation results are as follows:
During execution, pytest will automatically identify the confitest of the current directory Py, there is no need to import the method configuration in the direct reference. It is applied to all calls under the whole directory, and executed in the methods inside. conftest. Py and the running use case should be under the same pakage, and there is init under this package Py file
If each test case needs to add a fixture function, you need to pass in the name of the fixture in each test case method. Here, you can add a parameter autouse= ‘true’ in the decorator, which will be automatically applied to all test methods, but there is no way to return values to the test case.
For the method of use, add a decorator in front of the method, as follows:
@pytest. Set the value of the autouse parameter to true (false by default) in fixture, and each test function will automatically call this pre function.
Create a file named “test_autouse.py” with the following code:
Execute the above test file, and the results are as follows:
From the above running results, we can see that a decorator is added to the method myfixture ()@pytest. Fixture (autouse= “true”), the test case does not need to pass in the name of this fixture, and it will automatically execute this fixture before each use case.
A large amount of test data is needed in the test process. If each test data is written with a test case, the number of use cases will be very large. Generally, we will transfer the data used in the test to the test case in the form of parameters during the test, and generate a test result data for each test data.
At this time, you can use the parameterization function of fixture and add decorators to the fixture method@pytest. Fixture (params=[1,2,3]) will transfer three data 1, 2, and 3 into the use case respectively. The data that can be passed in here is a list. The incoming data needs to be received with a fixed parameter name request.
Create a file named “test_params.py” with the following code:
The operation results are as follows:
From the running results, we can see that for each value in params, fixture will call and execute once, using request Param to accept the parameterized data of use cases and generate a test result for each test data. Using this parameterization method in the testing work will reduce a lot of code and be easy to read and maintain.
If there are 1000 test cases in the project, one test case needs to be executed for 1 minute, and a tester needs 1000 minutes to complete a round of regression testing. Usually, we will exchange the labor cost for the time cost. If we add several people to execute it together, the time will be shortened. If it takes only 100 minutes for 10 people to execute together, this is a parallel testing, distributed scenario.
Pytest xdist is a pytest distributed execution plug-in, which can be executed by multiple CPUs or hosts. This plug-in allows users to execute tests concurrently (process level concurrency). The plug-in dynamically determines the execution order of test cases. In order to ensure that each test can be executed correctly in each independent thread, the independence of test cases should be guaranteed (which also conforms to the best practice of test case design).
When multiple CPUs execute use cases in parallel, you need to add the -n parameter after pytest. If the parameter is auto, the number of CPUs in the system will be automatically detected. If the parameter is a number, specify the number of processor processes to run the test.
There are 200 test cases in a project, and there is no correlation between each test case, which does not affect each other. These 200 test cases need to be tested within 1 hour. You can add a -n parameter and use multiple CPUs for parallel testing. Operation method:
Enter the project directory and execute pytest to identify and run all test cases under the project directory. With the -n parameter, you can specify four CPUs to execute concurrently. The concurrent execution speed of a large number of test cases is very obvious.
The test report is usually particularly important in the project. The report can reflect the workload of testers, and developers can understand the defects from the test report. Therefore, the status of the test report in the test process is very important. The test report provides a basis for correcting the quality problems of software and lays a foundation for software acceptance and delivery. According to the focus of the content, the test report can be divided into “version test report” and “summary test report”. After executing the pytest test test case, you can use the pytest HTML plug-in to generate a test report in HTML format.
Use with pytest xdist
Generate test report
The following figure:
The generated test report is finally in HTML format, and the report content includes the title, running time, environment, summary results, and the number of cases passed, skipped, failed, and errors, the number of expected failures, the number of unexpected passes, the number of reruns, and the detailed display of errors. The report will generate the same path where the script is running. You need to specify the path to add – html=path/to/html/report HTML this parameter configures the path of the report. If you do not add the parameter –self-contained-html, the CSS file that generates the report is independent, and it is easy to lose tens of millions of data when sharing.
When writing code, we often make some assumptions, and assertions are used to capture these assumptions in the code. Assertions are expressed as Boolean expressions, and testers usually add assertions to determine the correctness of the intermediate process. Assertions support displaying the values of the most common sub expressions, including calls, attributes, comparisons, and binary and unary operators. Python uses assert to judge an expression and trigger an exception when the expression condition is false.
The cases are as follows:
If there is no assertion, there is no way to determine the correctness of the results of each test step in the use case. Use assertions appropriately in the project to check and verify the structure, attributes, functions, security and other scenarios of the code.