Pytest框架的详细介绍
一、Pytest
介绍:pytest官网
## 安装
pip install pytest
二、Pytest编写规则
- 测试文件以test打头
- 测试类以Test开头,并且不能带有init方法
- 测试函数以test开头
- 断言使用基本的assert即可
三、Pytest consle参数介绍
- -v 表示显示每个函数的执行结果
- -q 表示只显示整体测试结果
- -s 用于显示测试函数中的print()输出结果
- -x --exitfirst 在出现第一个错误或者测试失败时退出
- -h 帮助
四、pycharm配置pytest
五、Pytest 示例
import pytest
class TestCase01(object):
def test01(self):
print('test01')
def test02(self):
print('test02')
class TestCase02(object):
def test03(self):
print('test03')
assert 1 == 2
def test04(self):
print('test04')
if __name__ == '__main__':
pytest.main(['-vs', 'test01.py'])
# 控制台输出
test01.py::TestCase01::test02 test02
PASSED
test01.py::TestCase02::test03 test03
FAILED
test01.py::TestCase02::test04 test04
PASSED
================================== FAILURES ===================================
______________________________ TestCase02.test03 ______________________________
self = <Cases.pytest.test01.TestCase02 object at 0x0000019179A14948>
def test03(self):
print('test03')
> assert 1 == 2
E assert 1 == 2
E -1
E +2
test01.py:12: AssertionError
========================= 1 failed, 3 passed in 0.09s =========================
Process finished with exit code 0
六、Pytest 加标记执行
mark方式
- 添加pytest.ini配置文件,如下:
pytest
markers=
do: do
undo: undo
- 用例上添加标记:@pytest.mark.do 或者 @pytest.mark.undo
import pytest
class TestCase02(object):
@pytest.mark.undo
def test03(self):
print('test03')
assert 1 == 2
@pytest.mark.do
def test04(self):
print('test04')
- 控制台输出:
(base) D:\TestSoftware\PyCharm\PyCharmProject\Jpress\Cases\pytest>pytest -m do test01.py
========================================================= test session starts =========================================================
platform win32 -- Python 3.7.4, pytest-5.2.1, py-1.8.0, pluggy-0.13.0
rootdir: D:\TestSoftware\PyCharm\PyCharmProject\Jpress\Cases\pytest, inifile: pytest.ini
plugins: allure-pytest-2.8.18, arraydiff-0.3, dependency-0.5.1, doctestplus-0.4.0, openfiles-0.4.0, remotedata-0.3.2
collected 2 items / 1 deselected / 1 selected
test01.py . [100%]
=================================================== 1 passed, 1 deselected in 0.07s ===================================================
(base) D:\TestSoftware\PyCharm\PyCharmProject\Jpress\Cases\pytest>
:: 双冒号指定执行
(base) D:\TestSoftware\PyCharm\PyCharmProject\Jpress\Cases\pytest>pytest test01.py::TestCase01
========================================================= test session starts =========================================================
platform win32 -- Python 3.7.4, pytest-5.2.1, py-1.8.0, pluggy-0.13.0
rootdir: D:\TestSoftware\PyCharm\PyCharmProject\Jpress\Cases\pytest, inifile: pytest.ini
plugins: allure-pytest-2.8.18, arraydiff-0.3, dependency-0.5.1, doctestplus-0.4.0, openfiles-0.4.0, remotedata-0.3.2
collected 2 items
test01.py .. [100%]
========================================================== 2 passed in 0.07s ==========================================================
-k 参数 模糊查询
(base) D:\TestSoftware\PyCharm\PyCharmProject\Jpress\Cases\pytest>pytest -k test test01.py
========================================================= test session starts =========================================================
platform win32 -- Python 3.7.4, pytest-5.2.1, py-1.8.0, pluggy-0.13.0
rootdir: D:\TestSoftware\PyCharm\PyCharmProject\Jpress\Cases\pytest, inifile: pytest.ini
plugins: allure-pytest-2.8.18, arraydiff-0.3, dependency-0.5.1, doctestplus-0.4.0, openfiles-0.4.0, remotedata-0.3.2
collected 4 items
test01.py ..F. [100%]
============================================================== FAILURES ===============================================================
__________________________________________________________ TestCase02.test03 __________________________________________________________
self = <Cases.pytest.test01.TestCase02 object at 0x0000023F03BD7848>
@pytest.mark.undo
def test03(self):
print('test03')
> assert 1 == 2
E assert 1 == 2
test01.py:13: AssertionError
-------------------------------------------------------- Captured stdout call ---------------------------------------------------------
test03
===================================================== 1 failed, 3 passed in 0.17s =====================================================
七、pytest的参数化处理,数组、元组、字典、还有自定义等数据
import pytest
# 数组
data = ['admin', '123']
@pytest.mark.parametrize('pwd', data)
def test01(pwd):
print(pwd)
# 元组
data2 = [
(1, 2, 3),
(4, 5, 6)
]
@pytest.mark.parametrize('a, b, c', data2)
def test02(a, b, c):
print(a, b, c)
# dic 字典
data3 = (
{
'user1': 'admin',
'pwd1': '123'
},
{
'user2': 'admin2',
'pwd2': '124'
},
{
'user3': 'admin3',
'pwd3': '125'
}
)
@pytest.mark.parametrize('dic', data3)
def test03(dic):
print(dic)
# 自定义 id做标识,当然也可以作为断言结果来判定用例执行结果
data4 = [
pytest.param(1, 2, 3, id='(a+b):pass'), # id可以自定义,只要方便理解,每个用例是干什么的
pytest.param(4, 5, 6, id='(a+b):fail') # 如果fail修改为pass,则结果都为通过
]
def test04(a,b):
return a+b
class Test04_param(object):
@pytest.mark.parametrize('a,b,expect', data4)
def test04_param_1(self, a, b, expect):
assert test04(a, b) == expect
if __name__ == '__main__':
pytest.main(['-vs', 'test02.py'])
八、pytest的fixture()实现用例之间的调用
fixture的一些使用规则:
- 在函数上添加装饰器 @pytest.fixture()
- fixture 命名的方法不以test开头,跟用例区分开,且有返回值,没有返回值默认为none
- 用例调用fixture的返回值,直接把fixture的函数名称作为变量名称
示例code:
@pytest.fixture()
def a():
print('这个是function a')
return 1
def test1(a):
print('test1')
def test2(a):
print('test2')
# 控制台输出:
rootdir: D:\TestSoftware\PyCharm\PyCharmProject\Jpress\Cases\pytest, inifile: pytest.ini
plugins: allure-pytest-2.8.18, arraydiff-0.3, dependency-0.5.1, doctestplus-0.4.0, openfiles-0.4.0, remotedata-0.3.2
collecting ... collected 1 item
pytest02.py::test2 这个是function a
PASSED [100%]test2
============================== 1 passed in 0.03s ==============================
九、pytest中的setup和teardown的使用、
模块级(setup_module/teardown_module)在模块始末调用
函数级(setup_function/teardown_function)在函数始末调用(在类外部)
类级(setup_class/teardown_class)在类的前后各调用一次(在类中)
方法级(setup_method/teardown_methond)在方法始末调用(在类中)
类里的(setup/teardown)在调用方法的前后(在类中)
# -*- coding: utf-8 -*-
def setup_module():
print("\nsetup_module,只执行一次,当有多个测试类的时候使用")
def teardown_module():
print("\nteardown_module,只执行一次,当有多个测试类的时候使用")
class TestPytest1(object):
@classmethod
def setup_class(cls):
print("\nsetup_class1,只执行一次")
@classmethod
def teardown_class(cls):
print("\nteardown_class1,只执行一次")
def setup_method(self):
print("\nsetup_method1,每个测试方法都执行一次")
def teardown_method(self):
print("teardown_method1,每个测试方法都执行一次")
def test_1(self):
print("\ntest_1,第1条测试用例")
def test_2(self):
print("\ntest_2,第2条测试用例")
class TestPytest2(object):
@classmethod
def setup_class(cls):
print("\nsetup_class2,只执行一次")
@classmethod
def teardown_class(cls):
print("\nteardown_class2,只执行一次")
def setup_method(self):
print("\nsetup_method2,每个测试方法都执行一次")
def teardown_method(self):
print("teardown_method2,每个测试方法都执行一次")
def test_3(self):
print("\ntest_3,第3条测试用例")
def test_4(self):
print("\ntest_4,第4条测试用例")
十、pytest使用allure生成测试报告
介绍:allure官网
- 安装
pip3 install allure-pytest
- 下载allure的一个可执行文件,window下载zip,之后进入xxx\allure-2.7.0\bin目录,设置环境变量
allure的用例描述
code示例
注意生成测试报告 必须在命令行执行
pytest --alluredir ./Reports test03.py
allure serve ./Reports 启动allure服务,查看报告
import pytest
import allure
@pytest.fixture(scope='session')
def login():
print('用例先登录')
@allure.step('步骤1,点击xxx')
def step_1():
print('11111')
@allure.step('步骤2,点击xxx')
def step_2():
print('22222')
@allure.feature('编辑页面')
class TestEditPage():
'''编辑页'''
@allure.story('这个是xxxx')
def test01(self,login):
'''用例描述:先登录,再执行xxx用例'''
step_1()
step_2()
print('已执行:step1,step2,第一次')
@allure.story('这个是xxxx')
def test02(self, login):
'''用例描述:先登录,再执行yyy用例'''
step_1()
step_2()
print('已执行:step1,step2,第二次')
if __name__ == '__main__':
# 注意生成测试报告 必须在命令行执行
# pytest --alluredir ./Reports test03.py
# allure serve ./Reports 启动allure服务,查看报告
pytest.main(['--aluredir','./Reports','test03.py'])
测试报告
十一、补充:pytest使用dependency来做依赖
具体使用如下:
# 安装
pip install pytest-dependency
# 例:后台管理页,操作page, 需先管理员登录,在管理员登录成功的fun上添加被依赖
被依赖的标签:@pytest.mark.dependency(name='admin_login')
# 在后台管理页的操作page,添加依赖
依赖的标签:@pytest.mark.dependency(depends=["admin_login"], scope="module")