pytest测试框架

本文详细介绍了pytest测试框架,包括其易于上手的特点、单元测试与功能测试支持、参数化、断言、fixture的使用、类/方法级别fixture、配置文件、插件如测试报告和控制测试顺序,以及高级用法如跳过、数据驱动和mock接口示例。
摘要由CSDN通过智能技术生成


一、pytest测试框架

特点:

1、非常容易上手,入门简单,文档丰富,文档中有很多参考实例

2、支持简单的单元测试和复杂的功能测试

3、支持参数化

4、执行测试用例过程中,支持跳过操作

5、支持重复执行失败的case

6、支持运行由Nose,unittest编写的测试case

7、pytest支持很多第三方插件

8、方便的和持续集成工具集成

1、pytest介绍及安装

  • pytest安装

    • 在线安装 pip install pytest

    • 离线安装方式 下载pytest离线安装包,并解压,然后在DOS下进入到解压的目录,然后执行 python setup.py install

    • pycharm

  • 判断是否安装成功:

    • pip show pytest

    • pycharm

2、pytest类定义及方法定义及运行

  • pytest测试类的定义:类名必须是以Test开头

  • pytest测试方法的定义:方法名必须是以test开头

  • 执行:在pycharm中右击方法名或者类名可以直接执行对应测试类或者测试方法

241427de8f65422ab7b0d336ff259664.png

4379ef67b61f44ba8e5265abe207da39.png

第二种运行方式: 通过pytest -s -v 测试文件名称 (-s 输出的用例输出的信息, -v输出的是执行的用例的类名以及方法名)

import pytest


def add(x, y):
    return x+y


class TestADD:  # 定义的类名必须是以Test开头
    def test_add_01(self):  # 定义的测试方法必须是以test开头
        result = add(1, 2)
        print(result)

    def test_add_02(self):
        result = add(2, 2)
        print(result)

 

3、pytest 断言

  • pytest里面的断言方法就只有一个

    assert 表达式

    class TestADD:  # 定义的类名必须是以Test开头
        def test_add_01(self):  # 定义的测试方法必须是以test开头
            result = add(1, 2)
            print(result)
            # assert result == 3        # 判断相等
            # assert result != 4        # 判断不相等
            # assert result             # 判断为True
            # assert False              # 判断为False
            # assert "a" in "abc"       # 判断包含
            # assert "a" not in "abc"   # 判断不包含
            # assert result is None
            # assert result is not None

     

4、pytest 方法级别的fixture

  • pytest方法级别的fixture是针对每个测试方法,在执行测试方法前会执行fixture初始化的操作,在执行完测试方法后,执行fixture销毁的操作。

    初始化的操作方法: def setup(self): 方法来实现。

    销毁的操作方法: def teardown(self): 方法来实现。

    import time
    
    
    def add(x, y):
        return x+y
    
    
    class TestAdd:
    
        def setup(self):
            print("测试用例开始执行时间:", time.strftime("%Y-%m-%D %H:%M:%S"))
    
        def test_add_01(self):
            result = add(1, 2)
            assert result == 3
    
        def test_add_02(self):
            result = add(2, 2)
            assert result == 4
    
        def teardown(self):
            print("测试用例结束时间:", time.strftime("%Y-%m-%d %H:%M:%S"))

     

5、pytest类级别的fixture

  • pytest 类级别的fixture针对每个测试类的初始化和销毁的操作,可以放在以下两个方法中

    • 类级别初始化的方法: def setup_class(self):

    • 类级别销毁的方法: def teardown_class(slef):

      方法名称固定,不能修改。

import time

def add(x, y):
    return x+y

class TestAdd:
    # 添加类级别的初始化操作方法
    def setup_class(self):
        print("测试类开始执行时间:",  time.strftime("%Y-%m-%d %H:%M:%S"))

    # 添加类级别的销毁操作方法
    def teardown_class(self):
        print("测试类结束执行时间:", time.strftime("%Y-%m-%d %H:%M:%S"))

    def setup(self):
        print("测试方法开始执行时间:", time.strftime("%Y-%m-%d %H:%M:%S"))

    def teardown(self):
        print("测试方法结束时间:", time.strftime("%Y-%m-%d %H:%M:%S"))

    def test_add_01(self):
        result = add(1, 2)
        print(result)
        assert result == 3

    def test_add_02(self):
        result = add(2, 2)
        print(result)
        assert result == 4

fixture的方法必须写在测试类当中,不能写在测试类外面。

6、pytest配置文件

pytest的配置文件有固定的三个名称: pytest.ini tox.ini setup.cfg 这三个配置文件是放在项目的根目录下。

[pytest]                    # 标识当前配置文件是pytest的配置文件
addopts = -s -v             # 标识pytest执行时增加的参数
testpaths = ./scripts       # 匹配搜索的目录
python_files = test_*.py    # 匹配测试文件
python_classes = Test*      # 匹配测试类
python_functions = test_*   # 匹配测试方法

 

Pytest插件

pytest测试报告

  • 安装pytest测试报告插件

    • 在线安装

    • 离线安装

    • pycharm

  • 使用方法

    [pytest]
    addopts = -s -v --html=report/report.html
    testpaths = ./scripts
    python_files = test_*.py
    python_classes = Test*
    python_functions = test_*

一、pytest常用插件

2、控制用例执行顺序

  • unittest测试用例执行顺序是根据测试方法名称的assicc码值的大小来的,值越小排在前面(a-z)

  • pytest 正常情况下是根据测试方法的从上到下的顺序来执行

    可以通过 pytest-ordering 插件来控制pytest测试方法执行的顺序。

  • 安装:

    • 在线安装: pip install pytest-ordering

    • 离线安装: 下载对应的离线安装包,解压后,并进入到对应的目录,执行 python setup.py install

    • pycharm

  • 使用

    @pytest.mark.run(order=x) # x 表示的是整数,(既可以是负数也可以是正数)

    • 全为负数或者正数时,值越小,优先级越高

    • 既有正数,又有负数,那么正数优先级高

    • 没有确定执行顺序的用例优先于负数

    • @pytest.mark.last    # 设置用例最后执行

3、失败重试

  • pytest-rerunfailures 安装

    • 在线安装

    • 离线安装

    • pycharm

  • 使用

    在addopts参数行中增加对应的参数项: --reruns 3

    当重复执行成功时,就不会再重复执行。

     

 


二、 pytest高级用法

1、跳过

@pytest.mark.skipif(condition, reason=None)

condition 表示是跳过的条件

这里面reason参数名称必填。

@pytest.mark.skip(reason=None)

reason表示的是跳过的原因

可以在测试类和测试方法上使用

import pytest


def add(x, y):
    return x+y

version = 21

class TestAdd:
    # @pytest.mark.last    # 设置用例最后执行
    def test_add_01(self):
        result = add(1, 2)
        assert 3 == result

    @pytest.mark.skipif(version > 20, reason="大于2.0的版本不需要再执行此用例")
    # @pytest.mark.skip("版本已更新,不需要再进行测试")
    @pytest.mark.run(order=0)
    def test_add_02(self):
        result = add(2, 2)
        assert 4 == result

    @pytest.mark.run(order=-2)
    def test_add_03(self):
        result = add(3, 2)
        assert 5 == result

 

2、数据的参数化

  • pytest参数化实现: @pytest.mark.parameterize(argnames, argvalues)

    • argnames 表示是 参数名字,是一串字符, 多个参数之间由逗号隔开 "username, password"

    • argvalues 表示的是参数化的数据 [("13700001111","123124"),("13800011111","123456")]

      argname的参数个数要与argvalues里面的测试数据的个数要相同,否则会报错。

import pytest


def add(x, y):
    return x+y

class TestAdd:
    @pytest.mark.parametrize("x,y,expect", [(1, 2, 3), (2, 2, 4), (3, 2, 5)])
    def test_add_01(self, x, y, expect):
        result = add(x, y)
        assert expect == result

 

读取yaml文件

-
    name: 100元优惠券
    money: 100
    condition: 1000
    createnum: 20
    type: 1
    send_start_time: 2022-06-26 20:01:08
    send_end_time: 2022-07-26 20:01:08
    use_start_time: 2022-06-27 20:01:08
    use_end_time: 2022-08-26 20:01:08
    use_type: 0
    cat_id1: 0
    cat_id2: 0
    cat_id3: 0
    status: 1

-
    name: 2元优惠券
    money: 200
    condition: 1000
    createnum: 20
    type: 1
    send_start_time: 2022-06-26 20:01:08
    send_end_time: 2022-07-26 20:01:08
    use_start_time: 2022-06-27 20:01:08
    use_end_time: 2022-08-26 20:01:08
    use_type: 0
    cat_id1: 0
    cat_id2: 0
    cat_id3: 0
    status: 1
import yaml
from parameterized import parameterized
import requests

def read_yaml():
    with open(r"D:\dcs\dcs12\优惠券参数化\data\get_token.yaml", encoding="utf-8", mode="r") as f:
        value = yaml.load(stream=f,Loader=yaml.FullLoader)
        return value
a = read_yaml()

print(a)
url = {}
# a = [{'name': '100元优惠券', 'money': 100, 'condition': 1000, 'createnum': 20, 'type': 1, 'send_start_time': datetime.datetime(2022, 6, 26, 20, 1, 8), 'send_end_time': datetime.datetime(2022, 7, 26, 20, 1, 8), 'use_start_time': datetime.datetime(2022, 6, 27, 20, 1, 8), 'use_end_time': datetime.datetime(2022, 8, 26, 20, 1, 8), 'use_type': 0, 'cat_id1': 0, 'cat_id2': 0, 'cat_id3': 0, 'status': 1},
#      {'name': '2元优惠券', 'money': 200, 'condition': 1000, 'createnum': 20, 'type': 1, 'send_start_time': datetime.datetime(2022, 6, 26, 20, 1, 8), 'send_end_time': datetime.datetime(2022, 7, 26, 20, 1, 8), 'use_start_time': datetime.datetime(2022, 6, 27, 20, 1, 8), 'use_end_time': datetime.datetime(2022, 8, 26, 20, 1, 8), 'use_type': 0, 'cat_id1': 0, 'cat_id2': 0, 'cat_id3': 0, 'status': 1}]
#
# data1 = a[0]
# data2 = a[1]
#
# requests.post(url=url,data=data1)
#
# requests.post(url=url,data=data2)
#

 

mok接口

import json
from flask import Flask,request

# 创建一个应用对象
app = Flask(__name__)

# 定义视图函数,设置路由规则
@app.route("/index")
def index():
    print("访问的index主页")
    return "hello mock"

# {"username":"admin", "password":"123456"}
@app.route("/api/sys/login",methods=["POST"])
def login():
    result = json.loads(request.get_data().decode("utf-8"))	# 字典形式的请求体数据
    username = result.get("username")
    password = result.get("password")
    print(username,password)
    if username =="13800000002" and password == "123456":
        data = {
            "success": True, "code": 10000,
            "message":"操作成功!",
            "token": "ajsdfj-12312-szs-fd-dfs"
        }
    else:
        data = {
            "success": False, "code": 99999,
            "message": "抱歉,系统繁忙,请稍后重试",
            "token": None
        }
    return data

if __name__ == '__main__':
    # 启动WEB服务器
    app.run()

 

 

 

  • 14
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值