菜鸟记录之pytest,updating
pytest(仅个人学习)
参数
- pytest 执行当前目录及子目录所有用例
- pytset py::class::function 执行具体某个文件某个类某个方法
- -m login 执行@pytest.mark.login装饰器修改的用例
- -q 只打印用例执行结果
- -s 等于--capture=no,输出到终端
- -x 遇到错误时停止测试
- --maxfail=num 用例错误个数达到num,停止测试
- -k login 执行包含login的用例
- -k "not login" 执行不包含login的用例
- -k "login or quit" 执行包含login或quit的用例
断言
# 判断 xx 为真
assert xx
# 判断 xx 不为真
assert not xx
# 判断 b 包含 a
assert a in b
# 判断 a 等于 b
assert a == b
# 判断 a 不等于 b
assert a != b
# 断言失败时显示报错信息
assert 表达式, 错误信息
# 判断代码抛出指定异常
with pytest.raises(IndexError) as excinfo:
i = 1 / 0
# 注意:断言需写在结构体外
# 断言异常的类型
assert excinfo.type == ZeroDivisionError
# 断言异常的值,value需要str转换
assert "division by zero" in str(excinfo.value)
# match匹配异常的value
def test_zero_division2():
with pytest.raises(ZeroDivisionError, match="zero"):
i = 100 / 0
# 断言装饰器
@pytest.mark.xfail(raises=ZeroDivisionError)
def test_zero_division3():
i = 100 / 0
with-raises更适用于故意测试异常的代码,断言装饰器适用于可能会发生异常的情况
前置与后置
在pytest详细的区分了各种级别
- 模块级别:setup_module、teardown_module
- 函数级别:setup_function、teardown_function
- 类级别:setup_class、teardown_class
- 方法级别:setup_method、teardown_method
执行顺序
全局:setup_module --> testcase --> teardown_module
类:setup_class --> testcase --> teardown_class
函数(不在类中的方法):setup_function --> testcase --> teardown_function
方法(在类中的方法):setup_method --> testcase --> teardown_method
测试用例:与unittest不同的是pytest的测试用例默认是从上往下执行,而unittest会按照ASCII码从小到大执行
❓有疑问的是:setup和teardown会优先function/method执行
类外:setup --> setup_function --> testcase --> teardown_function --> teardown
类内:setup --> setup_method --> testcase --> teardown_method --> teardown
fixture
@pytest.fixture(scope="function", params=None, autouse=False, ids=None, name=None)
def login():
"""
scope: fixture作用域, function(默认), class, module, package, session
params: 参数列表
autouse: 用例自动使用fixture, 默认False
ids: 配合参数列表使用,一对一作为参数标识
name: 装饰器名称,定义name后不能通过函数名调用fixture
"""
print('success')
fixture实例化顺序
- scope范围较高的实例化优先
- 同作用域的fixture遵循测试函数中声明的顺序,并遵循依赖关系(A 依赖 B,B先实例化)
- 自动使用的实例化优先
@pytest.mark.usefixtures(),先执行的放底层,后执行的放上层
fixture函数传参,先执行的放前面,后执行的放后面
fixture之间的依赖,通过函数传参传递
fixture有返回值,需通过函数传参的方式获取值
# request是pytest的一个内置fixture,用于获取测试用例上下文
# params用列表传递,根据列表长度来决定fixture调用几次(如果用字典传递,只能取key值)
@pytest.fixture(params=[1,2])
def user(request):
return request.param #1 2
@pytest.fixture(params=[4,5])
def pwd(request):
return request.param #4 5
# 有多个params,会生成笛卡尔积
def test_login(user, pwd):
print(user, pwd) #(1 4)(1 5)(2 4)(2 5)
fixture之yield
# 如果yield前面的代码抛出异常,则不会执行yield后面的内容(即teardown)
# 如果测试用例抛出异常,yield后面的内容正常执行
@pytest.fixture()
def login():
print('start login')
yield 'success'
print('end login')
# addfinalizer 终结函数
# request.addfinalizer()前面抛出异常,则不会调用fin
# 测试用例抛出异常,fin正常执行
@pytest.fixture()
def login(request):
print('start login')
def fin:
print('end fin')
request.addfinalizer(fin)
return 'success'
conftest.py文件
对于通用的fixture,可以将之写在conftest配置文件中
1、对同一package下所有测试用例生效
2、pytest自动引入,不需要import
3、文件名是固定的,不同目录可以有自己的conftest
用例执行状态
- passed 用例通过
- failed 断言失败
- error 代码报错
- xfail 预期失败
pytest的装饰器
@pytest.fixture(scope="function", params=None, autouse=False, ids=None, name=None)
功能:定义一个fixture
参数:
- scope: fixture作用域, function(默认), class, module, package, session
- params: 参数列表
- autouse: 用例自动使用fixture, 默认False
- ids: 配合参数列表使用,一对一作为参数标识
- name: 装饰器名称,定义name后不能通过函数名调用fixture
@pytest.mark.usefixture
功能:使用fixture
参数
@pytest.skip(reason="")
功能:跳过该测试用例
参数:
- reason:跳过的理由
@pytest.skipif(expr, reason="")
功能:表达式满足则跳过该测试用例
参数:
- expr:跳过用例的条件
- reason:跳过的理由
@pytest.mark.parametrize(param, value, ids=None, indirect=False)
参数:
- param:"a,b"、['a','b'] 参数名/函数名
- value:[(),()]、[{},{}] 参数值
- ids:用例id
- indirect:True时,参数为函数名
skip
import pytest
import sys
# 在测试用例执行期间强制跳过不再执行剩余内容
# for循环中使用相当于break
pytest.skip("循环第三次不执行了")
# 将skip赋值为一个变量,用于统一管理使用
skip_win = pytest.mark.skip("windows用例跳过执行")
@skip_win
def test_win10():
print(sys._getframe().f_code.co_name)
插件
1.pytest-html
# 下载
pip install pytest-html
# 使用
# --html 指定测试报告生成路径
# --self-contained-html css样式内嵌到HTML中
pytest --html=report.html --self-contained-html
2.pytest-repeat
# 下载
pip install pytest-repeat
# 使用
# --reruns 失败用例重行执行次数
# --count 重复执行次数
# --repeat-scope 重复执行的用例范围(function, class, module, package, session),搭配count使用
pytest --reruns=5 --count=2 --repeat-scope
# 指定测试用例重复执行count次
@pytest.mark.repeat(count)
注:兼容性问题
pytest-repeat不能与unittest.TestCase测试类一起使用,会使--count只重复1次并报警告
3.pytest-assume
# 下载
pip install pytest-assume
# 使用
插件不需要调用
pytest默认其中一个断言失败不会执行后面的代码
使用插件可以写多个断言,其中一个失败不影响后面的代码
4.pytest-xdist
# 下载
pip install pytest-xdist
# 分布式执行用例的设计原则
# 1.独立运行 2.随机执行 3.不影响其他用例
# 使用
# -n auto自动检测到系统的CPU核数,也可以指定CPU核数
# 分布式插件默认是无序执行
# --dist=loadscope 按照同一个模块下的函数和同一个测试类下的方法来分组
# --dist=loadfile 按照同一个文件名来分组
pytest -n atuo --dist=loadfile
pytest.ini配置文件
说明:pytest的主配置文件,可以改变pytest的默认行为
# 配置标记装饰器,可以解决warning报错
[pytest]
markers =
baidu: 百度的测试用例
QQ: qq的测试用例
# True: 标记为xfail的用例结果设置成失败
xfail_strict = True
# 更改默认命令行选项, 输入pytest达到下面的效果
addopts = pytest -v -s
# 控制台实时输出日志,True显示用例的项目路径
log_cli = True
# 配置不需要遍历用例的目录
norecursedirs = .* dist CVS _darcs {arch} *.egg venv src resources log report util
# 更改用例搜集规则
python_files = test_* *_test test*
python_classes = Test* test*
python_functions = test_* test*
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix