菜鸟笔记自动化框架之pytest

目录

1、概述

2、使用介绍

2.1、安装pytest

2.2、pytest编写规范

2.3、setup、teardown操作

2.4、断言

2.5、标记失败重跑次数

3.6、pytest-xdist 多CPU分发并行执行用例

3.7、使用装饰器@pytest.mark.usefixtures()修饰需要前运行的用例

3、数据驱动

3.1、单个参数

3.2、多个参数

3.3、使用多个@pytest.mark.parametrize()装饰器

3.4、运用文件数据作为参数

4、运行程序

4.1、单个程序运行

4.2、多个程序运行

4.3、批量运行


1、概述

pytest是一个非常成熟的全功能的python测试框架,主要特点有一下:

  • 1、简单灵活,容易上手,文档丰富;
  • 2、支持参数化,可以细粒度地控制要测试的测试用例;
  • 3、能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appnium等自动化测试、接口自动化测试(pytest+requests);
  • 4、pytest具有很多第三方插件,并且可以自定义扩展,比较好用的如pytest-selenium(集成selenium)、pytest-html(完美html测试报告生成)、pytest-rerunfailures(失败case重复执行)、pytest-xdist(多CPU分发)等;
  • 5、测试用例的skip和xfail处理;
  • 6、可以很好的和CI工具结合,例如jenkins

 

2、使用介绍

2.1、安装pytest

pip install pytest

2.2、pytest编写规范

  • 测试文件以test_开头(或与_test结尾)
  • 测试类以Test开头,并且class类内不能带有init方法
  • 测试函数以test_开头
  • 断言基本使用assert

2.3、setup、teardown操作

  • setup,在测试函数或类之前执行,完成准备工作,例如数据库链接、测试数据、打开文件等
  • teardown,在测试函数或类之后执行,完成收尾工作,例如断开数据库链接、回收内存资源等
  • setup、teardown
def setup(self):
    print("用例执行前都会执行")

def teardown(self):
    print("用例执行后都会执行")
  • setup_class、teardown_class
    @classmethod
    def setup_class(self):
        print("执行class前只会执行一次")

    @classmethod
    def teardown_class(self):
        print("执行class后只会执行一次")

2.4、断言

assert '100000' == res.json()['code']  # 断言使用Python原生assert

assert '注册成功' in res.json()['msg']

2.5、标记失败重跑次数

安装:pip3 install pytest-rerunfailures

命令:pytest --reruns 5 test_pytest.py

用命令运行或在代码中运用@pytest.mark.flaky

@pytest.mark.flaky(reruns=5, reruns_delay=1) # 如果失败则延迟1s后重跑 
def test_user_reg() # 最多重跑5次, reruns_delay可以不传 ...
    assert 1==2

3.6、pytest-xdist 多CPU分发并行执行用例

安装:pip3 install pytest-xdist

#分2个进程跑,如果有6个方法,第一个进程固定跑1、3、5,第二个进程固定跑2、4、6

命令:pytest test_01.py -n 2

3.7、使用装饰器@pytest.mark.usefixtures()修饰需要前运行的用例

需要每个用例前执行标记方法,代码如下:

import pytest
@pytest.fixture()   #标记
def test1():
    print("\n------我是test1-----")

@pytest.mark.usefixtures("test1")  
#运行每个用例前都会执行test1,括号里面是方法名,pytest.mark.usefixtures写在class前,功能与setup一致
class Testpytest():
    def test_1(self):
        print("我是1")

    def test_2(self):
        print("我是2")


运行结果:
------我是test1-----
我是1
------我是test1-----
我是2

只需要在指定用例前执行标记方法,代码如下:

import pytest
# @pytest.fixture()\
@pytest.fixture()
def test1():
    print("\n------我是test1-----")
    return 1234

class Testpytest():
    @pytest.mark.usefixtures("test1")
    def test_1(self):
        print("我是1")
        # print(test1)

    def test_2(self):
        print("我是2")

运行结果:
------我是test1-----
我是1
我是2

需要标记方法的return值时,只能通过方法名作为参数传入,代码如下:

import pytest
@pytest.fixture()
def test1():
    print("\n------我是test1-----")
    return 1234

class Testpytest():
    def test_1(self, test1):
        print("我是1")
        print(test1)

运行结果:
------我是test1-----
我是1
1234

如果一个class需要调用多个fixture,可以使用多个@pytest.mark.usefixtures()修饰器,注意先执行的放下底层,后执行放在上层,代码如下:

import pytest
@pytest.fixture()
def test1():
    print("\n------我是test1-----")

@pytest.fixture()
def test2():
    print("\n------我是test2-----")

@pytest.mark.usefixtures("test2")
@pytest.mark.usefixtures("test1")
class Testpytest():
    def test_1(self):
        print("我是1")

运行结果:
------我是test1-----

------我是test2-----
我是1

 

3、数据驱动

数据驱动运用pytest.mark.parametrize()装饰器,把测试过程中需要的测试数据提取出来,传递参数的个数来决定程序运行的次数

3.1、单个参数

在使用pytest.mark.parametrize()传递参数化数据时,测试用例本身必须有参数。第一个参数为字符串格式,第二参数为数据,数据的个数决定用例运行的次数

import pytest

class Testpytest():
    @pytest.mark.parametrize("a", ("1", "2", "3")) 
         # a作为装饰器传入值的变量,参数必须以元组或列表形式出现
    def test_1(self, a):   # 作为用例参数,接受装饰器传入的值
        print("\na是:"+a)

运行结果:
a是:1
.
a是:2
.
a是:3

3.2、多个参数

多个参数,第一个字符串,对应用例的多个参数,以逗号隔开;第二个参数为数据

import pytest

class Testpytest():
    @pytest.mark.parametrize("a,b", [("1", "2"), ("3", "4"), ("5", "6")])
    def test_1(self, a, b):
        print("\na+b是:"+a+b)

运行结果:
a+b是:12
.
a+b是:34
.
a+b是:56

3.3、使用多个@pytest.mark.parametrize()装饰器

import pytest

class Testpytest():
    @pytest.mark.parametrize("a", ("1","2"))
    @pytest.mark.parametrize("b", ("4","5"))
    def test_1(self, a, b):
        print("\na+b是:"+a+b)

运行结果:
a+b是:14
.
a+b是:24
.
a+b是:15
.
a+b是:25

3.4、运用文件数据作为参数

写一个读取文件数据,返回一个list数组的方法

import pytest

def data():
    with open("C:/Users/Administrator/Desktop/香港大盘成分股.txt", encoding="utf8") as f:
        datas = f.read().split("\n")
    return datas

class Testpytest():
    @pytest.mark.parametrize("a", data())
    def test_1(self, a):
        print("\n成分股:"+a)

 

4、运行程序

在工程目录下新建runner.py文件,内容如下:

4.1、单个程序运行

# coding:utf-8
import pytest
import os
                # 文件路径                             # 存入文件的路径                 
pytest.main(['./case/test_abc.py','-s', '--alluredir', './temp'])

4.2、多个程序运行

运行多个程序,则增加多个pytest.main()

# coding:utf-8
import pytest
import os

pytest.main(['./case/test_login.py','-s', '--alluredir', './temp'])
pytest.main(['./case/test_abc.py','-s', '--alluredir', './temp'])

4.3、批量运行

在该程序目录新建pytest.ini文件(名称不能改),pytest.ini内容如下:

-v:详细显示输出

case目录下的test_abc程序下Test_run类下的test_1方法,运行结果:PASSED

-s:显示print结果

显示:---a---

[pytest]
# 添加命令行参数
addopts = -v -s --alluredir ./temp

# 文件搜索路径
testpaths = ./case/
# 类名称
python_classes = Test*
# 方法名称
python_functions = test_*
# 文件名称
python_files = test_*.py

设置好pytest.ini文件后,运行命令:pytest

菜鸟笔记自动化框架之pytest_第1张图片

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(python,pytest,单元测试)