【python自动化】pytest系列(完结)

【python自动化】pytest系列(完结)_第1张图片

pytest系列文章一共有四篇,本文为第四篇完结篇。

应各位小伙伴留言,希望可以把这几篇pytest文章进行汇总。

公众号:梦无矶的测试开发之路,回复pytest可以领取对应汇总资料

本章知识点

文章目录

    • Pytest高阶用法
      • (1)参数化
      • (2)pytest.ini
        • ① marks标记
        • ② addopts配置
      • (3)pytest.mark.相关
        • 1、直接跳过执行
        • 2、满足条件跳过执行
        • 3、标记为预期失败函数
        • 4、重复测试
        • 5、依赖测试
      • (4)失败重运行
      • (5)指定用例的运行顺序
        • 1、安装依赖包
        • 2、pytest-ordering的使用
      • (6)用例相互依赖
        • 安装
        • 使用
    • 其他
      • 报错一:DeprecationWarning:

Pytest高阶用法

(1)参数化

@pytest.mark.parametrize("参数名",列表数据)
'''
参数名:用来接收每一项数据,并作为测试用例的参数。
列表数据:一组测试数据。
'''
@pytest.mark.parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None))
参数 说明
argnames 必传,参数名, 以逗号分隔的字符串,表示一个或多个参数名称(key),或参数字符串的列表/元组
argvalues 必传,参数值,若argnames有一个则单值列表传入,若argnames有多个,以套用元组的列表展示,元组内与参数名一一对应
indirect 为true时,那argnames一定是一个fixture函数名称,argvalues值将传入对应的fixture内,相当于@pytest.fixture(params=)的用法,默认False
ids 标记子用例执行名称,与argvalues数量一致,未指定自动生成,默认None
scope 如果指定,则表示参数的范围。范围用于按参数实例对测试进行分组。它还将覆盖任何fixture函数定义的范围,允许使用测试上下文或配置设置动态范围
#示例
# 这里参数名 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 =========================

组合参数化 : 多组参数,依次组合,笛卡尔积

@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组测试用例

============================= 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、pytest配置文件可以改变pytest的运行方式,它是一个固定的文件pytest.ini文件,读取配置信息,按指定的方式去运行

2、位置:一般放在项目的根目录(即当前项目的顶级文件夹下)

3、命名:pytest.ini,不能使用任何中文符号,包括汉字、空格、引号、冒号等等

4、运行的规则:不管是主函数模式运行,命令行模式运行,都会自动读取这个全局配置文件。

示列

[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标记

打标记: marks功能

  • 对用例打标记,运行的时候,只运行打标记的用例。
  • 300个回归用例。–打标记50个,作为冒烟测试。

1、得先注册标记名

pytest.ini

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

2、给测试用例/测试类打标记

基本使用

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

在测试类里面打标签,使用以下声明(测试类下,所有用例都被打上该标签):

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

在模块文件里打标签,使用以下声明(py文件下,所有测试函数和测试类里的测试函数,都被打上该标签)

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

3、运行时设置只运行标记的用例

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

4、可以叠加标记

② addopts配置

参数 作用
-s 表示输出调试信息,用于显示测试函数中print()打印的信息
-v 未加前只打印模块名,加v后打印类名、模块名、方法名,显示更详细的信息
-q 表示只显示整体测试结果
-vs 这两个参数可以一起使用
-n 支持多线程或者分布式运行测试用例(前提需安装:pytest-xdist插件)
–html 生成html的测试报告(前提需安装:pytest-html插件) 如:pytest -vs --html ./reports/result.html
-x 表示只要有一个测试用例报错,则执行停止
-k 模糊匹配,测试用例的部分字符串,指定执行测试用例。
-m mark标记

(3)pytest.mark.相关

1、直接跳过执行

@pytest.mark.skip

【python自动化】pytest系列(完结)_第2张图片

2、满足条件跳过执行

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

当condition为True则跳过,否则执行

【python自动化】pytest系列(完结)_第3张图片

3、标记为预期失败函数

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

当condition为True则将这条用例标记为xpassed,否则标记为passed

【python自动化】pytest系列(完结)_第4张图片

4、重复测试

使用"@pytest.mark.repeat"装饰器可以对测试用例进行重复运行

import pytest

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

这个测试用例会运行三次。

5、依赖测试

使用"@pytest.mark.dependency"装饰器标记测试用例之间的依赖关系,以确保在需要的测试用例之前运行先决条件

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)失败重运行

用例失败的情况下,可以重运行用例。

需要安装插件rerunfailures

安装方法:

pip install pytest-rerunfailures

使用方式:

命令行参数形式:

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

拓展

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

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

(5)指定用例的运行顺序

前面有讲到pytest有自己的用例执行顺序,但有时候我们就是想指定它按照我的方式去执行,有什么办法呢?

pytest有这样一个插件可以实现这个功能,pytest-ordering:指定用例的运行顺序

1、安装依赖包

pip install pytest-ordering

2、pytest-ordering的使用

通过装饰器的方法来控制case的执行顺序

1.方式一:

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

2.方式二:

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

3.方式三:

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

执行优先级:
0>较小的正数>较大的正数>无标记>较小的负数>较大的负数

(6)用例相互依赖

场景:存在一个增删改查相关的操作功能,当增加操作用例失败时,删除、修改、查询操作不执行,这种场景该怎么来处理呢?Pytest 框架提供了一个pytest-dependency 插件帮我们做了这件事情,我们只需要简单的使用即可。

安装

  • 在命令行窗口输入: pip install pytest-dependency
  • 查看安装版本:pip show pytest-dependency

使用

使用方法 : 用 @pytest.mark.dependency()对所依赖的用例进行标记,使用@pytest.mark.dependency(depends=["测试用例名称"]) 引用依赖,测试用例名称可以是多个

说明:当依赖的用例执行失败,被依赖的用例直接跳过

# !/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"])
  • 用 @pytest.mark.dependency()对所依赖的用例进行标记,使用@pytest.mark.dependency(depends=[“测试用例名称”]) 引用依赖,测试用例名称可以是多个

  • 用例多存在多个依赖时,只要存在一个依赖失败,被依赖用例就跳过,所有依赖成功才执行

还有其他插件和功能可以自行在插件库进行探索。

其他

报错一:DeprecationWarning:

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

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

网上很多说是版本过低啥的,我验证后发现,并不是,而是pytest有很多相关依赖,当前所用的环境和当前你安装的pytest所需要的一些依赖无法匹配,比如Allure之类的。

所以很简单的做法就是,你重新创建一个python的环境,保持一个项目拥有一套干净的环境,这样就不会出现类似的依赖冲突,相互不满足提示告警甚至报错的情况。

【python自动化】pytest系列(完结)_第5张图片

进入虚拟环境,在pycharm里面点击Terminal选择Command Prompt,前面显示有个括号的就是进入了虚拟环境。

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

【python自动化】pytest系列(完结)_第6张图片

至此,pytest系列完结,感谢各位小伙伴阅读至此,你一定是最棒的 ~

你可能感兴趣的:(python,自动化,pytest)