- 4.编写测试函数
- 4.1 使用assert声明
- 4.2 预期异常
- 4.3 测试函数标记
- 4.4 跳过测试
- 4.5 标记预期失败的测试
- 4.6 运行测试子集
- 4.6.1 单个目录
- 4.6.2 单个测试文件/模块
- 4.6.3 单个测试函数
- 4.6.4 单个测试类
- 4.6.5 单个测试类中的测试方法
- 4.6.6 用测试名划分测试集合
- 4.7 参数化测试
- 4.7.1 参数化方式
- 4.7.2 添加额外参数ids
4.编写测试函数
4.1 使用assert声明
使用pytest编写测试时,若需要传递测试失败信息,可以直接使用Pytho自带的assert关键字。pytest与其他测试框架如unittest的区别如下所示:
pytest | unittest |
---|---|
assert something | assertTrue(something) |
assert a==b | assertEqual(a,b) |
assert a<=b | assertLessEqual(a,b) |
... | ... |
pytest中assert主要有以下特点
- 1.assert 后面可以添加任何表达式,若表达式的结果通过bool转换结果为True,则代表测试通过
- 2.pytest 可以重写assert关键字。pytest可截断对原生assert的调用,替换为pytest定义的assert,从而提供更多的详细失败信息
import pytest
def addItemToList(item):
tmpList=[]
tmpList.append(item)
return tmpList
def test_addItemToList():
t1=addItemToList("a")
t2=addItemToList("b")
assert t1==t2
运行结果如下所示:
PS C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02> pytest .\test_01.py
=============================test session starts ====================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 1 item
test_01.py F [100%]
================================== FAILURES ======================================
___________________________test_addItemToList ____________________________________
def test_addItemToList():
t1=addItemToList("a")
t2=addItemToList("b")
> assert t1==t2
E AssertionError: assert ['a'] == ['b']
E At index 0 diff: 'a' != 'b'
E Use -v to get the full diff
test_01.py:12: AssertionError
=================================== short test summary info =========================
FAILED test_01.py::test_addItemToList - AssertionError: assert ['a'] == ['b']
====================================1 failed in 0.29s ==============================
在上面的运行结果中,失败的测试用例在行首会有一个 > 来标识。以E开头的行是pytest提供的额外判定信息,用于帮助了解异常的具体信息。
4.2 预期异常
在Python后来的版本,增加了函数参数注解功能,即在定义一个参数后,后面可直接声明参数的数据类型,方便其他人员知道如何调用这个函数,如下所示:
def add(x:int,y:int)->int:
return x+y
为确保像这样的函数,在发生类型错误时,可以抛出异常,可以使用with pytest.raises(< expected exception >),如下所示:
def add(x:int,y:int)->int:
if not isinstance(x,(int,)) or not isinstance(y,(int,)):
raise TypeError("args must be int")
else:
return x+y
def test_add():
with pytest.raises(TypeError):
add("1","2")
运行结果如下所示:
PS C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02> pytest .\test_01.py
==============================test session starts ================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 1 item
test_01.py . [100%]
=================================1 passed in 0.08s ===============================
测试用例中test_add()有with pytest.raises(TypeError)声明,则意味着无论with中的内容是什么,都至少会产生TypeError异常。如果测试通过,则说明确实发生了预期的TypeError异常,如果抛出的是其他类型的异常,则与预期不一致,测试失败。
在上面的测试用例中,仅检验了传参数据的类型异常,也可以检查值异常,比如在检验一个参数的数据类型之后,也可以再检验其内容,为校验异常消息是否符合预期,可以增加as exInfo语句得到异常消息的值,再进行校验,示例如下所示:
def add(x:int,y:int,operator:str)->int:
if not isinstance(x,(int,)) or not isinstance(y,(int,)) or not isinstance(operator,(str,)):
raise TypeError("args must be int")
if operator=="+":
return x + y
elif operator=="-":
return x - y
else:
raise ValueError("operator must be '+' or '-' ")
def test_add():
with pytest.raises(ValueError) as exInfo:
add(1,2,"*")
exInfo=exInfo.value.args[0]
expectInfo="operator must be '+' or '-' "
assert expectInfo== exInfo
运行结果如下所示:
PS C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02> pytest .\test_01.py
=============================test session starts ============================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 1 item
test_01.py . [100%]
============================1 passed in 0.13s ================================
4.3 测试函数标记
pytest提供了标记机制,允许使用marker对测试函数进行标记,一个测试函数可以有多个marker,一个marker也可以用来标记多个测试函数。
对测试函数进行标记,通常使用的场景为冒烟测试,一般情况下冒烟测试不需要跑全部的测试用例,只需要选择关键的点进行测试,这个时候只跑被标记为冒烟测试的测试用例,会省很多时间。
示例如下所示:
import pytest
def add(x:int,y:int,operator:str)->int:
if not isinstance(x,(int,)) or not isinstance(y,(int,)) or not isinstance(operator,(str,)):
raise TypeError("args must be int")
if operator=="+":
return x + y
elif operator=="-":
return x - y
else:
raise ValueError("operator must be '+' or '-' ")
@pytest.mark.testValueError
@pytest.mark.smoke
def test_addValueError():
with pytest.raises(ValueError) as exInfo:
add(1,2,"*")
exInfo=exInfo.value.args[0]
expectInfo="operator must be '+' or '-' "
assert expectInfo== exInfo
@pytest.mark.testTypeErrorTest
@pytest.mark.smoke
def test_addTypeError():
with pytest.raises(TypeError):
add("1","2","+")
现在只需要在命令中指定-m markerName,就可以运行指定的测试用例,如下所示:
PS C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02> pytest -m smoke .\test_02.py
=========================test session starts ===============================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 2 items
test_02.py .. [100%]
============================ 2 passed, 4 warnings in 0.12s ====================================
PS C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02> pytest -m testValueError .\test_02.py
==============================test session starts ==============================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 2 items / 1 deselected / 1 selected
test_02.py . [100%]
========================= 1 passed, 1 deselected, 4 warnings in 0.04s ===========================
针对上面示例,可以得出以下结论
1.pytest.mark.markName:markName由用户自行定义,并非pytest内置
2.-m:后面也可以使用表达式,可以在标记之间添加and、or、not等关键字,如下所示:
pytest -m "testValueError and testTypeError" .\test_02.py
pytest -m "testValueError and not testTypeError" .\test_02.py
4.4 跳过测试
pytest内置了一些标记,如skip、skipif、xfail。其中skip、skipif允许跳过不希望运行的测试。示例如下所示:
1.要直接跳过某一个测试函数,可以使用pytest.mark.skip()装饰器即可
import pytest
def add(x:int,y:int,operator:str)->int:
if not isinstance(x,(int,)) or not isinstance(y,(int,)) or not isinstance(operator,(str,)):
raise TypeError("args must be int")
if operator=="+":
return x + y
elif operator=="-":
return x - y
else:
raise ValueError("operator must be '+' or '-' ")
@pytest.mark.testValueError
@pytest.mark.smoke
def test_addValueError():
with pytest.raises(ValueError) as exInfo:
add(1,2,"*")
exInfo=exInfo.value.args[0]
expectInfo="operator must be '+' or '-' "
assert expectInfo== exInfo
@pytest.mark.skip(reason="skip this case")
def test_addTypeError():
with pytest.raises(TypeError):
add("1","2","+")
运行结果如下所示:
PS C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02> pytest -v .\test_02.py
==========================test session starts =================================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 2 items
test_02.py::test_addValueError PASSED [ 50%]
test_02.py::test_addTypeError SKIPPED [100%]
2.添加跳过的原因和条件,可以使用pytest.mark.skipif()装饰器即可
如果有一些测试,只有在满足特定条件的情况下,才被跳过,这时候则可以使用pytest.mark.skipif(),示例如下所示:
import pytest
def add(x:int,y:int,operator:str)->int:
"""this is sample case"""
if not isinstance(x,(int,)) or not isinstance(y,(int,)) or not isinstance(operator,(str,)):
raise TypeError("args must be int")
if operator=="+":
return x + y
elif operator=="-":
return x - y
else:
raise ValueError("operator must be '+' or '-' ")
@pytest.mark.testValueError
@pytest.mark.smoke
def test_addValueError():
with pytest.raises(ValueError) as exInfo:
add(1,2,"*")
exInfo=exInfo.value.args[0]
expectInfo="operator must be '+' or '-' "
assert expectInfo== exInfo
@pytest.mark.skipif(add.__doc__=="this is sample case",reason="skip this case")
def test_addTypeError():
with pytest.raises(TypeError):
add("1","2","+")
运行结果如下所示:
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 2 items
test_02.py::test_addValueError PASSED [ 50%]
test_02.py::test_addTypeError SKIPPED [100%]
尽管跳过的原因不是必须写,但还是建议在实际项目尽可能的写上,方便知道跳过的原因,如果想知道跳过的详细原因,可使用参数 -rs
PS C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02> pytest -rs -v .\test_02.py
======================test session starts ====================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 2 items
test_02.py::test_addValueError PASSED [ 50%]
test_02.py::test_addTypeError SKIPPED [100%]
==================================short test summary info =================================
SKIPPED [1] test_02.py:23: skip this case
==========================1 passed, 1 skipped, 2 warnings in 0.04s ========================
4.5 标记预期失败的测试
使用skip和skipif,在满足条件的下,会直接跳过,而不会执行。使用xfail标记,则是预期运行失败,如下所示:
import pytest
def add(x:int,y:int,operator:str)->int:
"""this is sample case"""
if not isinstance(x,(int,)) or not isinstance(y,(int,)) or not isinstance(operator,(str,)):
raise TypeError("args must be int")
if operator=="+":
return x + y
elif operator=="-":
return x - y
else:
raise ValueError("operator must be '+' or '-' ")
@pytest.mark.xfail
def test_addValueError():
with pytest.raises(ValueError) as exInfo:
add(1,2,"*")
exInfo=exInfo.value.args[0]
expectInfo="operator must be '+' or '-' "
assert expectInfo!= exInfo
@pytest.mark.xfail(add.__doc__=="this is sample case",reason="skip this case")
def test_addTypeError():
with pytest.raises(TypeError):
add("1","2","+")
运行结果如下所示:
PS C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02> pytest .\test_02.py
============================test session starts ===================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 2 items
test_02.py xX [100%]
======================= 1 xfailed, 1 xpassed in 0.19s ===============================
- x代表XFAIL,意味着expect to fail(预期失败,实际上也失败)
- X代表XPASS,意味着expect to fail but passed(预期失败,实际上成功)
对于标记为xfail,但实际运行结果为XPASS的测试,可以在pytest配置中强制指定为FAIL,在pytest.ini文件按如下修改即可:
[pytest]
xfail_strict=true
4.6 运行测试子集
前面主要介绍对测试函数进行标记及如何运行。而运行测试子集可以按目录、文件、类中的测试,还可以选择运行某一个测试用例(可能在文件中,也可以在类中)**。
4.6.1 单个目录
运行单个目录下的所有测试,以目录做为参数即可,如下所示:
pytest --tb=no .\PytestStudy\
4.6.2 单个测试文件/模块
运行单个测试文件/模块,以路径名加文件名做为参数即可,如下所示:
pytest --tb=no .\PytestStudy\Lesson02\test_01.py
4.6.3 单个测试函数
运行单个测试函数,只需要在文件名后面添加::符号和函数名即可,如下所示:
pytest .\test_02.py::test_addTypeError
4.6.4 单个测试类
测试类用于将某些相似的测试函数组合在一起,来看看以下示例:
import pytest
class Person:
_age=28
_name="Surpass"
def __init__(self,age,name):
self._name=name
self._age=age
@classmethod
def getAge(cls):
if not isinstance(cls._age,(int,)):
raise TypeError("age must be integer")
else:
return cls._age
@classmethod
def getName(cls):
if not isinstance(cls._name,(str,)):
raise TypeError("name must be string")
else:
return cls._name
class TestPerson:
def test_getAge(self):
with pytest.raises(TypeError):
Person.getAge("28")
def test_getName(self):
with pytest.raises(TypeError):
Person.getName(123)
以上测试类中的方法都是测试Person中的方法,因此可以放在一个测试类中,要运行该类,可以在文件名后面添加::符号和类名即可,与运行单个测试函数类似,如下所示:
pytest .\test_03.py::TestPerson -v
========================== test session starts ===========================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 2 items
test_03.py::TestPerson::test_getAge PASSED [ 50%]
test_03.py::TestPerson::test_getName PASSED [100%]
============================= 2 passed in 0.04s ============================================
4.6.5 单个测试类中的测试方法
如果不希望运行测试类中的所有测试方法,可以指定运行的测试方法名即,可以在文件名后面添加::类名::类中方法名即可,如下所示:
>>> pytest -v .\test_03.py::TestPerson::test_getName
=========================== test session starts ==================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 1 item
test_03.py::TestPerson::test_getName PASSED [100%]
============================= 1 passed in 0.04s ===============================
4.6.6 用测试名划分测试集合
-k选项允许用一个表达式指定需要运行的测试,表达式可以匹配测试名或其子串,表达式中也可以包含and、or、not等。
例如想运行目录中,所有文件中测试函数名包含_add的测试函数,可按如下方式进行操作:
>>> pytest -v -k _add
======================== test session starts ===============================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 5 items / 2 deselected / 3 selected
test_01.py::test_add PASSED [ 33%]
test_02.py::test_addValueError XFAIL [ 66%]
test_02.py::test_addTypeError XPASS [100%]
==================== 1 passed, 2 deselected, 1 xfailed, 1 xpassed in 0.14s ====================
4.7 参数化测试
4.7.1 参数化方式
向函数传值并校验其输出是软件测试的常用手段,但大部分情况下,仅使用一组数据是无法充分测试函数功能。参数化测试允许传递多组数据,一旦发现测试失败,pytest会及时抛出信息。
要使用参数化测试,需要使用装饰器pytest.mark.parametrize(args,argsvaules)来传递批量的参数。示例如下所示:
1.方式一
import pytest
def add(x:int,y:int)->int:
return x+y
@pytest.mark.parametrize("paras",[(1,2),(3,5),(7,8),(10,-98)])
def test_add(paras):
res=add(paras[0],paras[1])
expect=paras[0]+paras[1]
assert res==expect
运行结果如下所示:
>>> pytest -v .\test_04.py
================================================= test session starts =================================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 4 items
test_04.py::test_add[paras0] PASSED [ 25%]
test_04.py::test_add[paras1] PASSED [ 50%]
test_04.py::test_add[paras2] PASSED [ 75%]
test_04.py::test_add[paras3] PASSED [100%]
=====================4 passed in 0.10s ====================================
在parametrize()中第一个参数字符串列表(paras),第二个参数是一个值列表,pytest会轮流对每个paras做测试,并分别报告每个测试用例的结果。
parametrize()函数工作正常,那如果把paras替换为键值对形式了,能否达到同样的效果,如下所示:
2.方式二
import pytest
def add(x:int,y:int)->int:
return x+y
@pytest.mark.parametrize(("x","y"),[(1,2),(3,5),(7,8),(10,-98)])
def test_add(x,y):
res=add(x,y)
expect=x+y
assert res==expect
运行结果如下所示:
>>> pytest -v .\test_04.py
====================test session starts =================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 4 items
test_04.py::test_add[1-2] PASSED [ 25%]
test_04.py::test_add[3-5] PASSED [ 50%]
test_04.py::test_add[7-8] PASSED [ 75%]
test_04.py::test_add[10--98] PASSED [100%]
======================4 passed in 0.16s =============================
如果传入的参数具有标识性,则在输出结果中也同样具备可标识性,增强可读性。也可以使用完整的测试标识(pytest术语为node),如果标识符中包含空格,则需要使用引号。重新运行指定的测试如下所示:
>>> pytest -v test_04.py::test_add[1-2]
================================ test session starts =======================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 1 item
test_04.py::test_add[1-2] PASSED [100%]
========================== 1 passed in 0.04s ===================================
3.方式三
除了以上两种方式之外,还可以使用如下方式进行参数化,如下所示:
import pytest
def add(x:int,y:int)->int:
return x+y
paras=((1,2),(3,5),(7,8),(10,-98))
@pytest.mark.parametrize("p",paras)
def test_add(p):
res=add(p[0],p[1])
expect=p[0]+p[1]
assert res==expect
运行结果如下所示
>>> pytest -v test_04.py
================================ test session starts ======================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 4 items
test_04.py::test_add[p0] PASSED [ 25%]
test_04.py::test_add[p1] PASSED [ 50%]
test_04.py::test_add[p2] PASSED [ 75%]
test_04.py::test_add[p3] PASSED [100%]
==============================4 passed in 0.14s ======================================
4.7.2 添加额外参数ids
1.方式一
以上几种虽然可以达到参数化的目的,但可读性不太友好,为改善可读性,可以为parametrize()引入一个额外的参数ids,使列表中每个元素都被标识。ids是一个字符串列表和数据对象列表和长度一致。如下所示:
import pytest
def add(x:int,y:int)->int:
return x+y
paras=((1,2),(3,5),(7,8),(10,-98))
parasIds=[f"{x},{y}" for x,y in paras]
@pytest.mark.parametrize("p",paras,ids=parasIds)
def test_add(p):
res=add(p[0],p[1])
expect=p[0]+p[1]
assert res==expect
运行结果如下所示
>>> pytest -v test_04.py
========================= test session starts ===================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 4 items
test_04.py::test_add[1,2] PASSED [ 25%]
test_04.py::test_add[3,5] PASSED [ 50%]
test_04.py::test_add[7,8] PASSED [ 75%]
test_04.py::test_add[10,-98] PASSED 100%]
=================================== 4 passed in 0.11s ============================
parametrize()不仅适于一般的测试函数,也可以适用类,在用于类中,则数据集会被传递给该类的所有方法,如下所示:
import pytest
paras=((1,2),(3,5),(7,8),(10,-98))
parasIds=[f"{x},{y}" for x,y in paras]
class Oper:
_x=0
_y=0
def __int__(self,x,y):
self._x=x
self._y=y
@classmethod
def add(cls,x,y):
return x+y
@classmethod
def sub(cls,x,y):
return x-y
@pytest.mark.parametrize("p",paras,ids=parasIds)
class TestOper:
def test_add(self,p):
res=Oper.add(p[0],p[1])
expect=p[0]+p[1]
assert res==expect
def test_sub(self,p):
res = Oper.sub(p[0], p[1])
expect = p[0] - p[1]
assert res == expect
运行结果如下所示
>>> pytest -v test_04.py
============================= test session starts =============================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 8 items
test_04.py::TestOper::test_add[1,2] PASSED [ 12%]
test_04.py::TestOper::test_add[3,5] PASSED [ 25%]
test_04.py::TestOper::test_add[7,8] PASSED [ 37%]
test_04.py::TestOper::test_add[10,-98] PASSED [ 50%]
test_04.py::TestOper::test_sub[1,2] PASSED [ 62%]
test_04.py::TestOper::test_sub[3,5] PASSED [ 75%]
test_04.py::TestOper::test_sub[7,8] PASSED [ 87%]
test_04.py::TestOper::test_sub[10,-98] PASSED [100%]
============================ 8 passed in 0.13s ================================
2.方式二
在给@pytest.mark.parametrize()装饰器传入参数列表时,还可以在参数值中定义一个id做为标识,其语法格式如下所示:
@pytest.mark.parametrize(,id="id")
示例如下所示:
import pytest
class Oper:
_x=0
_y=0
def __int__(self,x,y):
self._x=x
self._y=y
@classmethod
def add(cls,x,y):
return x+y
@classmethod
def sub(cls,x,y):
return x-y
@pytest.mark.parametrize("p",[pytest.param((1,2),id="id-1"),pytest.param((3,5),id="id-2"),
pytest.param((7,8),id="id-3"),pytest.param((10,-98),id="id-4")])
class TestOper:
def test_add(self,p):
res=Oper.add(p[0],p[1])
expect=p[0]+p[1]
assert res==expect
def test_sub(self,p):
res = Oper.sub(p[0], p[1])
expect = p[0] - p[1]
assert res == expect
运行结果如下所示
>>> pytest -v test_04.py
==============test session starts ====================================
platform win32 -- Python 3.7.6, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 -- d:\program files\python\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\Surpass\Documents\PycharmProjects\PytestStudy\Lesson02
collected 8 items
test_04.py::TestOper::test_add[id-1] PASSED [ 12%]
test_04.py::TestOper::test_add[id-2] PASSED [ 25%]
test_04.py::TestOper::test_add[id-3] PASSED [ 37%]
test_04.py::TestOper::test_add[id-4] PASSED [ 50%]
test_04.py::TestOper::test_sub[id-1] PASSED [ 62%]
test_04.py::TestOper::test_sub[id-2] PASSED [ 75%]
test_04.py::TestOper::test_sub[id-3] PASSED [ 87%]
test_04.py::TestOper::test_sub[id-4] PASSED [100%]
=============================== 8 passed in 0.19s =============================
在id不能被参数批量生成,需要自定义时,这个方法非常适用。
原文地址:https://www.cnblogs.com/surpassme/p/13252315.html
本文同步在微信订阅号上发布,如各位小伙伴们喜欢我的文章,也可以关注我的微信订阅号:woaitest,或扫描下面的二维码添加关注: