一、用例设计规则
(1)文件名以test_*.py文件和*_test.py
(2)以test_开头的函数
(3)以Test开头的类
(4)以test_开头的方法
(5)所有的包pakege必须要有__init__.py文件
二、执行用例的规则
(1)执行目录下的所有用例
pytest 文件名/
(2)执行某个py文件下的用例
pytest 脚本名称.py
(3)执行某个py文件下的某个用例
1)pytest 脚本名称.py::类名::方法名 #有类名
python test_mod.py::TestClass::test_method
2)pytest 脚本名称.py::方法名 #无类名
pytest test_mod.py::test_method
(4)执行过程中遇到错误停止
pytest -x 脚本名称.py
(5)错误个数限制
pytest --maxfail==1 #当用例错误达到1时停止
三、用例中的setup和teardown
模块级(setup_module/teardown_module)开始于模块始末,全局的
函数级(setup_function/teardown_function)只对函数用例生效(不在类中)
类级(setup_class/teardown_class)只在类中前后运行一次(在类中)
方法级(setup_method/teardown_method)开始于方法始末(在类中)
类里面的(setup/teardown)运行在调用方法的前后
#等级划分:setup_module/teardown_module > setup_class/teardown_class > setup_method/teardown_method > setup/teardown
#setup_function不在类中,互不干扰
四、pytest-html生成报告
格式:pytest 脚本名称.py --html=自定义路径/报告名称.html ----self-contained-html
说明:若不加脚本名称,则会将当前目录下的所有用例都生成在一张报告中,--self-contained-html若不加,分享报告后,报告的样式会丢失,不利于观看,故加上这个可以将样式和页面合并,便于分享观看
五、失败重跑
(1)pip安装pytest-rerunffailures插件
(2)生成报告时添加--reruns n 参数
pytest test_class.py --reruns 1 --html=report.html --self-contained-html #此时n=1,代表重跑一次
六、pytest参数化parammetrize
(1)pytest.mark.parametrize装饰器可以实现测试用例参数化,跟unittest的ddt模块类似
#参数化.py #!/usr/bin/python # -*- coding: utf-8 -*- import pytest @pytest.mark.parametrize('x,y,z',[('2+3',5,1),('5-3',2,2),('3*3',9,3),('6/2',3,4)]) def test_count(x,y,z): print('开始第%s计算'%z) assert eval(x)==y if __name__=='__main__': pytest.main(['-s','参数化.py'])
运行结果
============================= test session starts ============================= platform win32 -- Python 3.7.1, pytest-6.1.1, py-1.9.0, pluggy-0.13.1 rootdir: F:xwexamplepytestcase plugins: html-2.1.1, metadata-1.10.0, rerunfailures-9.1.1 collected 4 items 参数化.py 开始第1计算 .开始第2计算 .开始第3计算 .开始第4计算 . ============================== 4 passed in 0.03s ==============================
(2)它也可以标记单个测试实例在参数化,例如使用内置的mark.xfail
#参数化.py
#!/usr/bin/python # -*- coding: utf-8 -*- import pytest @pytest.mark.parametrize('x,y,z',[('2+3',5,1),('5-3',2,2),('3*3',9,3),('6/2',3,4),pytest.param('4+6',11,5,marks=pytest.mark.xfail),]) def test_count(x,y,z): print('开始第%s计算'%z) assert eval(x)==y if __name__=='__main__': pytest.main(['-s','参数化.py'])
运行结果
C:UsersxwxxhAppDataLocalProgramsPythonPython37-32python.exe F:/xw/example/pytest/case/参数化.py ============================= test session starts ============================= platform win32 -- Python 3.7.1, pytest-6.1.1, py-1.9.0, pluggy-0.13.1 rootdir: F:xwexamplepytestcase plugins: html-2.1.1, metadata-1.10.0, rerunfailures-9.1.1 collected 5 items 参数化.py 开始第1计算 .开始第2计算 .开始第3计算 .开始第4计算 .开始第5计算 x ======================== 4 passed, 1 xfailed in 0.23s ========================= Process finished with exit code 0
(3)参数组合
若要获得多个参数化参数的所有组合,可以堆叠参数化装饰器
#参数组合.py
#!/usr/bin/python # -*- coding: utf-8 -*- import pytest @pytest.mark.parametrize('x',[1,2]) @pytest.mark.parametrize('y',[4,5]) def test_parm_group(x,y): print("%s*%s=%s"%(x,y,x*y)) if __name__=='__main__': pytest.main(['-s','参数组合.py'])
运行结果
C:UsersxwxxhAppDataLocalProgramsPythonPython37-32python.exe F:/xw/example/pytest/case/参数组合.py ============================= test session starts ============================= platform win32 -- Python 3.7.1, pytest-6.1.1, py-1.9.0, pluggy-0.13.1 rootdir: F:xwexamplepytestcase plugins: html-2.1.1, metadata-1.10.0, rerunfailures-9.1.1 collected 4 items 参数组合.py 1*4=4 .2*4=8 .1*5=5 .2*5=10 . ============================== 4 passed in 0.03s ============================== Process finished with exit code 0
七、skip跳过用例
1、skip强制跳过
pytest.mark.skip可以标记无法在某平台上运行的测试功能,或者希望失败的测试功能,意味着只有满足某些要求时才能测试通过,否则pytest应该跳过
(1)跳过测试函数的最简单的方法就是使用跳过装饰器标记它,可以传递一个原因
#skip.py
#!/usr/bin/python # -*- coding: utf-8 -*- import pytest @pytest.mark.skip('不运行') def test_01(): assert 2==3 def test_02(): assert 2+8==10 def test_03(): assert 3*3==9 if __name__=="__main__": pytest.main(['-q','skip.py'])
运行结果
C:UsersxwxxhAppDataLocalProgramsPythonPython37-32python.exe F:/xw/example/pytest/case/skip.py s.. [100%] 2 passed, 1 skipped in 0.02s Process finished with exit code 0
2、skipif有条件的跳过
如果希望有条件地跳过某些内容,则可以使用skipif代替,如下:条件为2>3,为假,所以要正常运行,若为真则跳过
#skipif.py
#!/usr/bin/python # -*- coding: utf-8 -*- import pytest @pytest.mark.skipif('2>3') def test_01(): assert 2==3 def test_02(): assert 2+8==10 def test_03(): assert 3*3==9 if __name__=="__main__": pytest.main(['-s','skipif.py'])
运行结果
skipif.py F.. ================================== FAILURES =================================== ___________________________________ test_01 ___________________________________ @pytest.mark.skipif('2>3') def test_01(): > assert 2==3 E assert 2 == 3 skipif.py:6: AssertionError =========================== short test summary info =========================== FAILED skipif.py::test_01 - assert 2 == 3 ========================= 1 failed, 2 passed in 0.14s ========================= Process finished with exit code 0