[python automation] pytest series (completed)

insert image description here

There are four articles in the pytest series, and this article is the fourth and final article.

In response to my friends’ messages, I hope I can summarize these pytest articles.

Public account: Meng Wuji’s road to test development, reply to pytest to receive the corresponding summary information

Knowledge points in this chapter

Advanced usage of Pytest

(1) Parameterization

@pytest.mark.parametrize("参数名",列表数据)
'''
参数名:用来接收每一项数据,并作为测试用例的参数。
列表数据:一组测试数据。
'''
@pytest.mark.parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None))
parameter illustrate
argnames Required, parameter name, a comma-separated string representing one or more parameter names (keys), or a list/tuple of parameter strings
argvalues Required, the parameter value is passed in. If there is one argnames, a single value list is passed in. If there are multiple argnames, it is displayed as a list of tuples. The tuple corresponds to the parameter name one-to-one.
indirect When it is true, the argnames must be a fixture function name, and the argvalues ​​value will be passed into the corresponding fixture, which is equivalent to the usage of @pytest.fixture(params=). The default is False
ids Mark sub-use case execution name, consistent with the number of argvalues, automatically generated if not specified, default None
scope If specified, represents the range of the parameter. Scopes are used to group tests by parameter instances. It will also override the scope defined by any fixture function, allowing dynamic scope to be set using the test context or configuration
#示例
# 这里参数名 a,b,c,对应传入进去的参数a,b,c,需要一一对应。
# 如果只写了一个参数,那么就表示后面每一个以逗号分隔的内容,都为一组数据。
@pytest.mark.parametrize("a,b,c",[(1,2,3),(7,8,15),(2,2,3),(9,6,15)])
def test_add(a,b,c):
    sum = a+b
    assert sum==c
    
    ### 运行结果 ###
============================= test session starts =============================
collecting ... collected 4 items

test_004_参数化.py::test_add[1-2-3] PASSED                               [ 25%]
test_004_参数化.py::test_add[7-8-15] PASSED                              [ 50%]
test_004_参数化.py::test_add[2-2-3] FAILED                               [ 75%]
test_004_参数化.py:12 (test_add[2-2-3])
4 != 3

Expected :3
Actual   :4
<Click to see difference>

a = 2, b = 2, c = 3

    @pytest.mark.parametrize("a,b,c",[(1,2,3),(7,8,15),(2,2,3),(9,6,15)])
    def test_add(a,b,c):
        sum = a+b
>       assert sum==c
E       assert 4 == 3

test_004_参数化.py:16: AssertionError

test_004_参数化.py::test_add[9-6-15] PASSED                              [100%]

========================= 1 failed, 3 passed in 0.06s =========================

Combination parameterization: multiple sets of parameters, combined in sequence, Cartesian product

@pytest.mark.parametrize("x",[2,4,6])
@pytest.mark.parametrize("y",[1,3,5])
def test_add(x,y):
    print(f"x:{
      
      x},y:{
      
      y}")

9 sets of test cases will be generated

============================= test session starts =============================
collecting ... collected 9 items

test_004_参数化.py::test_add[1-2] PASSED                                 [ 11%]x:2,y:1

test_004_参数化.py::test_add[1-4] PASSED                                 [ 22%]x:4,y:1

test_004_参数化.py::test_add[1-6] PASSED                                 [ 33%]x:6,y:1

test_004_参数化.py::test_add[3-2] PASSED                                 [ 44%]x:2,y:3

test_004_参数化.py::test_add[3-4] PASSED                                 [ 55%]x:4,y:3

test_004_参数化.py::test_add[3-6] PASSED                                 [ 66%]x:6,y:3

test_004_参数化.py::test_add[5-2] PASSED                                 [ 77%]x:2,y:5

test_004_参数化.py::test_add[5-4] PASSED                                 [ 88%]x:4,y:5

test_004_参数化.py::test_add[5-6] PASSED                                 [100%]x:6,y:5


============================== 9 passed in 0.03s ==============================

Process finished with exit code 0

(2)pytest.ini

1. The pytest configuration file can change the running mode of pytest. It is a fixed file pytest.ini file. It reads the configuration information and runs it in the specified way.

2. Location: Generally placed in the root directory of the project (that is, under the top-level folder of the current project)

3. Naming: pytest.ini, no Chinese symbols can be used, including Chinese characters, spaces, quotation marks, colons, etc.

4. Running rules: Whether running in main function mode or command line mode, this global configuration file will be automatically read.

display

[pytest]
markers = 
	mark1:描述
	mark2:描述
	mark3:描述
addopts = -vs
;指定pytest最低版本号
minversion = 7.0
;pytest默认是搜索执行当前目录下的所有以test_开头的测试用例;
;我们可以在pytest.ini配置testpaths = test_case/test_001.py,则只执行当前配置的文件夹下或文件里的指定用例,可配置多个,空格隔开
testpaths = ./testcase

;模块名的规则,配置测试搜索的模块文件名称
python_files = test*.py

;类名的规则,配置测试搜索的测试类名
python_classes = Test*

;方法名的规则,配置测试搜索的测试函数名
python_functions = test

① marks mark

Marking: marks function

  • Mark the use cases, and when running, only the marked use cases will be run.
  • 300 regression use cases. – Mark 50 as a smoke test.

1. You must first register the tag name

pytest.ini

[pytest]
    markers = 
        mark1:标签说明(只能英文,可不写)
        mark2:标签说明(只能英文,可不写)
        mark3:标签说明(只能英文,可不写)

2. Mark test cases/test classes

basic use

 @pytest.mark.已注册的标记
 # 如
 @pytest.mark.mark1

To label the test class, use the following statement (under the test class, all use cases are labeled with this label):

class TestClass():
    pytestmark = pytest.mark.已注册标签名
    # 或者 多标签模式
    pytestmark = [pytest.mark.标签名1,pytest.mark.标签名2] 

Label the module file and use the following statement (under the py file, all test functions and test functions in the test class are labeled with this label)

import pytest
pytestmark = pytest.mark.已注册标签名
# 或者 多标签模式
pytestmark = [pytest.mark.标签名1,pytest.mark.标签名2]

3. Set runtime to only run marked use cases.

pytest命令行: -m 标记名
在收集到的所有用例中,只运行对应标记名的用例。

4. Marks can be superimposed

② addopts configuration

parameter effect
-s Indicates output debugging information, used to display the information printed by print() in the test function
-v Before adding, only the module name is printed. After adding v, it prints the class name, module name, and method name to display more detailed information.
-q Indicates that only the overall test results are displayed
-vs These two parameters can be used together
-n Supports multi-threaded or distributed running test cases (prerequisite: pytest-xdist plug-in needs to be installed)
–html Generate html test reports (prerequisite: pytest-html plug-in installed) such as: pytest -vs --html ./reports/result.html
-x Indicates that as long as one test case reports an error, execution will stop.
-k Fuzzy matching, part of the string of the test case, specifies the execution of the test case.
-m mark mark

(3)pytest.mark.related

1. Skip execution directly

@pytest.mark.skip

insert image description here

2. Skip execution if conditions are met

@pytest.mark.skipif
根据特定的条件,不执行标识的测试函数.
 方法:
     skipif(condition, reason=None)
 参数:
     condition:跳过的条件,必传参数
     reason:标注原因,必传参数
 使用方法:
     @pytest.mark.skipif(condition, reason="xxx") 

When condition is True, skip, otherwise execute

insert image description here

3. Mark as expected failure function

标记测试函数为失败函数
 方法:
     xfail(condition=None, reason=None, raises=None, run=True, strict=False)
 常用参数:
     condition:预期失败的条件,必传参数
     reason:失败的原因,必传参数
 使用方法:
     @pytest.mark.xfail(condition, reason="xx")

When condition is True, this use case is marked as xpassed, otherwise it is marked as passed.

insert image description here

4. Repeat the test

Use the "@pytest.mark.repeat" decorator to run test cases repeatedly

import pytest

@pytest.mark.repeat(3)
def test_something():
    assert 1 + 1 == 2

This test case will be run three times.

5. Dependency testing

Mark dependencies between test cases using the "@pytest.mark.dependency" decorator to ensure prerequisites are run before required test cases

import pytest

@pytest.mark.dependency()
def test_login():
    assert True

@pytest.mark.dependency(depends=["test_login"])
def test_access_profile():
    assert True

@pytest.mark.dependency(depends=["test_login"])
def test_access_settings():
    assert True

(4) Rerun after failure

If a use case fails, the use case can be rerun.

Plugins need to be installedrerunfailures

installation method:

pip install pytest-rerunfailures

How to use:

Command line parameter form:

# 命令
pytest --reruns 重试次数
pytest --reruns 3 :运行失败的用例可以重新运行3次

expand

#
pytest --reruns 重试次数 --rerun-dalay 次数之间的延时设置(单位:秒)

# 示列
pytest  --reruns 3 --rerun-dalay 5
表示失败的用例可以重新运行3次,每次重运行间隔5秒。

(5) Specify the running order of use cases

As mentioned earlier, pytest has its own use case execution order, but sometimes we just want to specify it to execute in our own way. Is there any way?

pytest has a plug-in that can achieve this function pytest-ordering: specify the running order of use cases

1. Install dependency packages

pip install pytest-ordering

2. Use of pytest-ordering

Control the execution order of cases through decorator methods

1. Method 1:

- 第一个执行:		@ pytest.mark.run('first')
- 第二个执行:		@ pytest.mark.run('second')
- 倒数第二个执行:	@ pytest.mark.run('second_to_last')
- 最后一个执行:		@ pytest.mark.run('last')

2. Method two:

 - 第一个执行:		@ pytest.mark.first
 - 第二个执行:		@ pytest.mark.second
 - 倒数第二个执行:	  @ pytest.mark.second_to_last
 - 最后一个执行:	   @pytest.mark.last

3. Method three:

 - 第一个执行:		@ pytest.mark.run(order=1)
 - 第二个执行:		@ pytest.mark.run(order=2)
 - 倒数第二个执行:	  @ pytest.mark.run(order=-2)
 - 最后一个执行:	    @ pytest.mark.run(order=-1)

Execution priority:
0>small positive number>large positive number>unmarked>small negative number>large negative number

(6) Use cases depend on each other

Scenario: There is an operation function related to addition, deletion, modification and query. When the addition operation case fails, the deletion, modification and query operations are not executed. How to deal with this scenario? The Pytest framework provides a pytest-dependency plug-in to help us do this, we only need to use it simply.

Install

  • In the command line window enter:pip install pytest-dependency
  • Check the installed version:pip show pytest-dependency

use

Usage: @pytest.mark.dependency()Mark the dependent test cases and use to @pytest.mark.dependency(depends=["测试用例名称"])reference dependencies. The test case name can be multiple

Description: When the dependent use case fails to execute, the dependent use case is skipped directly.

# !/usr/bin/python3
# _*_coding:utf-8 _*_
import pytest

@pytest.mark.dependency()
def test_add():
    print("我是 test_add 用例")
    assert False

@pytest.mark.dependency(depends=["test_add"])
def test_update():
    print("我是 test_update 用例")
    assert False

@pytest.mark.dependency(depends=["test_add"])
def test_delete():
    print("我是 test_delete 用例")
    assert True

@pytest.mark.dependency(depends=["test_add"])
def test_select():
    print("我是 test_select 用例")
    assert True

if __name__ == '__main__':
    pytest.main(["-s"])
  • Use @pytest.mark.dependency() to mark dependent test cases, and use @pytest.mark.dependency(depends=["test case name"]) to reference dependencies. The test case name can be multiple

  • When a use case often has multiple dependencies, as long as one dependency fails, the dependent use case will be skipped and all dependencies will be executed only if they succeed.

There are other plug-ins and functions that you can explore by yourself in the plug-in library.

other

Error 1: DeprecationWarning:

DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.

if version.LooseVersion(pytest.version) >= version.LooseVersion(“6.0”):

Many people on the Internet say that the version is too low. After verification, I found that it is not the case, but that pytest has many related dependencies. The current environment cannot match some of the dependencies required by the currently installed pytest, such as Allure and the like.

So a very simple approach is to re-create a python environment and keep a project with a clean environment, so that there will be no similar dependency conflicts, warnings or even errors if mutual dissatisfaction occurs.

insert image description here

Enter the virtual environment, click Terminal in pycharm and select Command Prompt. If there are brackets in front of it, you have entered the virtual environment.

#退出虚拟环境
deactivate
#进入虚拟环境,重开命令窗口更快
activate

insert image description here

At this point, the pytest series is completed. Thank you all for reading so far. You must be the best ~

Guess you like

Origin blog.csdn.net/qq_46158060/article/details/132430139