pytest 6.0.2
一、Pytest运行方式
测试类主函数模式
import pytest
if __name__ == "__main__":
pytest.main()
#自动搜寻所有目录下的适合文件并执行
pytest.main(['./scripts/test_01.py','./scripts/test_02.py'])
#指定测试文件
命令行运行
pytest
#自动搜寻所有目录下的适合文件并执行
pytest ./scripts/test_01.py
#指定文件执行
二、pytest.init
pytest.ini 可以修改 pytest 的默认行为
注意: pytest.ini 不能使用任何中文符号,包括汉字、空格、引号、冒号等等;
[pytest]
addopts = --alluredir=reports
#更改默认命令行参数
testpaths = test_path
#指定不需要测试目录
norecursedirs = .* build dist CVS _darcs {arch} *.egg venv src
#指定 pytest 忽略某些目录
python_files = test_* *_test check_*
python_classes = Test* Check*
python_functions = test_* check_*
#更改测试用例收集规则:
#pytest 默认的用例收集规则:
#测试模块必须以 test_ 开头或以 _test 结尾;
#测试类必须以 Test 开头,且不能有 __init__() ;
#测试方法必须以 test_ 开头;
xfail_strict = true
#禁用 XPASS 将标记为 @pytest.mark.xfail 但实际通过的测试用例报告为失败
三、Pytest的setup和teardown函数
函数级别setup()/teardown()
运行于测试方法的始末,即:运行一次测试函数会运行一次setup和teardown
import pytest
class Test_01(object):
def setup():
print('setup')
def teardown():
print('teardown')
类级别setup_class()/teardown_class()
运行于测试类的始末,即:在一个测试内只运行一次setup_class和teardown_class,不关心测试类内有多少个测试函数
import pytest
class Test_01(object):
def setup_class():
print('setup_class')
def teardown_class():
print('teardown_class')
四、Pytest fixture
fixture修饰器来标记固定的工厂函数,在其他函数,模块,类或整个工程调用它时会被激活并优先执行,通常会被用于完成预置处理和重复操作
#简单例子
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断言
assert 1
assert 0
assert a == b
assert a in b
assert a != b
六、Pytest参数化
在 pytest 中,我们有更好的解决方法,就是参数化测试,即每组参数都独立执行一次测试。使用的工具就是 pytest.mark.parametrize(argnames, argvalues)
#单个参数时
@pytest.mark.parametrize('passwd',['123456','abcdefdfs','as52345fasdf4'])
def test_passwd_length(passwd):
assert len(passwd) >= 8
#多个参数时
@pytest.mark.parametrize('user, passwd',[('jack', 'abcdefgh'),('tom', 'a123456a')])
def test_passwd_md5(user, passwd):
db = {
'jack': 'e8dc4081b13434b45189a720b77b6818',
'tom': '1702a132e769a623c1adb78353fc9503'
}
import hashlib
assert hashlib.md5(passwd.encode()).hexdigest() == db[user]
七、Pytest跳过测试
Pytest 使用特定的标记 pytest.mark.skip
跳过测试
Pytest 还支持使用 pytest.mark.skipif
为测试函数指定被忽略的条件
@pytest.mark.skip()
def test_A():
pass
@pytest.mark.skip(reason="xxx")
def test_B():
pass
方法:
skipif(condition, reason=None)
参数:
condition:跳过的条件,必传参数
reason:标注原因,必传参数
使用方法:
@pytest.mark.skipif(condition, reason="xxx")
@pytest.mark.skipif(condition,reason='XXX')
def test_A():
pass
八、Python预见的错误
如果我们事先知道测试函数会执行失败,但又不想直接跳过,而是希望显示的提示。
Pytest 使用 pytest.mark.xfail
实现预见错误功能:
@pytest.mark.xfail(condition,reason='XXX')
def test_A():
assert 1 == 1
九、Pytest捕获异常
在测试过程中,经常需要测试是否如期抛出预期的异常,以确定异常处理模块生效。在 pytest 中使用 pytest.raises()
进行异常捕获:
import pytest
def test_raises():
with pytest.raises(TypeError) as e:
connect('localhost', '6379')
exec_msg = e.value.args[0]
assert exec_msg == 'port type must be int'