pytest
pytest是一个用于编写和运行Python单元测试的框架。它是Python生态系统中最受欢迎的测试框架之一,具有简单易用、灵活性强的特点。
pytest具有许多特性和优势,包括:
1. 简单易用:pytest提供了一种直观且简化的方式来编写测试用例。它使用简洁的语法和自动发现机制,使得编写和运行测试变得非常容易。
2. 自动化:pytest可以自动发现测试文件和测试函数。它会在指定目录中递归搜索以"test_"开头或以"_test"结尾的文件,并执行其中的测试函数。这种自动发现机制减少了手动配置的工作,使得测试更加便捷。
3. 丰富的断言:pytest提供了丰富的内置断言函数,用于验证测试结果是否符合预期。这些断言函数可以处理各种数据类型和数据结构,包括数字、字符串、列表、字典等,使得编写断言变得简单而直观。
4. 插件系统:pytest具有可扩展的插件系统,可以通过安装第三方插件来增强其功能。这些插件可以提供额外的报告输出、测试覆盖率分析、测试并发执行等功能,满足不同项目的需求。
5. 集成性:pytest可以与其他常用工具和框架集成,例如unittest、doctest和mock等。这意味着你可以使用pytest扩展已有的测试套件,或者在已有的代码中添加新的测试。
总体而言,pytest是一个功能强大、易用且灵活的Python测试框架。它通过简化测试编写过程、提供丰富的断言和灵活的插件系统,帮助开发人员编写高质量的测试用例,以确保代码的正确性和可靠性。
以下是列出的pytest常用模块的整理表格:
模块名 | 描述 |
---|---|
pytest-randomly | 随机执行测试,发现潜在的依赖或顺序问题 |
pytest-cov | 测试覆盖率工具,用于评估测试的质量和完整性 |
pytest-django | 方便地测试Django应用,提供了专门的fixture和命令 |
pytest-bdd | 使用行为驱动开发(BDD)方式编写测试,使用Gherkin语言描述场景和步骤 |
pytest-xdist | 并行执行测试,提高测试速度和效率 |
pytest-mock | 使用mock对象模拟测试中的依赖 |
pytest-html | 生成HTML格式的测试报告,方便查看和分享测试结果 |
pytest-flask | 方便地测试Flask应用,提供了专门的fixture和命令 |
pytest-timeout | 设置测试的超时时间,防止测试卡住或运行时间过长 |
pytest-selenium | 使用Selenium测试Web应用,提供了专门的fixture和命令 |
pytest-qt | 测试Qt应用,提供了专门的fixture和工具 |
pytest-env | 在pytest.ini文件中设置环境变量,方便配置测试环境 |
pytest-repeat | 重复执行测试,检测潜在的随机或不稳定问题 |
pytest-instafail | 实时查看测试失败信息,无需等待整个测试运行结束 |
pytest-order | 自定义测试执行顺序,满足特定需求或依赖 |
pytest-subtests | 使用subtests概念组织和报告测试,提高可读性和可维护性 |
pytest-asyncio | 测试异步代码,提供了专门的fixture和工具 |
pytest-mypy | 使用mypy检查类型注解,提高代码质量和可靠性 |
pytest-flake8 | 使用flake8检查代码风格和错误,提高可读性和规范性 |
pytest-xray | 与Xray集成,方便管理和报告测试用例和结果 |
pytest-vcr | 使用VCR.py记录和回放HTTP请求,方便测试外部服务 |
pytest-check | 使用多个断言语句,不会在第一个失败时停止测试 |
pytest-datadir | 管理测试数据文件,提供了专门的fixture和工具 |
pytest-pydocstyle | 使用pydocstyle检查文档字符串的风格和规范,提高代码可读性 |
pytest-benchmark | 对代码性能进行基准测试,提供了专门的fixture和工具 |
pytest-docker | 使用Docker创建和管理测试环境,提供了专门的fixture和命令 |
pytest-tornado | 测试Tornado应用,提供了专门的fixture和工具 |
pytest-freezegun | 使用freezegun模拟时间,方便测试时间相关的代码 |
1.pytest-html
pip3 install pytest-html
在Shell执行pytest -h
可以看到pytest的命令行参数有这10大类,共132个
类别 | 中文名 | 包含命令行参参数数量 | |
---|---|---|---|
1 | positional arguments | 形参 | 1 |
2 | general | 通用 | 31 |
3 | reporting | 报告 | 18 |
4 | collection | 收集 | 15 |
5 | test session debugging and configuration | 測試session调试和配置 | 11 |
6 | pytest-warnings | pytest警告 | 1 |
7 | logging | 日志 | 11 |
8 | reporting-allure | allure测试报告 | 3 |
9 | ini-options | pytest.ini/tox.ini/setup.cfg 配置文件 |
37 |
10 | environment variables | 环境变量 | 4 |
显示print
pytest --capture=no
-v, --verbose
输出详细信息
-q, --quiet
输出简要信息
–color=color
显示颜色
--html
生成报告html路径
--self-contained-html
合并css和html样式
-s 是显示带控制台输出结果
pytest -v --html=wubantu.html --color=yes --self-contained-html wubantu.py
在乌班图crontab运行要带绝对路径
/home/yys/.local/bin/pytest -v --html=/home/yys/share/report/wubantu.html --color=yes --self-contained-html /home/yys/mobile/wubantu.py
目前测试html显示日志和终端显示日志会有冲突
-k 选中模糊匹配函数,下面例如选择代02的运行
pytest.main(['-vs', __file__, '--html=./report/tt.html', '-k=02'])
collecting ... collected 2 items / 1 deselected / 1 selected
test_04.py::test_02 setup_function
test02
PASSEDteardown_function
3.通过全局配置文件pytest.ini文件执行。注意:
一般放在项目的根目录下,名称必须是pytest.ini
当有中文时候编码格式为GB2312
pytest.ini文件可以改变默认的测试用例规则。
不管是命令行运行也好还是说主函数运行也好,都会加载这个配置文件。
addopts多个话用空格隔开
[pytest]
addopts =-vs -q
testpaths= ./testcases
python_files = test_*.py
python_classes = Test*
python_functions = test_*
四、pytest跳过测试用例。
(1)无条件跳过
@pytest.mark.skip(reason="无理由跳过")
(2)有条件跳过
@pytest.mark.skipif(workage<10, reason="工作经验少于18年跳过")
(3)pytest.skip
如果你在使用 skipif
装饰器时无法直接访问 self,可以写在函数内部
pytest.skip
import pytest
class MyTestClass:
@pytest.mark.parametrize("some_value", [42])
def test_something(self, some_value):
if some_value == 42:
pytest.skip("Some value is 42.")
assert some_value != 42
通过这种方式,我们可以根据 some_value
的值来决定是否跳过测试用例。你可以根据你的具体需求修改条件和操作
5.pytest框架用例运行级别
>>模块级(setup_module/teardown_module)开始于横块始末,全局的
>>函数级(setup_function/teardown_function)只对函数用例生效(不在类中)
>>类级(setup_class/teardown_calss)只在类中前后运行一次(在类中)
>>方法级(setup_method/teardown_method)开始于方法始末(在类中)
>>类里面的(setup/teardown)运行在调用方法前后
6.Fixture前后置
@pytest.fixture()scope :作用域
function:在函数之前和之后执行class:在类之前和之后执行
package/session :在整个项目会话之前和之后执行。autouse :自动执行。默认是False.
@pytest.fixture(scope="function" ,autouse=True)
def exe_database_sql():
print("执行sQL查询")
yield
print("关闭数据库连接")
6.Pytest之parametrize()实现数据驱动方法:
@pytest.mark.parametrize(args_name,args_value)args_name :参数名称,用于将参数值传递给函数
args_value :参数值:(列表和字典列表,元祖和字典元祖),有n个值那么用例执行n次。
date = ['23', '343', '34', '343', '34', '343', '34', '343', '34', '343', '34', '343', '34', '343', '34', '343', '34', '343', '34', '343', '34']
@pytest.mark.parametrize('test_msg', date)
def test_crmSendMsg_tup(test_msg):
print(test_msg)
time.sleep(1)
安装 pytest-xdist
pip install pytest-xdist
import pytest
from time import sleep
def test_04():
print('3434')
def test_01():
# 通过延时,直观比较运行耗时
print("testcase_01.")
sleep(2)
def test_02():
print("testcase_02.")
sleep(3)
def test_03():
print("testcase_03.")
sleep(4)
if __name__ == "__main__":
pytest.main(["-v", '-n=4', __file__, "--html=report.html", "--color=yes"]) # 使用3个进程执行,耗时4.44s
print('23')
============================= test session starts =============================
platform win32 -- Python 3.9.10, pytest-7.1.2, pluggy-1.0.0 -- C:\Users\yys53\OneDrive\python\install\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.9.10', 'Platform': 'Windows-10-10.0.22000-SP0', 'Packages': {'pytest': '7.1.2', 'py': '1.11.0', 'pluggy': '1.0.0'}, 'Plugins': {'forked': '1.4.0', 'html': '3.1.1', 'metadata': '2.0.1', 'xdist': '2.5.0'}}
rootdir: C:\Users\yys53\OneDrive\python\bestscript
plugins: forked-1.4.0, html-3.1.1, metadata-2.0.1, xdist-2.5.0
gw0 I / gw1 I / gw2 I / gw3 I
[gw0] win32 Python 3.9.10 cwd: C:\Users\yys53\OneDrive\python\bestscript
[gw1] win32 Python 3.9.10 cwd: C:\Users\yys53\OneDrive\python\bestscript
[gw2] win32 Python 3.9.10 cwd: C:\Users\yys53\OneDrive\python\bestscript
[gw3] win32 Python 3.9.10 cwd: C:\Users\yys53\OneDrive\python\bestscript
[gw0] Python 3.9.10 (tags/v3.9.10:f2f3f53, Jan 17 2022, 15:14:21) [MSC v.1929 64 bit (AMD64)]
[gw1] Python 3.9.10 (tags/v3.9.10:f2f3f53, Jan 17 2022, 15:14:21) [MSC v.1929 64 bit (AMD64)]
[gw2] Python 3.9.10 (tags/v3.9.10:f2f3f53, Jan 17 2022, 15:14:21) [MSC v.1929 64 bit (AMD64)]
[gw3] Python 3.9.10 (tags/v3.9.10:f2f3f53, Jan 17 2022, 15:14:21) [MSC v.1929 64 bit (AMD64)]
gw0 [4] / gw1 [4] / gw2 [4] / gw3 [4]scheduling tests via LoadScheduling
文件命名2.py::test_03
文件命名2.py::test_04
文件命名2.py::test_01
文件命名2.py::test_02
[gw0] [ 25%] PASSED 文件命名2.py::test_04
[gw1] [ 50%] PASSED 文件命名2.py::test_01
[gw2] [ 75%] PASSED 文件命名2.py::test_02
[gw3] [100%] PASSED 文件命名2.py::test_03- generated html file: file://C:\Users\yys53\OneDrive\python\bestscript\report.html -
============================== 4 passed in 5.63s ==============================
2.pytest-parallel
pytest-parallel使用多线程后,则最后执行时间是运行时间最长的线程的时间。
1.注意:pytest-parallel目前暂不能和allure报告使用(已解决看第二点)
2.安装pytest-multithreading-allure (处理 pytest-parallel 不能和测试报告插件 allure-pytest 兼容的问题)(但是遇到问题:@pytest.mark.parametrize使用日志会混乱:未解决)
安装:
pip3 install pytest-parallel
常用参数解析:
–workers (optional) n:多进程运行, n是进程数。默认为1。
(注意:若为window平台,则该workers永远=1,在linux和mac下可以取不同值。)
–tests-per-worker (optional) n:多线程运行, n是每个worker运行的最大并发线程数。默认为1(该参数不受运行平台限制)。
(如果两个参数都配置了,就是进程并行,每个进程最多n个线程,总线程数:进程数 * 线程数)
在window下的cmd命令行执行:
1.yaml文件如何实现接口关联封装
2.yaml文件如何实现动态参数的处理3.yaml文件如何实现文件上传
4.yaml文件如何实现如何解决断言,特别是当有参数化的时候如何断言。
5.yaml文件数据量太大怎么样?
6.接口自动化框架的扩展︰加密接口,签名接口。自定义的功能接口。
深度思考:做自动化是为了什么?投入和产出比。
如何能够做到只要自动化测试框架搭建完成之后,其他的测试不需要改人任何代码,也可以通过这框架实现自动化测试?
用途∶
1.用于做配置文件
配置全局的数据︰环境变量,数据库信息,账号信息,日志格式,日志报告名称。2用于写测试用例(接口自动化测试用例)--用于数据驱动
一、YAML简介
yaml是一种数据格式(json),支持注释,换行,多行字符串,裸字符串等。
二、YAML语法规则
1.大小写敏感(区分大小写)⒉使用缩进表示层级关系。
3.缩进不管空格的数量,只要层级的左边对齐就OK4.#表示注释
三、YAML和JSON数据结构对比JSON
1.Map对象:键值对。(字典dict )使用f括起来,如:{name:百里,age:18}⒉数组,(列表list )
使用括起来,如:[{name:百里,age:18],{name:微微,age:16]]
如︰
msxy:
name: 百里
age: 18
一行的写法︰
msxy: {name: 百里,age: 18}
⒉数组,(列表list ),用一组横行""开头。如:
msxy:
-name: 百里
-age: 18
一行的写法∶
msxy : [{name: 百里},{age: 18}]
py例子
写入
allow_unicode=True 避免中文
default_flow_style=False : 表示dump后的字典数据全部以yml格式显示,默认为为True
import yaml
with open('config.yaml', 'w', encoding='utf-8') as f:
data = [{'msxy': [{'name': '百里'}, {'age': 18}]}]
yaml.dump(data=data, stream=f, allow_unicode=True, default_flow_style=False)
- msxy:
- name: 百里
- age: 18
读取
import yaml
with open('config.yaml', encoding='utf-8') as f:
content = yaml.load(stream=f.read(), Loader=yaml.Loader)
print(content)
[{'msxy': [{'name': '百里'}, {'age': 18}]}]
5.解决@pytest.mark.parametrize乱码问题
在pytest.ini文件中写入:
[pytest]
disable_test_id_escaping_and_forfeit_all_rights_to_community_support = True
控制台结果[]中的中文正常现实
============================= test session starts =============================
collecting ... collected 7 itemsUIAutomator - 副本.py::test_begin_te1[note9_5g_ip-锦瑟年华152] PASSED [ 14%]锦瑟年华152 192.168.31.50
UIAutomator - 副本.py::test_begin_te1[note8_ip-颠覆宇宙为英语] PASSED [ 28%]颠覆宇宙为英语 192.168.31.109
UIAutomator - 副本.py::test_begin_te1[mi8_lite_ip-搜狗不行来百度1] PASSED [ 42%]搜狗不行来百度1 192.168.31.176
UIAutomator - 副本.py::test_begin_te1[redmi9_ip-16619945346] PASSED [ 57%]16619945346 192.168.31.179
UIAutomator - 副本.py::test_begin_te1[note10pro_ip-不吃火锅] PASSED [ 71%]不吃火锅 192.168.31.41
UIAutomator - 副本.py::test_begin_te1[mix2s_ip-被风吹过的灼思] PASSED [ 85%]被风吹过的灼思 192.168.31.177
UIAutomator - 副本.py::test_begin_te1[redmi8A_ip-血红色的东云缀化] PASSED [100%]血红色的东云缀化 192.168.31.192
============================== 7 passed in 0.14s ==============================Process finished with exit code 0
(网上说方法二改conftest.py没成功)
需要安装库pytest-rerunfailures
pip3 install pytest-rerunfailures
pytest支持在测试失败时自动重试测试。这对于测试失败原因不是由测试代码本身引起的随机因素(例如网络问题或并发问题)非常有用。
要启用pytest测试重试,可以使用`--reruns`参数。例如,要将测试用例重新运行两次,可以使用以下命令运行pytest:
pytest --reruns 2 test_file.py
这将运行`test_file.py`中的所有测试用例,并在测试失败时重试测试用例两次。
您还可以使用`--reruns-delay`参数指定重试之间的时间间隔。例如,以下命令将测试用例重新运行两次,每次间隔5秒:
pytest --reruns 2 --reruns-delay 5 test_file.py
注意,重试测试用例可能会增加测试运行时间,因此建议仅在必要时使用此功能。
在 pytest 中,你可以使用 @pytest.mark.parametrize
装饰器来为测试函数添加重试功能。首先,你需要导入 pytest
模块,然后使用 @pytest.mark.parametrize
来为测试函数添加参数,其中一个参数是 pytest.mark.flaky
,它允许你指定测试失败时的重试次数和重试间隔。以下是一个示例:
import pytest
@pytest.mark.parametrize("retry_count", [2]) # 2 表示重试两次
@pytest.mark.flaky(reruns=2, reruns_delay=1) # 2 表示重试两次,1 表示重试间隔为1秒
def test_example(retry_count):
# 这个测试函数会尝试执行两次,如果失败,会在每次重试之间等待1秒
assert some_function_to_test() == expected_result
def some_function_to_test():
# 这里放置你的测试代码
pass
def expected_result():
# 这里定义你期望的测试结果
pass
在上面的示例中,@pytest.mark.flaky
装饰器允许测试函数 test_example
失败时重试两次,并且在每次重试之间等待1秒。你可以根据需要修改 reruns
和 `reruns_delay
pytest-repeat
是一个用于 Pytest 的插件,它允许你设置整体重复运行测试用例的次数。使用 pytest-repeat
插件可以轻松地在 Pytest 中实现整体运行次数的功能,而无需编写自定义插件或使用循环结构。
以下是 pytest-repeat
插件的基本用法:
-
安装插件:首先,确保已经安装了
pytest-repeat
插件。你可以使用以下命令进行安装:pip install pytest-repeat
-
整体运行次数:运行测试用例:使用
pytest
命令运行你的测试用例,并使用--count
参数指定整体运行次数。pytest --count=2
在上述示例中,测试用例将会运行两次。
-
指定函数运行次数:为了让测试函数多次运行,你需要在测试函数上添加
@pytest.mark.repeat(n)
装饰器,其中n
是你想要重复运行测试的次数。例如,如果你想要运行一个测试函数三次,你可以使用@pytest.mark.repeat(3)
装饰器:
import pytest
@pytest.mark.repeat(3) # 这将使测试函数运行三次
def test_example():
# 这是你的测试代码
现在,当你运行 pytest 时,被标记为 @pytest.mark.repeat
的测试函数将会按照指定的次数重复运行。
你也可以使用其他选项来更精细地控制重复运行的行为。以下是一些常用的选项:
--count=N
:设置整体运行次数为 N。--random-order
:在每次运行之前随机排序测试用例的顺序。--first-fail
:在某次运行中出现第一个失败后停止运行剩余的重复次数。--fail-last
:在所有重复运行完成后,以最后一次运行的结果作为测试结果。
请注意,pytest-repeat
插件会影响整个测试套件的运行次数,包括所有的测试文件和测试用例。使用该插件时,要确保在测试用例设计和执行上没有副作用,并且每次运行的结果是可预测和可重现的。
您可以使用 pytest-repeat
插件来重复运行所有或指定测试用例。例如,您可以使用 --count
参数来指定重复运行的次数。例如,要重复运行整个会话,可以在命令行中输入指令:
pytest test_repeat.py -s -v --count=3 --repeat-scope=session
¹。
您也可以在执行的用例上加入装饰器 @pytest.mark.repeat(count)
来重复执行单个或多个用例 ²。
希望这些信息对您有所帮助!
源: 与必应的对话, 2023/7/9
(1) pytest重复运行所有或指定测试用例(pytest-repeat插件) - 习久性成 - 博客园. https://bing.com/search?q=pytest+运行2次方法.
(2) pytest---重复执行用例(pytest-repeat) - 测试-安静 - 博客园. https://www.cnblogs.com/qican/p/15038067.html.
(3) 【pytest】2.运行方法&参数 - --D - 博客园. https://www.cnblogs.com/mind18/p/15621182.html.
(4) pytest重复运行所有或指定测试用例(pytest-repeat插件) - 习久性成 - 博客园. https://www.cnblogs.com/hls-code/p/15041061.html.
您可以在 conftest.py
文件中使用 pytest_addoption
函数来添加命令行选项,然后在测试用例中使用 request.config.getoption
函数来获取命令行传入的参数值。例如,您可以在 conftest.py
文件中添加以下代码来定义一个名为 --file_name
的命令行选项:
conftest.py
def pytest_addoption(parser):
parser.addoption(
"--paramet",
action="store"
)
@pytest.fixture(scope='session', autouse=False)
def paramet(request):
paramet = request.config.getoption("--paramet")
if '[' in paramet and ']' in paramet:
# 字符串转列表
import ast
paramet = ast.literal_eval(paramet)
return paramet
pytest --paramet=1
pytest-timeout
是一个用于设置测试超时的 pytest 插件。超时总是以秒为单位指定,可以通过多种方式定义,优先级从低到高如下:
- 您可以在 pytest 配置文件中使用
timeout
选项设置全局超时。例如:[pytest] timeout = 300
PYTEST_TIMEOUT
环境变量设置全局超时,覆盖配置文件中可能的值。--timeout
命令行选项设置全局超时,覆盖环境变量和配置选项。- 使用测试项上的
timeout
标记,您可以逐项指定超时:@pytest.mark.timeout(300) def test_foo(): pass
将超时设置为 0 秒将禁用超时,因此如果您已设置全局超时,则仍然可以使用标记禁用超时¹。希望这些信息对您有所帮助!
本文作者: 永生
本文链接: https://yys.zone/detail/?id=263
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
发表评论
评论列表 (0 条评论)
暂无评论,快来抢沙发吧!