Pytest--安装与入门

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 + 1def 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 itemtest_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 pytestdef fun_plus(x):return x+2def test_answer():assert fun_plus(2) == 5def test_addition():assert 1+1 == 2if __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 itemstest_demo01.py::test_answer FAILED                                       [ 50%]
test_demo01.py:5 (test_answer)
4 != 5Expected :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: AssertionErrortest_demo01.py::test_addition PASSED                                     [100%]========================= 1 failed, 1 passed in 0.03s =========================Process finished with exit code 1
2. 指定模块/文件
# test_demo01.py
import pytestdef fun_plus(x):return x+2def test_answer():assert fun_plus(2) == 5def test_addition():assert 1+1 == 2# if __name__ == '__main__':
#     pytest.main()
# test_demo02.py
import pytestdef fun_minus(x):return x-2def test_answer():assert fun_minus(2) == 5def test_minus():assert 4-2 == 2# if __name__ == '__main__':
#     pytest.main()
# run_suite.py
import pytestif __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 pytestif __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 LoadSchedulingtest_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.exedef 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.exedef 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 pytestif __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 itemstest_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 pytestif __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 itemstest_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 pytestif __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 itemstest_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 pytestif __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 itemstestcase/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 pytestdef fun_plus(x):return x+2def test_01_answer():assert fun_plus(2) == 5@pytest.mark.run(order=1)
def test_02_addition():assert 1+1 == 2if __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 pytestdef fun_minus(x):return x-2def test_answer():assert fun_minus(2) == 5@pytest.mark.smoke
def test_minus():assert 4-2 == 2if __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 selectedtest_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.mzph.cn/web/36316.shtml

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

相关文章

基于Java影院管理系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f;感兴趣的可以先收藏起来&#xff0c;还…

树莓派4B学习笔记14:Python多线程编程_线程间的同步通信_(锁‘threading.Lock’)

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; 今日学习树莓派与Python的多进程编程_线程间同步通信 文…

axios之CancelToken取消请求

从 v0.22.0 开始&#xff0c;Axios 支持以 fetch API 方式—— AbortController 取消请求 此 API 从 v0.22.0 开始已被弃用&#xff0c;不应在新项目中使用 官网链接 1. 背景 最近项目中遇到一个场景&#xff0c;当连续触发一个请求时&#xff0c;如果是同一个接口&#xf…

【Redis-04 补充】Redis事务

【Redis-04 补充】Redis事务 1. 事务冲突的问题1.1 举例1.2 悲观锁1.3 乐观锁1.4 Redis中的乐观锁 WATCH key [key …]1.5 Redis事务三特性 2. 秒杀案例2.1 相关代码2.2 模拟并发工具httpd-tools 3. 设计一个秒杀系统3.1 预热库存3.2 秒杀请求3.3 生成订单3.4 限流与防刷 4. 总…

【代码随想录】【算法训练营】【第52天】 [647]回文子串 [516]最长回文子序列

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 LeetCode。 day 52&#xff0c;周五&#xff0c;开始补作业了~ 题目详情 [647] 回文子串 题目描述 647 回文子串 解题思路 前提&#xff1a;寻找回文子串&#xff0c;子串意味着元素连续 思路&#xff1a;…

Android 10.0 关于定制自适应AdaptiveIconDrawable类型的动态时钟图标的功能实现系列一

1.前言 在10.0的系统rom定制化开发中,在关于定制动态时钟图标中,原系统是不支持动态时钟图标的功能,所以就需要从新 定制动态时钟图标关于自适应AdaptiveIconDrawable类型的样式,就是可以支持当改变系统图标样式变化时,动态时钟 图标的背景图形也跟着改变,所以接下来就来…

低代码+定制:优化项目管理的新方案

引言 在当今快速变化的商业环境中&#xff0c;企业需要更加灵活、高效的项目管理工具。低代码平台作为一种新的开发方式&#xff0c;因其能够快速构建应用程序而受到广泛关注。与此同时&#xff0c;软件定制开发仍然是满足特定复杂需求的重要手段。在项目管理中&#xff0c;低代…

【RT摩拳擦掌】基于RT106L/S语音识别的百度云控制系统

【RT摩拳擦掌】基于RT106L/S语音识别的百度云控制系统 一 文档简介二 平台构建2.1 使用平台2.2 百度智能云2.2.1 物联网核心套件2.2.2 在线语音合成 2.3 playback语音数据准备与烧录2.4 开机语音准备与添加2.5 唤醒词识别词命令准备与添加 三 代码准备3.1 sln-local/2-iot 代码…

【开发环境】MacBook M2安装git并拉取gitlab项目,解决gitlab出现Access Token使用无效的方法

文章目录 安装Homebrew安装git打开IDEA配置git打开IDEA拉取项目 安装Homebrew /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"在iTerm等命令行工具打开后&#xff0c;输入上面的命令 之后根据中文提示完成Homebrew的下载…

高考填报志愿,是选就业前景?还是选自己的兴趣爱好?

一、 当前的就业形式 受yi情影响&#xff0c;全国的就业处于下滑趋势&#xff0c;互联网和实体企业呈现疲软势态&#xff0c;很多企业不得不裁员。大学毕业生人数几乎每年都会上涨&#xff0c;带来的是僧多粥少的就业状态。 考得好不如报得好 就业环境如此严峻的形势下&#…

itext生成pdf文件demo示例

需求 在PDF文件中植入一些信息&#xff08;pdf模版&#xff09; 制作模版 可以看到下面红色箭头标注位置&#xff0c;这都是我们需要动态写入数据的表单域&#xff0c;可以使用wps等工具来制作 点击编辑表单&#xff0c;可以给对应空间添加表单域&#xff0c;表单域名称是ke…

Redis 哨兵主备切换的数据丢失问题应该怎么解决?

引言&#xff1a;Redis作为一种高性能的内存数据库&#xff0c;广泛应用于分布式系统中。为了保证服务的高可用性&#xff0c;Redis提供了哨兵&#xff08;Sentinel&#xff09;机制&#xff0c;用于监控和管理Redis实例的自动故障恢复。然而&#xff0c;即使在哨兵的保护下&am…

Golang | Leetcode Golang题解之第204题计数质数

题目&#xff1a; 题解&#xff1a; func countPrimes(n int) int {primes : []int{}isPrime : make([]bool, n)for i : range isPrime {isPrime[i] true}for i : 2; i < n; i {if isPrime[i] {primes append(primes, i)}for _, p : range primes {if i*p > n {break}…

idea 项目互联网转内网开发 依赖报错问题 maven问题

场景&#xff1a; 这个问题困扰好久&#xff0c;通过分析后&#xff0c;发现是maven配置问题&#xff0c;废话不多说&#xff0c;上干活。 问题描述 项目互联网从转内网开发&#xff0c;提前下载好repository&#xff0c;跟项目一起导入内网&#xff0c;导入后&#xff0c;发…

嵌入式计算器模块实现

嵌入式计算器模块规划 计算器混合算法解析 上面我们的算法理论已经完善, 我们只用给一个混合运算式, 计算器就可以帮助我们计算出结果. 但是存在一个痛点, 每次计算算式,都要重新编译程序, 所以我们想到了, 利用单片机, 读取用户输入的按键, 组成算式, 输入给机器, 这样我们就…

读AI新生:破解人机共存密码笔记15辅助博弈

1. 辅助博弈 1.1. assistance game 1.2. 逆强化学习如今已经是构建有效的人工智能系统的重要工具&#xff0c;但它做了一些简化的假设 1.2.1. 机器人一旦通过观察人类学会了奖励函数&#xff0c;它就会采用奖励函数&#xff0c;这样它就可以执行相同的任务 1.2.1.1. 解决这…

Dominate_一个用于生成和操作 HTML 文档的 Python 库

目录 01初识 Dominate 什么是 Dominate&#xff1f; 为什么选择 Dominate&#xff1f; 安装与配置 02Dominate 的基本使用 创建简单的 HTML 文档 添加表格 嵌套结构 03Dominate 的高级功能 动态内容生成 使用…

CSF视频文件格式转换WMV格式

如果大家看过一些高校教学讲解视频的话&#xff0c;很可能见过这样一个难得的格式&#xff0c;".csf "&#xff0c;非常漂亮 。 用暴风影音都可以打开观看&#xff0c;会自动下载解码。 但是一旦我们想要利用或者上传视频的时候就麻烦了&#xff0c;一般网站不认这…

下载旧版本vscode及扩展,离线下载远程linux服务器插件

背景 工作的内网没有网络&#xff0c;无法使用网络来下载插件和vscode软件&#xff0c;且有远程linux服务器需求&#xff0c;linux服务器中lib相关库比较旧且无法更新&#xff0c;所以需要选择一个旧版本的vscode&#xff0c;相应插件也需要选择旧版本的 旧版本vscode下载 没…

Windows下activemq集群配置(broker-network)

1.activemq版本信息 activemq&#xff1a;apache-activemq-5.18.4 2.activemq架构 3.activemq集群配置 activemq集群配置基于Networks of Brokers 这种HA方案的优点&#xff1a;是占用的节点数更少(只需要2个节点),而且2个broker都可以响应消息的接收与发送。不足&#xff…