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

pytest的使用

pytest

对比一下支持python语言得到自动化框架

维度unittest(Python 内置)pytestRobot Framework
安装方式无需安装(Python 标准库)pip install pytestpip install robotframework
语法风格基于类(需继承TestCase函数式或面向对象(无需样板代码)关键字驱动(表格化用例)
断言方法self.assertEqual()原生 assert 表达式关键字断言(如 Should Be Equal
参数化支持subTest 或第三方库内置 @pytest.mark.parametrize数据驱动(Test Template
插件生态少(依赖扩展库如HTMLTestRunner丰富(如 pytest-htmlpytest-xdistallure-pytest一般(需安装额外库如RequestsLibrary
测试报告需插件生成报告支持多格式报告(HTML、Allure 等)自带详细日志和报告
学习曲线中等(需熟悉 xUnit 模式)低(语法简洁)高(需掌握关键字和语法)
BDD 支持不支持支持(通过 pytest-bdd 插件)支持(通过 robotframework-bdd
适用场景简单项目或遗留系统维护复杂项目、高扩展性需求团队协作、非技术人员参与

pytest的介绍

pytest是一个流行且高效的python测试框架,它提供了丰富的功能和灵活的用法,使得编写和运行测试用例变得简单和高效。

  • 简单易用: pytest 的语法简洁清晰,对于编写测试用例非常友好
  • 强大的断言库: pytest 内置了丰富的断言库,可以轻松地进行测试结果的判断。
  • 支持参数化测试: pytest 支持参数化测试,允许使用不同的参数多次运行同一个测试函数,这大大提高了测试效率。
  • 丰富的插件生态系统: pytest 有着丰富的插件生态系统,可以通过插件扩展各种功能,比如覆盖率测试、测试报告生成(如pytest-html 插件可以生成完美的HTML测试报告)、失败用例重复执行(如pytest-rerunfailures 插件)等。此外, pytest 还支持与selenium、requests、appinum等结合,实现Web自动化、接口自动化、App自动化测试。
  • 灵活的测试控制: pytest 允许跳过指定用例,或对某些预期失败的case标记成失败,并支持重复执行失败的case。

安装

pip install pytest==8.3.2

在这里插入图片描述
执行的三角按钮就是pytest安装成功的标志之一。
更准确的可以通过pip list来查看是否存在pytest

用例运行规则

  1. 文件名必须是test_开头或者_test结尾
  2. 测试类必须以Test开头,并且不能有个__init__方法
  3. 测试方法必须以test开头

pytest命令参数

pytest提供了丰富的命令行选项来控制测试的执行。

命令描述备注
pytest在当前目录及其子目录中搜索并运行测试。
pytest -v增加输出的详细程度。
pytest -s显示测试中的 print 语句。
pytest test_module.py运行指定的测试模块。
pytest test_dir/运行指定目录下的所有测试。
pytest -k <keyword>只运行测试名包含指定关键字的测试。
pytest -m <marker>只运行标记为指定标记的测试。
pytest -q减少输出的详细程度。
pytest --html=report.html生成 HTML 格式的测试报告。需要安装 pytest-html 插件
pytest --cov测量测试覆盖率需要安装 pytest-cov 插件

运行符合运行规则的用例

pytest

详细打印,并输入print内容

pytest -sv

指定文件/测试用例

# 指定文件:pytest 包名/文件名
pytest cases/test_01.py
# 指定测试用:pytest 包名/文件名::类名::方法名
pytest cases/test_01.py::Test::test_a

pytest配置文件

在当前项目下创建pytest.ini文件,该文件是pytest的配置文件,以下是常见的配置选项

参数解释
addopts指定在命令行中默认包含的选项。
testpaths指定搜索测试的目录。
python_files指定发现测试模块时使用的文件匹配模式。
python_classes指定发现测试类时使用的类名前缀或模式。
python_functions指定发现测试函数和方法时使用的函数名前缀或模式。
norecursedirs指定在搜索测试时应该避免递归进入的目录模式。
markers定义测试标记,用于标记测试用例。

详细输出cases包下文件名为test_凯欧且方法名为Test开头的所有用例

[pytest]
addopts = -sv
testpaths = ./cases
python_files = my*.py
python_classes = Test*

在这里插入图片描述
可以发现,不区分大小写

前后置

前面提到,在pytest中,不能使用__init__,那么该如何实现数据的初始化呢?
pytest 框架提供三种⽅法做前后置的操作

  • setup_method 和 teardown_method :这两个⽅法⽤于类中的每个测试⽅法的前置和后置操作。
  • setup_class 和 teardown_class :这两个⽅法⽤于整个测试类的前置和后置操作。
  • • fixture :这是 pytest 推荐的⽅式来实现测试⽤例的前置和后置操作。
  1. setup_methodteardown_method
import  pytestclass TestExample:def setup_method(self):print("setup_method")def teardown_method(self):print("teardown_method")def test_example1(self):print("test_example1")def test_example2(self):print("test_example2")

在这里插入图片描述
2. setup_class 和 teardown_class

import  pytestclass TestExample:def setup_class(self):print("setup_class: Before all test")def teardown_class(self):print("teardown_class: After all test")def test_example1(self):print("test_example1")def test_example2(self):print("test_example2")

在这里插入图片描述

断言

断⾔( assert )是⼀种调试辅助⼯具,⽤于检查程序的状态是否符合预期。如果断⾔失败(即条件为假),Python解释器将抛出⼀个 AssertionError 异常。断⾔通常⽤于检测程序中的逻辑错误。

pytest 允许你在 Python 测试中使⽤标准的 Python assert 语句来验证预期和值。

assert 条件, 错误信息
  • 条件:必须是一个布尔表达式
  • 错误信息:当条件为假的时候,显示的错误信息
def divide(a,b):assert b==0,'除数不能为0'return a/b
def test():# 基本数据类型的断言a = 1b = 2assert a==b,"a和b不相等"# 断言字符串str = 'hello'assert str == 'hello'# 断⾔列表expect_list = [1, 'apple', 3.14]actual_list = [1, 'apple', 3.14]# 断⾔元组expect_tuple = (1, 'apple', 3.14)actual_tuple = (1, 'apple', 3.14)# 断⾔字典expect_dict = {'name': 'Alice', 'age': 25}actual_dict = {'name': 'Alice', 'age': 25}# 断⾔集合expect_set = {1, 2, 3, 'apple'}actual_set = {1, 2, 3, 'apple'}assert expect_list == actual_listassert expect_tuple == actual_tupleassert expect_dict == actual_dictassert expect_set == actual_set# 函数断言print(divide(10, 0))

在这里插入图片描述

参数化

参数化设计是自动化设计中的一个重要组成部分,他通过定义设计参数和规则,使得设计过程更加灵活和可控
pytest中内置的 pytest.mark.parametrize 装饰器允许对测试函数的参数进⾏参数化。

  1. 在用例上使用参数化
import pytest@pytest.mark.parametrize("test_input,expected", [("3+5",8),("2+4",6)])
def test_eval(test_input,expected):assert eval(test_input)==expected

在这里插入图片描述
2. 在类上使用参数化

import pytest@pytest.mark.parametrize("n,expected", [(1, 2), (3, 4)])
class TestClass:def test_simple_class(self,n,expected):assert n + 1==expecteddef test_weird_simple_case(self,n,expected):assert (n*1)+1==expected

在这里插入图片描述
要对模块中的所有测试进⾏参数化,你可以将 pytestmark 全局变量赋值:

import pytestpytestmark = pytest.mark.parametrize("n,expected", [(1, 2), (3, 4)])class TestClass:def test_simple_class(self,n,expected):assert n + 1==expecteddef test_weird_simple_case(self,n,expected):assert (n*1)+1==expected
class TestClass02:def test_simple_case(self, n, expected):assert n + 1 == expecteddef test_weird_simple_case(self, n, expected):assert (n * 1) + 1 == expected

在这里插入图片描述
3. 自定义参数化数据源

import pytestdef data_provider():return ["a", "b"]
# 定义⼀个测试函数,它依赖于上⾯函数的返回值
@pytest.mark.parametrize("data", data_provider())
def test_data(data):assert data != Noneprint(f"Testing with data provider: {data}")

在这里插入图片描述

fixture

pytest 中的 fixture 是⼀种强⼤的机制,⽤于提供测试函数所需的资源或上下⽂。它可以⽤于设置测试环境、准备数据等。以下是 fixture 的⼀些核⼼概念和使⽤场景.

在这里插入图片描述
访问列表页和详情页之间都需要执行登录操作

import pytest@pytest.fixture
def login():print("执行登录操作")
def test_list(login):print("访问列表页")
def test_detail(login):print("访问详情页")

在这里插入图片描述
通过使⽤ @pytest.fixture 装饰器来告诉 pytest ⼀个特定函数是⼀个 fixture,通过运⾏结果可⻅,在执⾏列表⻚和详情⻚之前都会先执⾏ login ⽅法

fixture嵌套
import pytest@pytest.fixture
def first_entry():return 'a'@pytest.fixture
def order(first_entry):return [first_entry]def test_string(order):order.append('b')assert order == ['a', 'b']

在这里插入图片描述

请求多个fixture
import pytestclass Fruit:def __init__(self, name):self.name = namedef __eq__(self, other):return self.name == other.name@pytest.fixture
def my_fruit():return Fruit('apple')
@pytest.fixture
def fruit_basket(my_fruit):return [Fruit("banana"),my_fruit]
def test_fruit_basket(my_fruit,fruit_basket):assert my_fruit in fruit_basket

在这里插入图片描述

yield fixture

当运行测试的时候,希望确保它们能够自我清理,以便它们不会干扰其他测试。
“Yield” fixture 使⽤ yield ⽽不是 return 。有了这些 fixture ,我们可以运⾏⼀些代码,并将对象返回给请求的 fixture/test ,就像其他 fixture ⼀样。

import pytest@pytest.fixture
def open_close():print("open")yieldprint("close")
def test_01(open_close):print("test_01")

在这里插入图片描述
创建文件句柄和关闭文件

import pytest@pytest.fixture
def file_read():print("打开文件句柄")fo = open('test.txt','r',encoding='utf-8')yield foprint("关闭打开文件")fo.close()
@pytest.fixture
def file_write():print('打开文件句柄')fo = open('test.txt','w',encoding='utf-8')yield foprint("关闭文件句柄")fo.close()
def test_file(file_write,file_read):# 写入数据w = file_writew.write("测试数据")r = file_readstr = r.read()print("文件内容,", str)

在这里插入图片描述

带参数的fixture
pytest.fixture(scope='', params='', autouse='', ids='', name='')

参数详解:

  • 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. score的使用
    score=function
import pytest@pytest.fixture(scope="function")
def fixture_01():print("初始化")yieldprint("销毁")class TestCase:def test_01(self,fixture_01):print("test_01")def test_02(self,fixture_01):print("test_02")

在这里插入图片描述

score=class

import pytest@pytest.fixture(scope="class")
def fixture_01():print("初始化")yieldprint("销毁")class TestCase:def test_01(self,fixture_01):print("test_01")def test_02(self,fixture_01):print("test_02")

在这里插入图片描述
根据比对可以发现,如果scope=class的时候,只会在类创建和销毁的时候分别调用fixture_01;而scope=function,会在每次调用函数的时候都去调用fixture_01函数
2. : scope=“moudle” 、 scope=“session” 实现全局的前后置应⽤

# myA.py
def test_01(fixture_01):print("test_01")def test_02(fixture_01):print("test_02")
# myB.py
def test_01(fixture_01):print("test_01")def test_02(fixture_01):print("test_02")
# conftest.py
import pytest@pytest.fixture(scope='module')
# @pytest.fixture(scope='session')
def fixture_01():print("初始化")yieldprint("销毁")

在这里插入图片描述
在这里插入图片描述

scope=function表示一个函数都需要执行一次,class表示一个类需要执行一次,module表示一个模块需要执行一次(一个文件),session表示一次测试需要执行一次。
3. autouse 的使⽤
autouse默认为False,如果设置为True,则表示每个fixure范围内的函数默认去调用

import pytest@pytest.fixture(scope="class", autouse=True)
def fixture_01():print("初始化")yieldprint("清理")
class TestCase():def test_01(self):print("第⼀个测试⽤例")def test_02(self):print("第⼆个测试⽤例")

在这里插入图片描述

  1. 通过 params 实现参数化
import pytest@pytest.fixture(params=['a','b'])
def data_provider(request):return request.param# 定义一个测试函数,依赖上面的参数化fixture
def test_data(data_provider):assert data_provider != Noneprint(f"{data_provider}")

在这里插入图片描述
前⾯我们已经学过pytest中通过 @pytest.mark.parametrize 实现参数化,通过 fixture 也可以实现参数化
parametrize 更适合简单场景,⽽ fixture 更适合需要动态数据和资源管理的复杂场景

指定用例顺序

在使⽤pytest进⾏测试时,有时候我们需要按照特定的顺序来运⾏测试⽤例,尤其是在涉及到测试⽤例
之间的依赖关系时。pytest本⾝并不直接⽀持通过配置来改变测试⽤例的默认运⾏顺序,pytest-order是一个第三方插件,需要手动下载一下

pip install pytest-order==1.3.0

在这里插入图片描述
在这里插入图片描述

http://www.dtcms.com/a/574168.html

相关文章:

  • 神经网络—— 学习与感知器
  • 聊城网站建设价格能做门户网站带论坛功能的cms
  • 有没有专门发布毕业设计代做网站衡阳市本地新闻头条
  • 网站跟app的区别是什么电商网站对比 京东商城 淘宝网 阿里巴巴
  • 天空星GD32F4系列开发板移植FreeRTOS超详细教程(基于Keil环境)
  • 告别漫长GC停顿:深入解析G1如何实现可预测的毫秒级响应
  • 开发小型门户网站的方法 步骤十大不收费看盘网站
  • 教怎么做ppt的网站网站域名icp备案
  • 如何用AI创建一个适合你的编程社区用户名
  • 计算机网络自顶向下方法33——网络层 路由器工作原理 输入端口处理和基于目的地转发 交换 输出端口处理
  • [RE2] Regexp对象 | shared_ptr | AST树
  • Redis Desktop Manager(Redis可视化工具)安装
  • 家务机器人
  • yolo 获取异常样本 yolo 异常
  • 解析几何——求点A到点B和C组成直线的垂线的距离,以及点到线段的距离
  • 网校 039 网站建设多少钱济南做微网站推广
  • 一台云服务器可以做多少个网站国外网站在国内备案
  • 应用案例实践 | 基于“隐语SecretFlow”多方安全分析的智能化理赔
  • 北京做erp报价的网站做网站用vue吗
  • 大话大模型应用(二)--让大模型听话:Prompt EngineeringContext Engineering
  • 中国古建筑网站高清视频网络服务器免费
  • 自适应网站做多大尺寸的开网站做淘宝客
  • 朝阳网站推广企业网站模板价格
  • ControlNet:Adding Conditional Control to Text-to-Image Diffusion Models
  • 网站维护的方法asp.net 4.0网站开发实例教程
  • web前端 DSL转换技术
  • 有什么好的网站推荐一下成都网页制作要多少钱
  • 厦门建设厅网站站长工具seo综合查询官网
  • 灯塔工厂:如何通过数字化实现制造升级
  • 电商网站 内容优化哪一个网站有做实验的过程