Pytest--安装与入门

news2024/11/26 8:28:46

pytest是一个能够简化成测试系统构建、方便测试规模扩展的框架,它让测试变得更具表现力和可读性–模版代码不再是必需的。只需要几分钟的时间,就可以对你的应用开始一个简单的单元测试或者复杂的功能测试。

1. 安装pytest

pip install -U pytest

检查版本

> pytest --version
pytest 8.2.2

2. 创建第一个测试

注:

  • 文件名必须以 test 开头
  • 测试类必须以 Test 开头,且不能含有 init 方法
  • 测试方法必须以 test 开头
# test_sample.py
def func(x):
    return x + 1

def test_answer():
    assert func(3) == 5

然后在该python文件的目录下执行pytest

================================================= test session starts =================================================
platform win32 -- Python 3.9.9, pytest-7.0.1, pluggy-1.0.0
rootdir: D:\Code\Pytest
collected 1 item

test_sample.py F                                                                                                 [100%]

====================================================== FAILURES =======================================================
_____________________________________________________ test_answer _____________________________________________________

    def test_answer():
>       assert func(3) == 5
E       assert 4 == 5
E        +  where 4 = func(3)

test_sample.py:5: AssertionError
=============================================== short test summary info ===============================================
FAILED test_sample.py::test_answer - assert 4 == 5
================================================== 1 failed in 0.12s ==================================================
PS D:\Code\Pytest>

[100%]指的是运行所有测试用例的总体进度。完成后,pytest会显示一个报告,如上述测试,是一个失败报告,因为func(3)不返回5。

3. 运行多个测试

pytest _*.py或者pytest *_可以使 pytest 运行目录下的多个符合条件的文件。

3. pytest测试用例的运行方式

主函数模式

1. 运行所有:pytest.main()
import pytest

def fun_plus(x):
    return x+2

def test_answer():
    assert fun_plus(2) == 5

def test_addition():
    assert 1+1 == 2


if __name__ == '__main__':
    pytest.main()

执行结果

测试用例执行通过是没有的展示的,但执行失败会有具体的信息,甚至指出出错地方:

F:\SoftWare\Python\Python39\python39.exe F:/SoftWare/JetBrains/PyCharm2023.1.2/plugins/python/helpers/pycharm/_jb_pytest_runner.py --path F:\Code\PyCharmProject\Interview\pytest\test_demo01.py 
Testing started at 10:09 ...
Launching pytest with arguments F:\Code\PyCharmProject\Interview\pytest\test_demo01.py --no-header --no-summary -q in F:\Code\PyCharmProject\Interview\pytest

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

test_demo01.py::test_answer FAILED                                       [ 50%]
test_demo01.py:5 (test_answer)
4 != 5

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

def test_answer():
>       assert fun_plus(2) == 5
E       assert 4 == 5
E        +  where 4 = fun_plus(2)

test_demo01.py:7: AssertionError

test_demo01.py::test_addition PASSED                                     [100%]

========================= 1 failed, 1 passed in 0.03s =========================

Process finished with exit code 1
2. 指定模块/文件
# test_demo01.py
import pytest

def fun_plus(x):
    return x+2

def test_answer():
    assert fun_plus(2) == 5

def test_addition():
    assert 1+1 == 2


# if __name__ == '__main__':
#     pytest.main()
# test_demo02.py
import pytest

def fun_minus(x):
    return x-2

def test_answer():
    assert fun_minus(2) == 5

def test_minus():
    assert 4-2 == 2


# if __name__ == '__main__':
#     pytest.main()
# run_suite.py
import pytest

if __name__ == '__main__':
    pytest.main(['-vs', './test_demo01.py', './test_demo02.py'])

参数详解:

-s:表⽰输出调试信息,输出print信息
-v:显⽰更加详细的信息
-vs:两个参数可以同时使⽤

注:main函数中的参数要求是列表形式的,如果有多个模块/文件,则继续以逗号分隔

多线程或者分布式运行:

安装插件 pytest-xdist

pip install pytest-xdist
# run_suite.py
import pytest

if __name__ == '__main__':
    pytest.main(['-vs', './', '-n 2'])
# 以两个线程来运行当前目录下的所有测试用例

执行结果:

============================= test session starts =============================
platform win32 -- Python 3.9.9, pytest-8.2.2, pluggy-1.5.0 -- F:\SoftWare\Python\Python39\python39.exe
cachedir: .pytest_cache
rootdir: F:\Code\PyCharmProject\Interview\pytest
plugins: xdist-3.6.1
created: 2/2 workers
2 workers [4 items]

scheduling tests via LoadScheduling

test_demo02.py::test_answer 
test_demo01.py::test_answer 
[gw0] FAILED test_demo01.py::test_answer 
[gw1] FAILED test_demo02.py::test_answer 
test_demo02.py::test_minus 
[gw1] PASSED test_demo02.py::test_minus 
test_demo01.py::test_addition 
[gw0] PASSED test_demo01.py::test_addition 

================================== FAILURES ===================================
_________________________________ test_answer _________________________________
[gw0] win32 -- Python 3.9.9 F:\SoftWare\Python\Python39\python39.exe

    def test_answer():
>       assert fun_plus(2) == 5
E       assert 4 == 5
E        +  where 4 = fun_plus(2)

test_demo01.py:7: AssertionError
_________________________________ test_answer _________________________________
[gw1] win32 -- Python 3.9.9 F:\SoftWare\Python\Python39\python39.exe

    def test_answer():
>       assert fun_minus(2) == 5
E       assert 0 == 5
E        +  where 0 = fun_minus(2)

test_demo02.py:7: AssertionError
=========================== short test summary info ===========================
FAILED test_demo01.py::test_answer - assert 4 == 5
FAILED test_demo02.py::test_answer - assert 0 == 5
========================= 2 failed, 2 passed in 0.34s =========================

Process finished with exit code 0
reruns 失败用例重跑

安装插件 pytest-rerunfailures

pip install pytest-rerunfailures

–reruns=num:失败用例重跑,将这个模块多执行num次,最后返回结果

# run_suite.py
import pytest

if __name__ == '__main__':
    pytest.main(['-vs', '--reruns=2'])

执行结果:

============================= test session starts =============================
platform win32 -- Python 3.9.9, pytest-8.2.2, pluggy-1.5.0 -- F:\SoftWare\Python\Python39\python39.exe
cachedir: .pytest_cache
rootdir: F:\Code\PyCharmProject\Interview\pytest
plugins: rerunfailures-14.0, xdist-3.6.1
collecting ... collected 4 items

test_demo01.py::test_answer RERUN
test_demo01.py::test_answer RERUN
test_demo01.py::test_answer FAILED
test_demo01.py::test_addition PASSED
test_demo02.py::test_answer RERUN
test_demo02.py::test_answer RERUN
test_demo02.py::test_answer FAILED
test_demo02.py::test_minus PASSED

================================== FAILURES ===================================
_________________________________ test_answer _________________________________

    def test_answer():
>       assert fun_plus(2) == 5
E       assert 4 == 5
E        +  where 4 = fun_plus(2)

test_demo01.py:7: AssertionError
_________________________________ test_answer _________________________________

    def test_answer():
>       assert fun_minus(2) == 5
E       assert 0 == 5
E        +  where 0 = fun_minus(2)

test_demo02.py:7: AssertionError
=========================== short test summary info ===========================
FAILED test_demo01.py::test_answer - assert 4 == 5
FAILED test_demo02.py::test_answer - assert 0 == 5
==================== 2 failed, 2 passed, 4 rerun in 0.05s =====================

Process finished with exit code 0
用例失败,测试停止

-x:只要有一个用例失败,测试就会停止

# run_suite.py
import pytest

if __name__ == '__main__':
    pytest.main(['-vs', '-x'])

执行结果:

============================= test session starts =============================
platform win32 -- Python 3.9.9, pytest-8.2.2, pluggy-1.5.0 -- F:\SoftWare\Python\Python39\python39.exe
cachedir: .pytest_cache
rootdir: F:\Code\PyCharmProject\Interview\pytest
plugins: rerunfailures-14.0, xdist-3.6.1
collecting ... collected 4 items

test_demo01.py::test_answer FAILED

================================== FAILURES ===================================
_________________________________ test_answer _________________________________

    def test_answer():
>       assert fun_plus(2) == 5
E       assert 4 == 5
E        +  where 4 = fun_plus(2)

test_demo01.py:7: AssertionError
=========================== short test summary info ===========================
FAILED test_demo01.py::test_answer - assert 4 == 5
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!
============================== 1 failed in 0.04s ==============================

Process finished with exit code 0
最大失败测试用例

–maxfail=n:如果有n个用例失败,测试就会停止(前提:安装插件 pytest-xdist)

# run_suite.py
import pytest

if __name__ == '__main__':
    pytest.main(['-vs', '--maxfail=1'])

执行结果:

============================= test session starts =============================
platform win32 -- Python 3.9.9, pytest-8.2.2, pluggy-1.5.0 -- F:\SoftWare\Python\Python39\python39.exe
cachedir: .pytest_cache
rootdir: F:\Code\PyCharmProject\Interview\pytest
plugins: rerunfailures-14.0, xdist-3.6.1
collecting ... collected 4 items

test_demo01.py::test_answer FAILED

================================== FAILURES ===================================
_________________________________ test_answer _________________________________

    def test_answer():
>       assert fun_plus(2) == 5
E       assert 4 == 5
E        +  where 4 = fun_plus(2)

test_demo01.py:7: AssertionError
=========================== short test summary info ===========================
FAILED test_demo01.py::test_answer - assert 4 == 5
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!
============================== 1 failed in 0.04s ==============================

Process finished with exit code 0
通过读取 pytest.ini 配置文件运行
# pytest.ini

[pytest]
# 命令行参数,用空格分隔
addopts = -vs

# 测试用例文件夹
testpaths = testcase
# run_suite.py
import pytest

if __name__ == '__main__':
    pytest.main(['--maxfail=1'])

已经将测试用例转移到 testcase 文件夹下,看看执行结果:

============================= test session starts =============================
platform win32 -- Python 3.9.9, pytest-8.2.2, pluggy-1.5.0 -- F:\SoftWare\Python\Python39\python39.exe
cachedir: .pytest_cache
rootdir: F:\Code\PyCharmProject\Interview\pytest
configfile: pytest.ini
testpaths: testcase
plugins: rerunfailures-14.0, xdist-3.6.1
collecting ... collected 4 items

testcase/test_demo01.py::test_answer FAILED

================================== FAILURES ===================================
_________________________________ test_answer _________________________________

    def test_answer():
>       assert fun_plus(2) == 5
E       assert 4 == 5
E        +  where 4 = fun_plus(2)

testcase\test_demo01.py:7: AssertionError
=========================== short test summary info ===========================
FAILED testcase/test_demo01.py::test_answer - assert 4 == 5
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!
============================== 1 failed in 0.04s ==============================

Process finished with exit code 0

更多的配置还有:


# 配置测试搜索的模块文件名称
python_files = test_*.py

# 配置测试搜索的测试类名
python_classes = Test*

# 配置测试搜索的函数名
python_functions = test*

4. pytest执行测试用例顺序

unittest默认的执行顺序:

按照ASCII大小执行的,即在写测试用例时将测试名按大小顺序或加上数字顺序大小即可使其按顺序执行。

pytest默认的执行顺序:

按照用例的先后顺序执行,即哪个用例写在前面就先执行哪个用例

当然我们也可以通过插件的方式自定义其执行顺序

安装 pytest-ordering 插件

pip install pytest-ordering

使用方法

@pytest.mark.run(order=1)

import pytest

def fun_plus(x):
    return x+2

def test_01_answer():
    assert fun_plus(2) == 5

@pytest.mark.run(order=1)
def test_02_addition():
    assert 1+1 == 2


if __name__ == '__main__':
    pytest.main()

5. 以安静报告模式执行测试用例

pytest -q test_sysexit.py

注:-q与--quiet的效果一样。

6. 分组执行测试用例

一旦开发了多个测试,你可能需要对测试进行分组,我们可以利用配置文件中的配置为测试进行分组执行:

@pytest.mark.组名

# pytest.ini
[pytest]
# 命令行参数,用空格分隔
addopts = -vs

# 测试用例文件夹
testpaths = ./testcase

# 分组
markers =
    smoke:冒烟用例
    group1:第一组测试用例
# test_demo02.py
import pytest

def fun_minus(x):
    return x-2


def test_answer():
    assert fun_minus(2) == 5

@pytest.mark.smoke
def test_minus():
    assert 4-2 == 2


if __name__ == '__main__':
    pytest.main(['./test_demo02.py', '-m', 'smoke'])

测试结果:

============================= test session starts =============================
platform win32 -- Python 3.9.9, pytest-8.2.2, pluggy-1.5.0 -- F:\SoftWare\Python\Python39\python39.exe
cachedir: .pytest_cache
rootdir: F:\Code\PyCharmProject\Interview\pytest
configfile: pytest.ini
plugins: ordering-0.6, rerunfailures-14.0, xdist-3.6.1
collecting ... collected 2 items / 1 deselected / 1 selected

test_demo02.py::test_minus PASSED

======================= 1 passed, 1 deselected in 0.02s =======================

Process finished with exit code 0

记一个PyCharm中可能遇到的问题

在单个test_xxx.py文件中,在main中传入了参数,但不管怎么运行都没有生效,在cmd窗口又是正常生效的,甚至在run_suite.py中的main也是正常的。这是因为程序自动识别到了pytest框架,默认以pytest运行,要main主函数运行。

解决方法:

1、修改Python解释器(但需要对每个test文件都这样,很麻烦)

Edit Configurations,新增解释器,将目标文件作为单独的python文件运行

2、修改Python integrated Tools(可以一劳永逸)

进入到File->Settings->Tools->Python integrated Tools页面,找到 Testing - Default test runner,将其修改为Unittest

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1873265.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PD快充诱骗芯片工作原理,USB-C充电器出不来电压是什么原因?

一般使用Type-C接口的充电器基本上都是采用新的快充协议——PD快充协议&#xff0c;它不同于以前的USB-A的QC协议&#xff0c;这种协议&#xff0c;默认是没有快充电压输出的&#xff0c;VBUS和GND是0V。 所以&#xff0c;我们可以使用电阻的方式&#xff08;电流小&#xff09…

Steam新用户怎么参加夏促 Steam最新注册账号+下载客户端教程

steam夏促来了&#xff0c;这里给新玩家科普一下&#xff0c;steam就是一个游戏平台&#xff0c;里面的海量的各种游戏&#xff0c;而steam经常会有各种打折的活动&#xff0c;夏促就是其中之一&#xff0c;并且是其中规模最大的之一&#xff0c;涵盖游戏数量多&#xff0c;优惠…

【乐吾乐2D可视化组态编辑器】画布

5.1 设置画布属性 默认颜色&#xff1a;预先设置默认颜色&#xff0c;拖拽到画布的节点&#xff08;基础图形、文字、icon&#xff09;自动统一默认颜色。 画笔填充颜色&#xff1a;预先设置画笔填充颜色&#xff0c;拖拽到画布的节点&#xff08;基础图形&#xff09;自动统…

企业应该如果安全上网,软件防查盗版,企业防盗版

随着信息化的发展&#xff0c;企业日常办公越来越依赖互联网。终端以及普通PC终端在访问互联网过程中&#xff0c;会遇到各种各样不容忽视的风险&#xff0c;例如员工主动故意的数据泄漏&#xff0c;后台应用程序偷偷向外部发信息&#xff0c;木马间谍软件的外联&#xff0c;以…

java服务MultipartFile入参测试

项目中经常会涉及到文件的上传下载以及导入相关的功能&#xff0c;今天针对MultipartFile类型文档导入写一下如何测试。 文档导入接口完成&#xff0c;使用postman测试&#xff0c;使用POST方法&#xff0c;进入Body模块&#xff0c;选择form-data选项&#xff0c;key的框体右侧…

微信小程序根据蓝牙RSSI信号强度测试设备距离

背景 在做小程序连接蓝牙设备的时候&#xff0c;有需求表明在搜索到0.5米之内的设备时自动连接 问题&#xff1a; 蓝牙模组只提供了RSSI信号强度&#xff0c;那又该如何计算蓝牙设备距离小程序的距离呢&#xff1f; 解决方案 通过以下公式做大量测试&#xff1a;求 A、n 的平均…

npm创建一个空的vue3项目的方法或者pnpm创建vue3项目

1、前提我们已经安装了npm&#xff0c;或者pnpm 2、我们用npm来创建vue3项目 快速上手 | Vue.js 官网地址 这里我安装是的 node v18.20.3 以下是安装过程 &#xff1a; npm create vuelatest 根据自己的需要进行创建即可。 3、我们用pnpm来创建vite vue3项目 pnpm create …

SpringBoot项目中获取IP地址

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 OkHttp 是一个由 Square 开发的高效、现代的 HTTP 客户端库&#xff0c;用于 Android 和 Java 应用程序。它支持 HTTP/2 和 SPDY 等现代网络协议&#xff0c;…

Python28 十大机器学习算法之线性回归和逻辑回归

1.三类广义上的机器学习算法 监督学习。工作原理&#xff1a;该算法由一个目标/结果变量&#xff08;或因变量&#xff09;组成&#xff0c;该变量将从一组给定的预测变量&#xff08;自变量&#xff09;进行预测。使用这组变量&#xff0c;我们生成了一个将输入数据映射到所…

【python】pop()函数

python pop() &#xff0c;如何在Python的列表或数组中移除元素 使用 pop() 从列表中删除元素 pop() 语法概述 pop() 方法的语法如下&#xff1a; list_name.pop(index)list_name&#xff1a;列表变量名&#xff1b;内置的 pop() 方法仅需要一个可选参数&#xff1b;可选参…

async异步函数

文章目录 异步函数&#xff08;用 async 声明的函数&#xff09;异步函数的返回值async/await 的使用异步函数的异常处理总结 感谢铁子阅读&#xff0c;觉得有帮助的话点点关注点点赞&#xff0c;谢谢&#xff01; 异步函数&#xff08;用 async 声明的函数&#xff09; 异步函…

免疫防御和代谢控制十字路口的炎性小体

谷禾健康 人体的肠道粘膜内层形成物理屏障和免疫防御系统&#xff0c;以防止微生物入侵。当身体受到感染或细胞遭受损伤时&#xff0c;免疫系统会启动炎症反应来应对这些情况。炎症是对感染和组织损伤的一种急性反应&#xff0c;以限制对身体的伤害&#xff0c;这种反应是身体自…

Docker期末复习

云计算服务类型有: IaaS 基础设施及服务 PaaS 平台及服务 SaaS 软件及服务 服务类型辨析示例: IaaS 服务提供的云服务器软件到操作系统,具体应用软件自己安装,如腾讯云上申请的云服务器等;SaaS提供的服务就是具体的软件,例如微软的Office套件等。 云计算部署模式有: 私有云…

行业唯一!法大大斩获“数字可信服务——金牌奖”

近日&#xff0c;由BSI&#xff08;英国标准协会&#xff09;主办的第七届“万物互联 ∙ 智慧高峰”论坛暨第六届密码模块认证大会在上海成功举办&#xff0c;论坛上&#xff0c;法大大作为安全高效的电子合同智能签管平台&#xff0c;荣获BSI颁发的“数字可信服务——金牌奖”…

Python 语法基础一

1.变量 python 中变量很简单&#xff0c;不需要指定数据类型&#xff0c;直接使用等号定义就好。python变量里面存的是内存地址&#xff0c;也就是这个值存在内存里面的哪个地方&#xff0c;如果再把这个变量赋值给另一个变量&#xff0c;新的变量通过之前那个变量知道那个变量…

esp8266 GPIO

功能综述 ESP8266 的 16 个通⽤ IO 的管脚位置和名称如下表所示。 管脚功能选择 功能选择寄存器 PERIPHS_IO_MUX_MTDI_U&#xff08;不同的 GPIO&#xff0c;该寄存器不同&#xff09; PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U,FUNC_GPIO12);PERIPHS_IO_MUX_为前缀。后面的…

求生之路史低入手 教你怎么使用求生之路创意工坊提高体验性

求生之路是一款抵御丧尸的第一人称射击游戏&#xff0c;四名幸存者联机配合&#xff0c;在现代的城市中&#xff0c;击败各种丧尸还有强大的变种人BOSS&#xff0c;虽然是十几年前的游戏&#xff0c;但是毫不夸张的说&#xff0c;游戏丝毫不过时&#xff0c;目前steam夏促&…

Vue项目生产环境的打包优化

Vue项目生产环境的打包优化 前言 在这篇文章我们讨论Vue项目生产环境的打包优化&#xff0c;并按步骤展示实际优化过程中的修改和前后对比。 背景 刚开始的打包体积为48.71M 优化 步骤一&#xff1a;删除viser-vue viser-vue底层依赖antv/g2等库一并被删除&#xff0c;…

javafx飞机大战

Javafx飞机大战 1.使用javafx库2.按下wasd控制我方战机移动3.按下k键 我方战机发射炮弹 4.我方战机不能飞出游戏边界5.敌方战机随机发射炮弹和移动6.地方战机有多个,地方战机存在多种类型7.按下空格键 游戏停止8.游戏实时显示分数9.我方实时显示被命中次数10.超过一定的命中次数…

【24医学顶刊】GANDALF:主动学习 + 图注意力变换器 + 变分自编码器,改善多标签图像分类

GANDALF&#xff1a;主动学习 图注意力变换器 变分自编码器&#xff0c;改善多标签图像分类 提出背景子解法1&#xff1a;多标签信息样本的选择子解法2&#xff1a;生成信息丰富且非冗余的合成样本 例子&#xff1a;胸部X射线图像分析传统方法的操作和局限GaNDLF方法的优势 工…