当前位置: 首页 > news >正文

自动化框架pytest

1.简介

pytest是一个基于Python的测试框架,广泛用于编写简单且可扩展的测试代码。它支持单元测试、功能测试和集成测试,适用于从简单脚本到复杂应用程序的测试场景。

2.安装

pip install pytest==8.3.2
pytest 版本最低 Python 版本
8.0+3.8+
7.1+3.7+
6.2 - 7.03.6+
5.0 - 6.13.5+
3.3 - 4.62.7, 3.4+

注意自己的python版本是否支持要下载的pytest版本

3.用例运行规则

安装完pytest后,在已test开头的方法前面会出现这个运行的图标

规则:

1. ⽂件名必须以 test_ 开头或者 _test 结尾

2. 测试类必须以 Test 开头,并且不能有 __init__ ⽅法。

3. 测试⽅法必须以 test 开头

满足上述规则的用例,我们在终端输入pytest就会自动执行这些用例

注意:测试的Python类中不可以添加init⽅法

pytest 在实例化测试类时,默认会调用无参数的构造函数。如果测试类中定义了 __init__ 方法,可能会导致 pytest 无法正确初始化测试类,从而引发错误。

测试类的主要目的是定义测试方法,而不是管理复杂的初始化逻辑。pytest 提供了其他机制(如 fixture)来处理初始化需求。

4.前后置

使用 setup_method 或 setup_class 方法来替代 __init__ 方法。这些方法是 pytest 推荐的初始化方式,会在测试运行前自动调用。

pytest 框架提供三种⽅法做前后置的操作:

setup_method 和 teardown_method :这两个⽅法⽤于类中的每个测试⽅法的前置和后置操

作。

setup_class 和 teardown_class :这两个⽅法⽤于整个测试类的前置和后置操作。

fixture :这是 pytest 推荐的⽅式来实现测试⽤例的前置和后置操作。 fixture 提供了更

灵活的控制和更强⼤的功能。(fixture将在后面单独讲解)

setup_method 和 teardown_method 会在每个方法执行前后都执行一遍

setup_class 和 teardown_class 会在本类的所有测试方法执行前执行一次,执行后执行一次,但是不能跨测试类执行(fixture能够解决这个问题)

5.pytest命令参数

基础运行参数

  • -v 或 --verbose: 显示详细测试结果,包括每个测试用例的名称和状态。
  • -q 或 --quiet: 简化输出,仅显示总体结果。
  • -k <表达式>: 通过关键字表达式筛选测试用例。例如 pytest -k "test_login" 仅运行名称包含 test_login 的测试。
  • -m <标记>: 运行带有特定标记的测试用例。例如 pytest -m smoke 仅运行标记为 smoke 的测试。

测试范围控制

  • :: 指定特定测试类或方法。例如 pytest tests/test_module.py::TestClass::test_method 仅运行指定方法。
  • --collect-only: 仅列出可用的测试用例但不执行。
  • --lf 或 --last-failed: 仅重新运行上次失败的测试。
  • --ff 或 --failed-first: 先运行上次失败的测试,再运行其他测试。

输出与报告

  • --tb=<style>: 设置错误回溯格式。可选值:auto(默认)、longshortnolinenative
  • -r <chars>: 显示额外摘要信息。例如 -rA 显示所有结果,-rE 显示错误。
  • --junitxml=<path>: 生成 JUnit 格式的 XML 报告。
  • --html=<path>: 生成 HTML 报告(需安装 pytest-html 插件)。

调试与诊断

  • -s: 禁用捕获,直接输出打印内容(相当于 --capture=no)。
  • --pdb: 在测试失败时自动进入调试模式。
  • --setup-show: 显示测试的 fixture 执行过程。
  • --durations=<N>: 显示最慢的 N 个测试用例的执行时间。

其他实用参数

  • -x: 遇到第一个失败时立即停止测试。
  • --maxfail=<num>: 允许的最大失败次数,达到后停止测试。
  • --cov=<path>: 生成代码覆盖率报告(需安装 pytest-cov 插件)。
  • -n <num>: 使用多进程并行运行测试(需安装 pytest-xdist 插件)。

6.pytest配置文件

在当前项⽬下创建 pytest.ini ⽂件,pytest.ini作用于同级目录及其子目录,该⽂件为 pytest 的配置⽂件,以下为常⻅的配置选项:

参数解释
addopts指定在命令⾏中默认包含的选项。
testpaths指定搜索测试的⽬录。
python_files指定发现测试模块时使⽤的⽂件匹配模式。
python_classes指定发现测试类时使⽤的类名前缀或模式。
python_functions指定发现测试函数和⽅法时使⽤的函数名前缀或模式。
norecursedirs指定在搜索测试时应该避免递归进⼊的⽬录模式。
markers定义测试标记,⽤于标记测试⽤例。
[pytest]
addopts = -vs
testpaths = ./cases
python_files = test_*.py
python_classes = Test*

7.断言

断⾔( assert )是⼀种调试辅助⼯具,⽤于检查程序的状态是否符合预期。如果断⾔失败(即条件为假),Python解释器将抛出⼀个 AssertionError 异常。断⾔通常⽤于检测程序中的逻辑错误。pytest 允许你在 Python 测试中使⽤标准的 Python assert语句来验证预期和值。

语法:

assert 条件,错误信息• 条件 :必须是⼀个布尔表达式。
• 错误信息 :当条件为假时显⽰的错误信息,可选。

8.参数化

参数化设计是⾃动化设计中的⼀个重要组成部分,它通过定义设计参数和规则,使得设计过程更加灵活和可控。

pytest中内置的 pytest.mark.parametrize 装饰器允许对测试函数的参数进⾏参数化。

在用例上使用参数化

在类上使用参数化:

@pytest.mark.parametrize("test_input,expected",[("3+2",5),("22*2",44),("3-2",1),("5/2",2.5)])
class Test_01:def test_01(self,test_input,expected):assert eval(test_input) == expecteddef test_02(self,test_input,expected):assert eval(test_input) == expecteddef test_03(self,test_input,expected):assert eval(test_input) == expected

对模块中所有测试进行参数化

import pytestpytestmark = pytest.mark.parametrize("test_input,expected",[("3+2",5),("22*2",44),("3-2",1),("5/2",2.5)])
class Test_01:def test_01(self,test_input,expected):assert eval(test_input) == expecteddef test_02(self,test_input,expected):assert eval(test_input) == expecteddef test_03(self,test_input,expected):assert eval(test_input) == expectedclass Test_02:def test_04(self,test_input,expected):assert eval(test_input) == expecteddef test_05(self,test_input,expected):assert eval(test_input) == expecteddef test_06(self,test_input,expected):assert eval(test_input) == expected

9.fixture

概念:

Fixture 是测试框架中的一个重要概念,用于在测试运行前准备所需的数据或环境,并在测试完成后进行清理。Fixture 可以确保测试在一致和可控的条件下运行,提高测试的可靠性和可维护性。

主要作用:

Fixture 通常用于以下几种场景:

  • 数据库初始化:例如创建测试表、插入测试数据。
  • 文件系统准备:例如创建临时文件或目录。
  • 网络请求模拟:例如模拟 API 返回数据。
  • 资源管理:例如打开和关闭数据库连接。

fixture基本使用一:

def fixture_01():print("fixture_01")
def test_fixture_01():fixture_01()print("test_fixture_01")@pytest.fixture
def fixture_02():print("fixture_02")
def test_fixture_02(fixture_02):print("test_fixture_02")

未标记 fixture ⽅法的调⽤与 fixture 标记的⽅法调⽤完全不⼀样,前者需要在⽅法体中调⽤,

⽽后者可以将函数名作为参数进⾏调⽤。

测试脚本中存在的很多重复的代码、公共的数据对象时,使⽤ fixture 最为合适

fixture基本使用二:

访问列表⻚和详情⻚之前都需要执⾏登录操作,相当于前置

import pytest
@pytest.fixture
def login():print("---执⾏登陆操作-----")
def test_list(login):print("---访问列表⻚")
def test_detail(login):print("---访问详情⻚")

fixture嵌套:

import pytest
@pytest.fixture
def first_entry():return "first"@pytest.fixture
def second_entry(first_entry):return [first_entry]def test_01(second_entry):second_entry.append("second_entry")print(second_entry)

测试不必局限于单个 fixture ,它们可以依赖于您想要的任意数量的 fixture ,并且fixture 也可以使⽤其他 fixture 。 pytest 最伟⼤的优势之⼀是其极其灵活的 fixture 系统,它允许我们将测试的复杂需求简化为更简单和有组织的函数,我们只需要每个函数描述它们所依赖的事物

请求多个fixture

  • fixture 的执行顺序由 pytest 自动管理,通常按依赖关系和定义顺序执行。

yield fixture:

在 pytest 中,yield fixture 是一种通过生成器(yield)机制管理资源的 fixture。它允许在测试执行前进行初始化操作,并在测试完成后自动执行清理操作,适合处理需要释放的资源(如数据库连接、文件句柄等)。

yield相当于return ,但又不太一样,在测试用例执行完毕后,会回来执行yield下面的代码

创建⽂件句柄与关闭⽂件:

import pytest
@pytest.fixture
def file_read():print("打开⽂件句柄")fo = open("test.txt", "r")yield foprint("关闭打开的⽂件")fo.close()def file_write():print("打开⽂件句柄")fo = open("test.txt","w",encoding="utf-8")return fodef test_file(file_write, file_read):
# 写⼊数据w = file_writew.write("测试数据")w.close() # 写⼊后关闭⽂件句柄,以便读取
# 读取数据r = file_readstr = r.read(10)print("⽂件内容:", str)

带参数的fixture:

参数详解:

• scope 参数⽤于控制fixture的作⽤范围,决定了fixture的⽣命周期。可选值有:
◦ function (默认):每个测试函数都会调⽤⼀次fixture。
◦ class :在同⼀个测试类中共享这个fixture。
◦ module :在同⼀个测试模块中共享这个fixture。(⼀个⽂件⾥)
◦ session :整个测试会话中共享这个fixture。

• autouse 参数默认为 False 。如果设置为 True ,则每个测试函数都会⾃动调⽤该fixture,
⽆需显式传⼊

• params 参数⽤于参数化fixture,⽀持列表传⼊。每个参数值都会使fixture执⾏⼀次,类似于for循环

• ids 参数与 params 配合使⽤,为每个参数化实例指定可读的标识符(给参数取名字)

• name 参数⽤于为fixture显式设置⼀个名称。如果使⽤了 name ,则在测试函数中需要使⽤这个名称来引⽤ fixture (给fixture取名字)

1.scope

scope="function"

每个测试用例运行前都会调用

fixture默认是funtions,每个方法

scope="class"

在同⼀个测试类中共享这个fixture。

scope="session"
  • 作用域:fixture 在整个模块(即一个 .py 文件)中只执行一次。
  • 用途:适合在模块级别进行初始化和清理操作,例如打开数据库连接、设置全局配置等。
#conftest.pyimport pytest
@pytest.fixture(scope="module")
def module_fixture():print("\n模块级别的前置操作")yieldprint("\n模块级别的后置操作")
#作用于整个test_module.pydef test_module1(module_fixture):print("test_module1")def test_module2(module_fixture):print("test_module2")

scope="session"

  • 作用域:fixture 在整个测试会话(即所有测试文件)中只执行一次。
  • 用途:适合在会话级别进行初始化和清理操作,例如启动浏览器、连接数据库等。
  • #conftest.pyimport pytest
    @pytest.fixture(scope="session")
    def module_fixture():print("\n模块级别的前置操作")yieldprint("\n模块级别的后置操作")
    #test_module1.pydef test_module1(module_fixture):print("test_module11")def test_module2(module_fixture):print("test_module12")
    #test_module2.pydef test_module1(module_fixture):print("test_module21")def test_module2(module_fixture):print("test_module22")

2.autose

autouse 默认为 False ,即当前的 fixture 需要⼿动显⽰调⽤,在该案例之前我们默认使⽤的

都是 autouse=False

当 autouse=True 时, fixture 会在所有测试函数执⾏之前⾃动调⽤,⽆论这些测试函数是否显式地引⽤了该 fixture

 

3.params

  • 作用:用于参数化 fixture,支持传入一个列表。每个参数值都会使 fixture 执行一次,类似于 for 循环。
  • 用途:适合在不同参数下重复执行同一个 fixture。
import pytest# 定义⼀个参数化的 fixture
@pytest.fixture(params=["a", "b"])
def data_provider(request):return request.param
# 定义⼀个测试函数,它依赖于上⾯的参数化 fixture
def test_data(data_provider):assert data_provider != Noneprint(f"Testing with data provider: {data_provider}")

4.ids

  • 作用:与 params 配合使用,为每个参数化实例指定可读的标识符(给参数取名字)。
  • 用途:提高测试结果的可读性,特别是在参数较多时。就是告诉我们用的是那个参数,给参数取的名字

5.name

  • 作用:用于为 fixture 显式设置一个名称。如果使用了 name,则在测试函数中需要使用这个名称来引用 fixture。
  • 用途:避免 fixture 名称与测试函数中的变量名冲突,或者为 fixture 取一个更具描述性的名称。
  • name相当于改名卡,使用后原来的名字就不能用了
http://www.lryc.cn/news/607432.html

相关文章:

  • linux编译基础知识-编译时路径和运行时路径
  • ModeSeq论文阅读
  • Redis 数据结构全景解析
  • 如何管理数据足迹,实现SAP S/4HANA的无缝迁移
  • 记一次Windwos非常离谱的系统错误,IPF错误,程序构建卡顿,程序启动卡顿。。。
  • 从“多、老、旧”到“4i焕新”:品牌官方商城(小程序/官网/APP···)的范式跃迁与增长再想象
  • 振动波形转音频播放并做声纹聚类
  • Eigent:革新复杂任务处理的多智能体协作平台技术解析
  • MybatisPlus如何用wrapper语句灵活连接多查询条件
  • [位运算]2411. 按位或最大的最小子数组长度
  • 安卓开发--RelativeLayout(相对布局)
  • AI在安全方面的十个应用场景
  • 技术栈:基于Java语言的搭子_搭子社交_圈子_圈子社交_搭子小程序_搭子APP平台
  • 电子合同管理台账功能详解
  • 移除 Excel 文件(.xlsx)的工作表保护
  • EasyExcel 公式计算大全
  • python进程、线程、协程
  • 【LeetCode 热题 100】155. 最小栈
  • 【东枫科技】DreamHAT+
  • 【人工智能-17】机器学习:KNN算法、模型选择和调优、朴素贝叶斯分类
  • kafka快速部署、集成、调优
  • 力扣 hot100 Day62
  • 机器学习sklearn:编码、哑变量、二值化和分段
  • TCP协议的特点和首部格式
  • 同品牌的系列广告要如何保证宣传的连贯性?
  • 广东省省考备考(第六十三天8.1)——判断推理(强化训练)
  • 国产开源大模型崛起:使用Kimi K2/Qwen2/GLM-4.5搭建编程助手
  • Galaxea机器人由星海图人工智能科技有限公司研发的高性能仿人形机器人
  • 大模型结构比较
  • uniapp 开发微信小程序,获取经纬度(uni.getLocation)并且转化详细地址(‌高德地图逆地理编码API、‌腾讯地图逆地理编码)