常用参数
pytest -v -s 文件名/文件夹名
-m
:只运行被标记的测试用例-k
:只运行与给定字符串表达式匹配的测试用例-s
:显示详细报告-q
:显示简洁报告-x
:用例失败时立即停止测试<font style="color:rgb(51, 51, 51);">--maxfail=n</font>
:失败n后停止运行测试
参数化
import pytest
@pytest.mark.parametrize('username,password',[('admin','123456'),('cherry','33333')])
def test_Demo1(username,password):
print(username,password)
assert 1 == 1
if __name__ == '__main__':
pytest.main(['-vs','--color=yes','./run.py'])
Pytest.ini文件配置
- 避免每次都填参数,文件需要放在项目根目录下
pytest.ini
[pytest]
# 执行命令
addopts = -s -v --color=yes
# 用例文件夹
testpaths = ./run.py
# 用例文件
python_files = test*.py
# 用例类
python_classes = Test*
# 用例函数
python_funtions = test*
# 控制台输出
log_cli = 1
- 然后每次只需要输入pytest即可
Pytest.fixture
- fixture修饰器来标记固定的工厂函数,在其他函数、模块、类或整个工程调用它时会被激活并优先执行,通常会被用于完成预置处理和重复操作
fixture(scope='function',params=None,autouse=Flase,ids=None,name=None)
<font style="color:#F5222D;">scope</font>
:被标记方法的作用域
<font style="color:#096DD9;">function(default)</font>
:作用于每个测试方法,每个test都运行一次
<font style="color:#096DD9;">class</font>
:作用于整个类,每个class的所有test只运行一次
<font style="color:#096DD9;">module</font>
:作用于整个模块,每个module的所有test只运行一次
<font style="color:#096DD9;">session</font>
:作用于整个session(慎用),每个session只运行一次
<font style="color:#F5222D;">params</font>
:(list类型)提供参数数据,供调用标记方法的函数使用
<font style="color:#F5222D;">autouse</font>
:是否自动运行,默认为False不运行,设置为True自动运行
- 用途1:装饰函数
import pytest
class Test_demo:
# 被装饰过的函数,函数名可以作为变量传递给测试用例,最终在执行用例之前执行这个装饰过的函数
@pytest.fixture()
def before(self):
print('\n-------------->before')
def test_a(self,before):
print('-------->test_a')
assert 1 == 1
输出结果
run.py::Test_demo::test_a
-------------->before
-------->test_a
PASSED
============================== 1 passed in 0.01s ==============================
- 用途2:装饰类
import pytest
@pytest.fixture()
def before(): # fixture标记的函数可以应用于测试类外部,且在setup之前运行
print('\n-------------->before')
@pytest.mark.usefixtures('before')
class Test_demo:
def setup(self):
print('------>setup')
def test_a(self):
print('-------->test_a')
assert 1 == 1
输出结果:
run.py::Test_demo::test_a
-------------->before # 发现before自动优先于测试类运行
------>setup
-------->test_a
PASSED
============================== 1 passed in 0.01s ==============================
- 用途3:自己运行,不用装饰任何其他
import pytest
@pytest.fixture(autouse=True) # 设置为默认运行
def before():
print('\n-------------->before')
# @pytest.mark.usefixtures('before')
class Test_demo:
def setup(self):
print('------>setup')
def test_a(self):
print('-------->test_a')
assert 1 == 1
输出结果:
run.py::Test_demo::test_a
-------------->before # 发现before自动优先于测试类运行
------>setup
-------->test_a
PASSED
============================== 1 passed in 0.01s ==============================
- 用途4:设置作用域(
**<font style="color:#096DD9;">scope</font>**
)
import pytest
@pytest.fixture(autouse=True,scope='function') # 作用域为function,会作用在每个测试用例之前,设置为默认运行
def before():
print('\n------>before')
# @pytest.mark.usefixtures('before')
class Test_demo:
def setup(self):
print('------>setup')
def test_a(self):
print('------>test_a')
assert 1 == 1
def test_b(self):
print('------->test_b')
assert 1 == 1
作用域function输出结果:
run.py::Test_demo::test_a
------>before # 运行第一次
------>setup
------>test_a
PASSED
run.py::Test_demo::test_b
------>before # 运行第二次
------>setup
------->test_b
PASSED
============================== 2 passed in 0.01s ==============================
作用域class输出结果:
run.py::Test_demo::test_a
------>before # 只运行一次
------>setup
------>test_a
PASSED
run.py::Test_demo::test_b ------>setup
------->test_b
PASSED
============================== 2 passed in 0.02s ==============================
- 用途5:参数化(将返回值传递给测试用例)
- 返回的值为单个数
import pytest
@pytest.fixture()
def need_data():
return 2 # 返回数字2
class Test_demo:
def test_a(self,need_data):
print('\n-------->test_a')
assert need_data != 3 # 拿到返回值做断言
输出结果:
run.py::Test_demo::test_a
-------->test_a
PASSED
============================== 1 passed in 0.03s ==============================
2. <font style="color:#9254DE;">返回值为列表</font>
import pytest
@pytest.fixture(params=[1,2,3])
def need_data(request):
return request.param # 返回数字2
class Test_demo:
def test_a(self,need_data):
print('\n-------->test_a')
assert need_data != 3 # 拿到返回值做断言
输出结果:
run.py::Test_demo::test_a[1]
-------->test_a
PASSED
run.py::Test_demo::test_a[2]
-------->test_a
PASSED
run.py::Test_demo::test_a[3]
-------->test_a
FAILED
================================== FAILURES ===================================
_____________________________ Test_demo.test_a[3] _____________________________
self = <run.Test_demo object at 0x000000000360C100>, need_data = 3
def test_a(self,need_data):
print('\n-------->test_a')
> assert need_data != 3 # 拿到返回值做断言
E AssertionError
run.py:36: AssertionError
=========================== short test summary info ===========================
FAILED run.py::Test_demo::test_a[3] - AssertionError
========================= 1 failed, 2 passed in 0.37s =========================
- 嵌套:一个fixture引用另一个fixture
import pytest
@pytest.fixture()
def fix1():
print('\n-->call fix1')
@pytest.fixture()
def fix2(fix1):
print('-->call fix2')
def test_main(fix2):
assert 1 == 1
输出结果:
run.py::test_main
-->call fix1
-->call fix2
PASSED
============================== 1 passed in 0.01s ==============================
- 组合:指多个fixture实现遍历组合
import pytest
@pytest.fixture(params=['unittest','pytest'])
def fix1(request):
yield request.param
@pytest.fixture(params=['python','java'])
def fix2(request):
yield request.param
def test_main(fix1,fix2):
print(f'\n{fix1},{fix2}')
assert 1 == 1
输出结果:
run.py::test_main[unittest-python]
unittest----python
PASSED
run.py::test_main[unittest-java]
unittest----java
PASSED
run.py::test_main[pytest-python]
pytest----python
PASSED
run.py::test_main[pytest-java]
pytest----java
PASSED
============================== 4 passed in 0.02s ==============================
- 覆盖:就近原则,本地fixture优先级高于上级或全局
import pytest
@pytest.fixture()
def fix1(request):
print('\ncall fix1')
@pytest.fixture()
def fix1(request):
print('\ncall fix2')
def test_main(fix1):
assert 1 == 1
输出结果:
run.py::test_main
call fix2
PASSED
============================== 1 passed in 0.01s ==============================