pytest学习理论笔记
Pytest 基本介绍
1. 作用: 我们通过 pytest 框架可以实现测试用例的自动执行,与其它的集成工具配置可以实现可持化集成自动化测试
2. 安装:
(1) Pip install -U pytest
(2) Pytest --version 可以展示出当前pytest 的版本号
3. Pytest 执行的默认规则
(1) Pytest 默认情况下会在当前文件所在的根目录下去查找要执行测试文件。而且可以穿透查找
(2) Pytest 默认情况下会去查找 以 test_打头 和 _test结尾的 py 文件
(3) Pytest 默认情况下会去查找 以 Test 打头的类
(4) Pytest 默认情况下会去查找以 test_ 打头的函数
4. Pytest 的调用方式
(1) 在具体的 py 文件中通过pytest.main() 去调用
(2) 在命令行中去调用【 推荐大家直接使用 pychram 集成的命令行,直接输入 pytest 命令即可 】
Pytest 配置文件
1. 作用: 可以自定义我们 pytest 在使用过程中需要的默认配置,例如修改文个名、测试脚本存放目录.......
2. Addopts : 在 pytest 命令后面可以添加的参数( -s )
3. Test_paths: 用于定义 pytest 框架默认在哪个路径下搜索被测文件
4. Python_files: 用于定义 pytest 框架默认找什么样的文件去执行
5. Python_classes: 用于定义 pytest 框架找什么样的类
6. Python_functions : 用于定义pytst 框架找什么样的函数
7. 关于 Pytest配置文件命名可以有三种: pytest.ini tox.ini setup.cfg
Pytest 插件安装
因为pytest 是支持第三方扩展的,所以我们可以通过安装对应的插件来让 pytest 实现更丰富的功能。
一、html 报告插件
1.安装: pip install 本地的包路径
2.调用: pytest --html=自定义路径
二、失败重试的插件
1.安装: pip install 本地的包路径
2.调用: pytest --reruns 次数 【 当我们当前的被测脚本在执行上出现失败的时候会按着我们所设定的次数再次去运行 】
3..(绿色的点)表示当前用例执行是通过的, R 表示当前用例执行了重试, F 表示当前用例执行是失败
控制执行顺序
1. 作用: 通过这个插件我们可以控制被测试函数的运行顺序
2. 安装: pip install 本地安装包
3. 使用:
@pytest.mark.run( order=数值 ) 【加在被测试函数的上方,形成装饰器】
4 规律:
A. 不论正负,数值越小权重越大
B. 正数的权重一定大于负数
C. 数值 0 权重是最大的
D. 如果不写 权重只会比负数
Setup+ teardown 函数
1. 作用:
(1) Setup 我们称之为叫配置函数,一般用于实现普通函数的前置条件准备。
(2) Teardown 我们称之为叫清理函数,用于将普通函数执行完成之后不再使用的资源进行关闭和清除
2. 细节:
(1) Setup 和teardown 一定要放在类的里面才有用
(2) Setup一定会先于 teardown 执行
(3) Setup 和 teardown 执行次数和当前被测试普通函数个数相关
(4) Setup一定会先于普通函数执行,而teardown 一定会后于普通函数执行
Setup_class + teardown_class 函数
1. 作用: 在原则上作用和上述的二个函数是一样的,只不过这二个函数的作用对象是类而非函数
2. 细节:
(1) Setup 和 setup_class 是可以同时存在的,如果二者同时存在那么优先执行 setup_class
(2) Setup_class 的执行次默认只有一次,因为它和类相关 。
Pytest 跳过功能
1. 作用:通过这个功能,我们可以在执行测试用例的时候有选择的去执行我们的测试函数及测试文件....
2. 跳过种类语法
#(1) 无条件跳:
@pytest.mark.skip()
#(2)有条件跳:
@pytest.mark.skipif( 条件表达式, reason=”跳过说明” )
# -*- coding=utf-8 -*-
import pytest
class TestDemo:
# 下面的操作就是 无条件跳过语法
@pytest.mark.skip()
def test_fn1(self):
print("测试函数1")
@pytest.mark.skipif(3>2, reason="当3大于2的时候跳过本次测试" )
def test_fn2(self):
print("测试函数2")
3. 跳过的对象:
(1) 跳过函数 :只会跳过当前指定的函数
(2) 跳过类: 会将该类下面的所有函数都跳过
(3) 跳过模块:会将一个py文件中所有的测试套件都跳过
Pytestmark = pytest.mark.skip|skipif() 此时需要注意的就是 pytestmark 这个变量不能自定义
# -*- coding=utf-8 -*- import pytest # 如果想要跳过整个模块(py文件)那么就可以使用下述的语法 # 需要注意的就是下面的这个变量名是不能自定义的,必须叫.... pytestmark = pytest.mark.skipif(4>2, reason=".....") # @pytest.mark.skip() class TestDemo: def test_fn1(self): print("测试函数1") def test_fn2(self): print("测试函数2") class TestDemo2: def test_fn3(self): print("测试函数3") """ 1 跳过操作可以作用于函数 """
Pytest 参数化【 重要 】
1. 作用: 当我们使用脚本去代替手工测试的时候会遇到以下的情况, 有一个被测试功能点,我们为它设计了多条测试用例,而且每条测试用例的执行步骤是一样的,只不过输入的测试数据不一样,此时我们就可以通过参数化来简化我们代码。
2. 语法:
@pytest.mark.parametrize( 属性名, 属性值对象 )
3. 细节:
(1) 我们在 parametrize 函数中定义属性名,必须要把它传入到具体的函数内才可以使用。
(2) 依据parametrize() 函数的传参特点,当我们有多个属性值需要参数化的时候可以直接用一个变量名来接收,此时这个变量会拿到所有属性对应的值,至于说拿到的是什么类型,由使用者传入的类型决定。
单属性参数化:
# -*- coding=utf-8 -*- import pytest class TestDemo: # 单个属性的参数化语法 @pytest.mark.parametrize("name", ["张三", "李四"]) def test_fn(self, name): print(name) print( "fn表示一个被测功能点,它有多条用例,不一样只是每条用例的数据" )
多属性参数化:
# -*- coding=utf-8 -*- import pytest class TestDemo: # 单个属性的参数化语法 @pytest.mark.skip() @pytest.mark.parametrize(("username", "password"), [("张三","123456"), ("李四", 'abcd')]) def test_fn(self, username, password): print("用户名是%s,密码是%s"%(username, password)) print( "此时这个被测功能点需要输入多个测试数据" ) @pytest.mark.parametrize("obj", [["1", 2]]) def test_param(self, obj): print(obj, type(obj)) print("通过本函数来验证变量名列表是否可以简写")
Pytest fixture 函数
1. 作用: 功能和 setup 类似,主要是用于给开发者来提取当前模块中的通用或者可以共用的代码模块。( 功能要比setup 强大 )
2. 定义语法:
@pytest.fixture() 将这句话写在某一个普通函数的正上方,且这个普通函数是写在类的外部
3. 调用语法:
(1) 直接将 fixture 函数名当做变量传入到一个函数内
(2) 使用 @pytest.mark.usefixtures( “函数名” ) ,这种调用方法一般作用于类。
4. Fixture 函数作用域
我们可以在定义 fixture 函数的时候,直接在 fixture() 内通过参数 scope 与 autouse 来配置完成作用的定义
@pytest.fixture( autouse=False, scope=”function” ) 此语法中给出的是默认值
1. Scope 可以设置为 function class moduel session 四个值
2. 设置function 的时候表示每个 test_ 打头的函数都会调用该fixture
3. 设置 class 的时候会调用 N 次,N等于当前模块中类的个数
4. 设置 module 的时候会调用 1 次
5. 设置为 session 的时候也调用一次,且先于其它的作用域执行。
test_demo1.py
# -*- coding=utf-8 -*- import pytest # 在类的外部去定义 fixture 函数 # 通过第7行代码就完成了 fixture 函数的定义 @pytest.fixture() def get_data(): # print("当前被测试功能都希望使用的数据,我们将这个操作提取出来放在一个外部的函数中") print("get_data执行了") @pytest.mark.usefixtures("get_data") class TestDemo: def test_fn(self): print("我是测试函数1") def test_fn2(self): print("我是测试函数2")
test_demo2.py
# -*- coding=utf-8 -*- import pytest @pytest.fixture(scope="module", autouse=True) def get_data2(): print("这是第二个 get_data") # 通过第7行代码就完成了 fixture 函数的定义 @pytest.fixture(scope="session", autouse=True) def get_data(): print("get_data执行了") class TestDemo: def test_fn(self): print("我是测试函数1") def test_fn2(self): print("我是测试函数2") class TestDemo2: def test_fn3(self): print("我是测试函数3") """ 1 fixture 可以对函数起作用 2 fixture 可以对类起作用 3 fixture 可以对当前模块起作用 4 可以对 session 起作用 """