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:TestSoftwarePyCharmPyCharmProjectJpressCasespytest>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:TestSoftwarePyCharmPyCharmProjectJpressCasespytest, 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:TestSoftwarePyCharmPyCharmProjectJpressCasespytest>


:: 双冒号指定执行

(base) D:TestSoftwarePyCharmPyCharmProjectJpressCasespytest>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:TestSoftwarePyCharmPyCharmProjectJpressCasespytest, 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:TestSoftwarePyCharmPyCharmProjectJpressCasespytest>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:TestSoftwarePyCharmPyCharmProjectJpressCasespytest, 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:TestSoftwarePyCharmPyCharmProjectJpressCasespytest, 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("
setup_module,只执行一次,当有多个测试类的时候使用")

def teardown_module():
    print("
teardown_module,只执行一次,当有多个测试类的时候使用")

class TestPytest1(object):

    @classmethod
    def setup_class(cls):
        print("
setup_class1,只执行一次")

    @classmethod
    def teardown_class(cls):
        print("
teardown_class1,只执行一次")

    def setup_method(self):
        print("
setup_method1,每个测试方法都执行一次")

    def teardown_method(self):
        print("teardown_method1,每个测试方法都执行一次")

    def test_1(self):
        print("
test_1,第1条测试用例")

    def test_2(self):
        print("
test_2,第2条测试用例")

class TestPytest2(object):

    @classmethod
    def setup_class(cls):
        print("
setup_class2,只执行一次")

    @classmethod
    def teardown_class(cls):
        print("
teardown_class2,只执行一次")

    def setup_method(self):
        print("
setup_method2,每个测试方法都执行一次")

    def teardown_method(self):
        print("teardown_method2,每个测试方法都执行一次")

    def test_3(self):
        print("
test_3,第3条测试用例")

    def test_4(self):
        print("
test_4,第4条测试用例")
 

十、pytest使用allure生成测试报告

介绍:allure官网

  • 安装
pip3 install allure-pytest

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")

原文地址:https://www.cnblogs.com/c-jw/p/13953537.html