import pytest
class Test_pytest:
# 第一种传参:return返回值
@pytest.fixture()
def data(self):
return 1
def test_a(self, data):
assert data == 1
@pytest.mark.usefixtures("data") # 拿不到参数
def test_a_1(self):
assert False
# 第二种传参:params参数值
@pytest.fixture(params=[1, 2, 3])
def more_data(self, request):
return request.param
def test_b(self, more_data):
assert more_data != 2
# 第三种传参:parametrize
@pytest.mark.parametrize("a,b", [(1, 2), (0, 3)])
def test_c(self, a, b):
assert a+b == 1
sudo python setup install
python setup install
注意:
- 以管理员身份运行该命令
pytest --version
sudo pip3 install -U pytest
或
pip3 install -U pytest
注意:
- 以管理员身份运行该命令
pytest --version
pytest.main()
pytest -s xxx/xxx.py
vim test_abc.py
import pytest # 引入pytest包
def test_a(): # test开头的测试函数
print("------->test_a")
assert 1 # 断言成功
def test_b():
print("------->test_b")
assert 0 # 断言失败
if __name__ == '__main__':
pytest.main("-s test_abc.py") # 调用pytest的main函数执行测试
执行结果:
test_abc.py
------->test_a
. # .(代表成功)
------->test_b
F # F(代表失败)
setup()
和teardown()
import pytest
class Test_ABC:
# 函数级开始
def setup(self):
print("------->setup_method")
# 函数级结束
def teardown(self):
print("------->teardown_method")
def test_a(self):
print("------->test_a")
assert 1
def test_b(self):
print("------->test_b")
if __name__ == '__main__':
pytest.main("-s test_abc.py")
执行结果:
test_abc.py
------->setup_method # 第一次 setup()
------->test_a
.
------->teardown_method # 第一次 teardown()
------->setup_method # 第二次 setup()
------->test_b
.
------->teardown_method # 第二次 teardown()
setup_class
和teardown_class
import pytest
class Test_ABC:
# 测试类级开始
def setup_class(self):
print("------->setup_class")
# 测试类级结束
def teardown_class(self):
print("------->teardown_class")
def test_a(self):
print("------->test_a")
assert 1
def test_b(self):
print("------->test_b")
if __name__ == '__main__':
pytest.main("-s test_abc.py")
执行结果:
test_abc.py
------->setup_class # 第一次 setup_class()
------->test_a
.
------->test_b
F
------->teardown_class # 第一次 teardown_class()
pytest的配置文件通常放在测试目录下,名称为pytest.ini,命令行运行时会使用该配置文件中的配置
GBK编码
空格分隔,可添加多个命令行参数 -所有参数均为插件包的参数
[pytest]
addopts = -s ...
当前目录下的scripts文件夹 -可自定义
[pytest]
testpaths = ./scripts
当前目录下的scripts文件夹下,以test_开头,以.py结尾的所有文件 -可自定义
[pytest]
python_files = test_*.py
当前目录下的scripts文件夹下,以test_开头,以.py结尾的所有文件中,以Test_开头的类 -可自定义
[pytest]
python_classes = Test_*
当前目录下的scripts文件夹下,以test_开头,以.py结尾的所有文件中,以Test_开头的类内,以test_开头的方法 -可自定义
[pytest]
python_functions = test_*
[pytest]
# 命令行参数
addopts = -s --reruns 1 --html=./report/test_report.html
# 测试路径
testpaths = ./scripts
# 搜索文件名
python_files = test001.py
# 搜索测试类名
python_classes = Test_*
# 搜索测试方法名
python_functions = test_*
文件路径:
Test_App/{test_abc.py,pytest.ini}
pyetst.ini配置文件内容:
有中文就用GBK编码
[pytest]
# 命令行参数
addopts = -s
# 搜索文件名
python_files = test_*.py
# 搜索的类名
python_classes = Test_*
# 搜索的函数名
python_functions = test_*
通过命令行方式,生成xml/html格式的测试报告,存储于用户指定路径
插件名称:pytest-html
python setup.py install
pip3 install pytest-html
pip3 install -U pytest-html
pytest --html=用户路径/report.html
import pytest
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
def test_a(self):
print("------->test_a")
assert 1
def test_b(self):
print("------->test_b")
assert 0 # 断言失败
提示:运行方式
- 修改Test_App/pytest.ini文件,添加报告参数
addopts = -s --html=./report.html
参数 说明 -s 输出程序运行信息 --html=./report.html
在当前目录下生成report.html文件 若要生成xml文件,可将
--html=./report.html
改成--html=./report.xml
- 命令行运行
cd Test_App
pytest
- 执行结果
在当前目录会生成assets
文件夹和report.html
文件
函数修饰符的方式标记被测试函数执行的顺序
插件名称:pytest-ordering
python setup.py install
pip3 install pytest-ordering
pip3 install -U pytest-ordering
@pytest.mark.run(order=x)
默认情况下,pytest是根据测试方法名由小到大执行的,可以通过第三方插件包改变其运行顺序
eg:
第一种:默认执行方式
import pytest
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
def test_a(self):
print("------->test_a")
assert 1
def test_b(self):
print("------->test_b")
assert 0
if __name__ == '__main__':
pytest.main("-s test_abc.py")
结果:
test_abc.py
------->setup_class
------->test_a # 默认第一个运行
.
------->test_b # 默认第二个运行
F
------->teardown_class
第二种:
import pytest
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
@pytest.mark.run(order=2)
def test_a(self):
print("------->test_a")
assert 1
@pytest.mark.run(order=1)
def test_b(self):
print("------->test_b")
assert 0
if __name__ == '__main__':
pytest.main("-s test_abc.py")
结果:
test_abc.py
------->setup_class
------->test_b # order=1 优先运行
F
------->test_a # order=2 晚于 order=1 运行
.
------->teardown_class
通过命令行方式,控制失败函数的重试次数
插件名称:pytest-rerunfailures
python setup.py install
pip3 install pytest-rerunfailures
pip3 install -U pytest-rerunfailures
pytest --reruns n
eg:
import pytest
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
def test_a(self):
print("------->test_a")
assert 1
def test_b(self):
print("------->test_b")
assert 0 # 断言失败
addopts = -s --reruns 2 --html=./report.html
pytest
fixture修饰器来标记固定的工厂函数,在其他函数、模块、类或整个工程调用它时,会被激活并优先执行,通常会被用于完成预置处理和重复操作
conftest.py
文件中,被fixure标记的函数可作为全局变量fixture(scope="function", params=None, autouse=False, ids=None, name=None)
常用参数 | 说明 |
---|---|
scope | 被标记方法的作用域 |
function |
default,作用于每个测试方法,每个test都运行一次 |
class |
作用于整个类,每个class的所有test只运行一次 |
module |
作用于整个模块,每个module的所有test只运行一次 |
session |
作用于整个session(慎用),每个session只运行一次 |
params | (list类型)提供参数数据,供调用标记方法的函数使用 |
autouse | 是否自动运行,默认为False不运行,设置为True自动运行 |
eg:
@pytest.fixture()
import pytest
class Test_ABC:
@pytest.fixture()
def before(self):
print("------->before")
def test_a(self,before): # ?? test_a方法传入了被fixture标识的函数,已变量的形式
print("------->test_a")
assert 1
if __name__ == '__main__':
pytest.main("-s test_abc.py")
执行结果:
test_abc.py
------->before # 发现before会优先于测试函数运行
------->test_a
.
@pytest.fixture()
@pytest.mark.usefixtures("before")
import pytest
@pytest.fixture() # fixture标记的函数可以应用于测试类外部
def before():
print("------->before")
@pytest.mark.usefixtures("before")
class Test_ABC:
def setup(self):
print("------->setup")
def test_a(self):
print("------->test_a")
assert 1
if __name__ == '__main__':
pytest.main("-s test_abc.py")
执行结果:
test_abc.py
------->before # 发现before会优先于测试类运行
------->setup
------->test_a
.
@pytest.fixture(autouse=True) # 设置为默认运行
import pytest
@pytest.fixture(autouse=True) # 设置为默认运行
def before():
print("------->before")
class Test_ABC:
def setup(self):
print("------->setup")
def test_a(self):
print("------->test_a")
assert 1
if __name__ == '__main__':
pytest.main("-s test_abc.py")
执行结果:
test_abc.py
------->before # 发现before自动优先于测试类运行
------->setup
------->test_a
.
@pytest.fixture(scope=‘function‘,autouse=True) # 作用域设置为function,自动运行
import pytest
@pytest.fixture(scope='function',autouse=True) # 作用域设置为function,自动运行
def before():
print("------->before")
class Test_ABC:
def setup(self):
print("------->setup")
def test_a(self):
print("------->test_a")
assert 1
def test_b(self):
print("------->test_b")
assert 1
if __name__ == '__main__':
pytest.main("-s test_abc.py")
执行结果:
test_abc.py
------->before # 运行第一次
------->setup
------->test_a
.------->before # 运行第二次
------->setup
------->test_b
.
@pytest.fixture(scope=‘class‘,autouse=True) # 作用域设置为class,自动运行
import pytest
@pytest.fixture(scope='class',autouse=True) # 作用域设置为class,自动运行
def before():
print("------->before")
class Test_ABC:
def setup(self):
print("------->setup")
def test_a(self):
print("------->test_a")
assert 1
def test_b(self):
print("------->test_b")
assert 1
if __name__ == '__main__':
pytest.main("-s test_abc.py")
执行结果:
test_abc.py
------->before # 发现只运行一次
------->setup
------->test_a
.
------->setup
------->test_b
.
第一种:@pytest.fixture()
import pytest
@pytest.fixture()
def need_data():
return 2 # 返回数字2
class Test_ABC:
def test_a(self,need_data):
print("------->test_a")
assert need_data != 3 # 拿到返回值做一次断言
if __name__ == '__main__':
pytest.main("-s test_abc.py")
执行结果:
test_abc.py
------->test_a
.
第二种:
@pytest.fixture(params=[1, 2, 3])
request
request.param
- 运行三次
import pytest
@pytest.fixture(params=[1, 2, 3])
def need_data(request): # 传入参数request系统封装参数
return request.param # 取列表中单个值,默认的取值方式
class Test_ABC:
def test_a(self,need_data):
print("------->test_a")
assert need_data != 3 # 断言need_data不等于3
if __name__ == '__main__':
pytest.main("-s test_abc.py")
执行结果:
# 可以发现结果运行了三次
test_abc.py
1
------->test_a
.
2
------->test_a
.
3
------->test_a
F
根据特定的条件,不执行标识的测试函数
skipif(condition, reason=None)
参数 | 说明 |
---|---|
condition |
跳过的条件,必传参数 |
reason |
标注原因,必传参数 |
@pytest.mark.skipif(condition, reason="xxx")
eg:
import pytest
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
def test_a(self):
print("------->test_a")
assert 1
@pytest.mark.skipif(condition=2>1,reason = "跳过该函数") # 跳过测试函数test_b
def test_b(self):
print("------->test_b")
assert 0
执行结果:
test_abc.py
------->setup_class
------->test_a #只执行了函数test_a
.
------->teardown_class
s # 跳过函数
标记测试函数为失败函数
xfail(condition=None, reason=None, raises=None, run=True, strict=False)
常用参数 | 名称 |
---|---|
condition |
预期失败的条件,必传参数 |
reason |
失败的原因,必传参数 |
@pytest.mark.xfail(condition, reason="xx")
eg:
import pytest
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
def test_a(self):
print("------->test_a")
assert 1
@pytest.mark.xfail(2 > 1, reason="标注为预期失败") # 标记为预期失败函数test_b
def test_b(self):
print("------->test_b")
assert 0
执行结果:
test_abc.py
------->setup_class
------->test_a
.
------->test_b
------->teardown_class
x # 失败标记
方便测试函数对测试属于的获取
parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)
常用参数 | 说明 |
---|---|
argnames |
参数名 |
argvalues |
参数对应值,类型必须为list |
当参数是一个值时,格式为
[value]
当参数个数大于一个时,格式为
[(param_value1,param_value2.....),(param_value1,param_value2.....)]
@pytest.mark.parametrize(argnames,argvalues)
eg:
import pytest
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
@pytest.mark.parametrize("a",[3,6]) # a参数被赋予两个值,函数会运行两遍
def test_a(self,a): # 参数必须和parametrize里面的参数一致
print("test data:a=%d"%a)
assert a%3 == 0
执行结果:
test_abc.py
------->setup_class
test data:a=3 # 运行第一次取值a=3
.
test data:a=6 # 运行第二次取值a=6
.
------->teardown_class
import pytest
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
@pytest.mark.parametrize("a,b",[(1,2),(0,3)]) # 参数a,b均被赋予两个值,函数会运行两遍
def test_a(self,a,b): # 参数必须和parametrize里面的参数一致
print("test data:a=%d,b=%d"%(a,b))
assert a+b == 3
执行结果:
test_abc.py
------->setup_class
test data:a=1,b=2 # 运行第一次取值 a=1,b=2
.
test data:a=0,b=3 # 运行第二次取值 a=0,b=3
.
------->teardown_class
import pytest
def return_test_data():
return [(1,2),(0,3)]
class Test_ABC:
def setup_class(self):
print("------->setup_class")
def teardown_class(self):
print("------->teardown_class")
@pytest.mark.parametrize("a,b",return_test_data()) # 使用函数返回值的形式传入参数值
def test_a(self,a,b):
print("test data:a=%d,b=%d"%(a,b))
assert a+b == 3
执行结果:
test_abc.py
------->setup_class
test data:a=1,b=2 # 运行第一次取值 a=1,b=2
.
test data:a=0,b=3 # 运行第二次取值 a=0,b=3
.
------->teardown_class
更新中......
原文:https://www.cnblogs.com/ricsy/p/11581703.html