二、pytest测试框架基础使用
pytest-xdist 测试用例分布式执行。多CPU分发。
pytest-ordering 用于改变测试用例的执行顺序(从上到下)
pytest-rerunfailures 用例失败后重跑
pytest-html (生成html格式的自动化测试报告)
allure-pytest 用于生成美观的测试报告。放到requirements.txt中,通过pip install -r requirements.txt
1.模块名必须以test_开头或者_test结尾 --> test_login.py
2.测试类必须以Test开头,并且不能有init方法。 --> TestLogin
3.测试方法必须以test开头 --> test_login
# interface_case/test_login.py def test_login(): print("测试接口登录函数") class TestLogin: def test_login(self): print("测试接口登录类")# interface_case/test_logout.py class TestLogout: def test_logout(self): print("测试接口注销类")# web_case/test_login.py class TestLogin: def test_login_01(self): print("测试WEB登录类01") def test_login_02(self): print("测试WEB登录类02") def test_login_03(self): print("测试WEB登录类03") def test_login_04(self): print("测试WEB登录类04")# web_case/test_logout.py class TestLogout: def test_logout(self): print("测试WEB注销类")# all.py import pytest if __name__ == '__main__': pytest.main()
(1)运行所有:pytest.main() (2)指定模块:pytest.main(['-vs','test_login.py']) (3)指定目录:pytest.main(['-vs','./interface_testcase']) (4)通过nodeid指定用例运行:nodeid由模块名,分隔符,类名,方法名,函数名组 成。 pytest.main(['-vs','./interface_testcase/test_interface.py::test_04_func']) pytest.main(['- vs','./interface_testcase/test_interface.py::TestInterface::test_03_zhiliao']) 参数详解: -s:表示输出调试信息,包括print打印的信息 -v:显示更详细的信息 -vs:这两个参数一起用 -n:支持多线程或者分布式运行测试用例。 -n 后面的数字是几,就代表几个线程 如:pytest -vs ./testcase/test_login.py -n 2 --reruns NUM:失败用例重跑 -x:表示只要要一个用例报错,那么测试停止。 --maxfail=2 出现两个用例失败就停止。 -k:根据测试用例的部分字符串指定测试用例。 如:pytest -vs ./testcase -k "ao" --html ./report/report.html:生成html的测试报告。
pytest.main()
pytest.main(['-vs','test_login.py'])
pytest.main(['-vs','./interface_testcase'])
pytest.main(["-vs", "./interface_testcase/test_login.py::test_login"])
pytest.main(["-vs", "./web_testcase/test_login.py", "-n =2"]) pytest.main(["-vs", "./web_testcase/test_login.py", "-n 2"])# web_case/test_login.py import time import pytest class TestLogin: def test_login_01(self): time.sleep(3) print("测试WEB登录类01") def test_login_02(self): time.sleep(3) print("测试WEB登录类02") def test_login_03(self): time.sleep(3) print("测试WEB登录类03") def test_login_04(self): time.sleep(3) print("测试WEB登录类04")
开启2个线程,可以看到运行的时间从 12.04s -> 6.72s, 时间缩短了一半
pytest.main(["-vs", "./web_testcase/test_login.py", "--reruns=2"])# web_case/test_login.py import pytest class TestLogin: def test_login_01(self): print("测试WEB登录类01") def test_login_02(self): print("测试WEB登录类02") assert 1 == 2 def test_login_03(self): print("测试WEB登录类03") def test_login_04(self): print("测试WEB登录类04")
pytest.main(["-vs", "./web_testcase/test_login.py", "-x"])
3.2 命令行模式(在pycharm的Terminal中运行)
3.2.1 运行所有: pytest
pytest
pytest -vs web_testcase/test_login.py
pytest -vs ./interface_testcase
pytest -vs ./interface_testcase/test_login.py::test_login
pytest -vs ./testcase/test_login.py -n 2# web_case/test_login.py import time import pytest class TestLogin: def test_login_01(self): time.sleep(3) print("测试WEB登录类01") def test_login_02(self): time.sleep(3) print("测试WEB登录类02") def test_login_03(self): time.sleep(3) print("测试WEB登录类03") def test_login_04(self): time.sleep(3) print("测试WEB登录类04")
pytest -vs ./web_testcase/test_login.py --reruns 2
pytest -vs ./web_testcase/test_login.py -x
1. pytest.ini 是pytest单元测试框架的核心配置文件
2. 一般放置在项目的根目录
3. 编码格式必须是 ASCI格式, 可以使用notepad++修改格式
4. 文件的作用可以改变pytest的默认规则。
5. 运行的规则,不管是主函数的模式,还是命令行的模式,都会读取这个配置文件[pytest] ;;命令行的参数,用空格分隔 addopts = -vs ;;测试用例的路径 testpaths = ./web_testcase ;;模块名的规则 python_files = test*.py ;;类名的规则 python_classes = Test* ;;方法名的规则 python_functions = test [注意]: 中文需要删除,放在此处用于阅读方便直接pytest之后,如果没有pytest.ini文件,那么就会运行所有的用例,但是存在pytest.ini文件,并且文件指定了目录为 web_testcase,所以只会执行web_testcase下的用例。
并且如果当 python_files 为其他文件名的py文件时候,就会执行指定对应的文件名开头的文件的用例,同理类名和函数名也一个道理
# unittest:ascII的大小来绝对的执行的顺序 # pytest:默认从上到下 # 改变默认的执行顺序:使用mark标记。 @pytest.mark.run(order=3)import pytest class TestLogin: def test_login_06(self): print("测试WEB登录类06") def test_login_04(self): print("测试WEB登录类04") def test_login_07(self): print("测试WEB登录类07") def test_login_03(self): print("测试WEB登录类03")
# 默认情况下,从上往下依次执行,如果想要按照指定的过程来执行用例,需要使用装饰器来修改执行顺序 # @pytest.mark.run(order=3) import pytest class TestLogin: def test_login_06(self): print("测试WEB登录类06") @pytest.mark.run(order=1) def test_login_04(self): print("测试WEB登录类04") def test_login_07(self): print("测试WEB登录类07") @pytest.mark.run(order=2) def test_login_03(self): print("测试WEB登录类03")
# 注意: 当只存在一个标记的时候,不管标记的顺序是几,都按照顺序为1 执行,剩下的按照从上往下执行 import pytest class TestLogin: def test_login_06(self): print("测试WEB登录类06") def test_login_04(self): print("测试WEB登录类04") def test_login_07(self): print("测试WEB登录类07") @pytest.mark.run(order=2) def test_login_03(self): print("测试WEB登录类03")
pytest -m smoke pytest -m "smoke or usermanage";;pytest.ini markers将用例进行分类,最好要有,不然会有警告出现 [pytest] addopts = -vs testpaths = ./ python_files = test*.py python_classes = Test* python_functions = test markers = smoke:冒烟模块 usermanage:用户管理模块 productmanage:商品管理模块# interface_testcase/test_logout.py import pytest class TestLogout: @pytest.mark.smoke def test_logout(self): print("测试接口注销类")# web_testcase/test_login.py import pytest class TestLogin: def test_login_06(self): print("测试WEB登录类06") @pytest.mark.smoke def test_login_04(self): print("测试WEB登录类04") @pytest.mark.usermanage def test_login_07(self): print("测试WEB登录类07") @pytest.mark.smoke def test_login_03(self): print("测试WEB登录类03")
;; 可以直接在 pytest.ini 文件中进行分组 [pytest] addopts = -vs -m smoke testpaths = ./web_testcase/test_login.py python_files = test*.py python_classes = Test* python_functions = test markers = smoke:冒烟模块 usermanage:用户管理模块 productmanage:商品管理模块
# (1)无条件跳过 @pytest.mark.skip(reason="薇薇太漂亮") # (2)有条件跳过 @pytest.mark.skipif(age>=18,reason='已成年')[pytest] addopts = -vs testpaths = ./web_testcase/test_login.py python_files = test*.py python_classes = Test* python_functions = test markers = smoke:冒烟模块 usermanage:用户管理模块 productmanage:商品管理模块# web_testcase/test_login.py import pytest class TestLogin: age = 18 def test_login_06(self): print("测试WEB登录类06") @pytest.mark.smoke @pytest.mark.skipif(age=18, reason="成年") def test_login_04(self): print("测试WEB登录类04") @pytest.mark.usermanage @pytest.mark.skip(reason="薇薇太漂亮") def test_login_07(self): print("测试WEB登录类07") @pytest.mark.smoke def test_login_03(self): print("测试WEB登录类03")
--html ./report_html.html[pytest] addopts = -vs --html ./report_html.html testpaths = ./web_testcase/test_login.py python_files = test*.py python_classes = Test* python_functions = test markers = smoke:冒烟模块 usermanage:用户管理模块 productmanage:商品管理模块执行结束,会生成 report_html.html