初识Pytest自动化测试框架,我彻底懂了

news2025/1/19 11:25:59

初识Pytest

  • Pytest是Python实现的一个测试工具,可以用于所有类型和级别的软件测试。

  • Pytest是一个可以自动查找到你编写的用例并运行后输出结果的测试框架。

  • Pytest的特点:

    • 是一个命令行工具,编写用例简单,可读性强
    • 非常容易上手,入门简单,文档丰富,文档中有很多实例可以参考
    • 支持单元测试和功能测试
    • 支持参数化
    • 执行测试过程中可以将某些测试跳过,或者对某些预期失败的Case标记成失败
    • 支持重复执行失败的Case
    • 支持运行由unittest编写的测试Case
    • 具有很多第三方插件,并且可以自定义扩展
    • 方便的和持续集成工具集成
    • 可以运行以test开头或test结尾的包、文件和方法
    • 可以使用assert进行断言
  • Pytest 安装

     pip install -U pytest -i https://pypi.tuna.tsinghua.edu.cn/simple
    

Pytest 第一个例子

  • pytest 默认能够自动识别 test 开头函数和方法,以及 Test 开头的类。
import pytest
import requests


def test_one():
    r = requests.get('https://www.baidu.com')
    print(r.status_code)

def test_two():
    r = requests.get('https://www.baidu.com')
    print(r.encoding)

class TestTask(object):
    def test_1(self):
        print('test 1')

    def test_2(self):
        print('test 2')

if __name__ == '__main__':
    pytest.main() # pytest
  • 右键直接运行,结果如下
============================= test session starts ==============================
platform darwin -- Python 3.7.3, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /Users/xiaoyidemac/Desktop/测试
plugins: tavern-1.16.3, openfiles-0.3.2, arraydiff-0.3, allure-pytest-2.9.45, doctestplus-0.3.0, remotedata-0.3.1collected 4 items

pytest_code.py .200
.ISO-8859-1
                                                      [100%]

============================== 4 passed in 0.29s ===============================

Process finished with exit code 0
.test 1
.test 2

pytest运行方式

通过代码中pytest.main()可以右键直接运行,相当于python test_1.py;也可以通过命令行的方式启动运行

代码中运行的方式

  • pytest.main()
    会执行当前文件的同时,路径下所有以test开头的py文件都会被执行
    pytest先获取所有文件中的测试函数后,再执行
    不会显示代码中的标准输出(print、logging)
  • pytest.main(['-s'])
    会执行当前文件的同时,路径下所有以test开头的py文件都会被执行
    pytest先获取所有文件中的测试函数后,再执行
    显示代码中的标准输出(print、logging)
  • pytest.main(['test_1.py'])
    只会执行当前文件
    不会显示代码中的标准输出(print、logging)
  • pytest.main(['-s', 'test_1.py'])
    只会执行当前文件
    显示代码中的标准输出(print、logging)

上述四种方式皆有对应的命令行运行的方式

  • pytest
    会执行当前文件的同时,路径下所有以test开头的py文件都会被执行
    pytest先获取所有文件中的测试函数后,再执行
    不会显示代码中的标准输出(print、logging)
  • pytest -s
    会执行当前文件的同时,路径下所有以test开头的py文件都会被执行
    pytest先获取所有文件中的测试函数后,再执行
    显示代码中的标准输出(print、logging)
  • pytest test_1.py
    只会执行当前文件
    不会显示代码中的标准输出(print、logging)
  • pytest -s test_1.py
    只会执行当前文件
    显示代码中的标准输出(print、logging)

注意:

  • 测试脚本中的测试类,如果不以Test作为名称开头,将无法执行
  • 测试脚本中的函数,如果不以test作为名称开头,将无法执行

断言的处理

assert

什么是断言

  • 断言就是用来检测程序是否正确, 若条件为假,就中断程序执行
  • 编写代码时,总是会做出一些假设,断言就是用于在代码中捕捉这些假设
  • 断言表示为一些布尔表达式

断言的使用场景

  • 使用assert语句
  • 断言预期的异常
  • 断言预期的警告

assert断言语句

  • 采用assert断言时,可添加备注信息
  • 当断言预测失败时,备注信息会以AssertionError抛出,并在控制台输出
assert expression [, arguments]
# expression 为 True 则 pass
# expression 为 False 则 抛出异常,有 argument 则输出 argument
'''
expression:
1)比较运算
2)逻辑运算  and | or | not
3)身份运算  is | is not
4)成员运算  in | not in
'''

示例代码:

import requests

def test_assert():
    r = requests.get('http://www.baidu.com')
    assert r.status_code == 200, "没有返回200,断言失败"

异常断言

  • 在测试过程中,对某些方法进行测试时,预测输入某些特定数据,会抛出某种异常,若出现该异常,则用例执行通过。

  • 对这预期会出现的异常的断言,可以采用pytest中的pytest.raises()进行处理。

pytest.raises()的使用

  • pytest.raises(expected_exception, match=None, kwargs)
    expected_exception 是预期异常类或者的异常类元组
    match 用于匹配异常的消息内容
import pytest


def is_leap_year(year):
    # 先判断year是不是整型
    if isinstance(year, int) is not True:
        raise TypeError("传入的参数不是整数")
    elif year == 0:
        raise ValueError("公元元年是从公元一年开始!!")
    elif abs(year) != year:
        raise ValueError("传入的参数不是正整数")
    elif (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
        print("%d年是闰年" % year)
        return True
    else:
        print("%d年不是闰年" % year)
        return False


class TestAssert(object):
    """对判断是否是闰年的方法进行测试"""

    def test_exception_typeerror(self):
        # 使用 pytest.raises 作为上下文管理器,捕获给定异常类型TypeError
        # is_leap_year('2020')抛出TypeError,被pytest.raises捕获到,则测试用例执行通过
        with pytest.raises(TypeError):
            # 传入字符串引发类型错误
            is_leap_year('2020')

运行结果如下:

============================= test session starts ==============================
platform darwin -- Python 3.7.3, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /Users/xiaoyidemac/Desktop/测试
plugins: tavern-1.16.3, openfiles-0.3.2, arraydiff-0.3, allure-pytest-2.9.45, doctestplus-0.3.0, remotedata-0.3.1collected 1 item

pytest_code.py                                                          [100%]

============================== 1 passed in 0.06s ===============================

把异常信息存储到变量

有时候我们可能需要在测试用到产生的异常信息,我们可以把异常信息存储到一个变量中,变量的类型为 异常类 ,包含异常的 type、value 或者 traceback 等信息。

import pytest

def is_leap_year(year):
    # 先判断year是不是整型
    if isinstance(year, int) is not True:
        raise TypeError("传入的参数不是整数")
    elif year == 0:
        raise ValueError("公元元年是从公元一年开始!!")
    elif abs(year) != year:
        raise ValueError("传入的参数不是正整数")
    elif (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
        print("%d年是闰年" % year)
        return True
    else:
        print("%d年不是闰年" % year)
        return False

class TestAssert(object):
    """对判断是否是闰年的方法进行测试"""

    def test_exception_typeerror(self):
        # 预测到参数不符合要求,会抛出TypeError异常;若出现该异常,则测试用例执行通过
        with pytest.raises(TypeError) as err_info:
            # 传入字符串引发类型错误
            is_leap_year('2020')
        # 断言异常的类型是 TypeError,断言成功则不会抛出异常
        assert err_info.type == TypeError, '错误类型不匹配'

通过异常的内容捕捉异常

import pytest

def is_leap_year(year):
    # 先判断year是不是整型
    if isinstance(year, int) is not True:
        raise TypeError("传入的参数不是整数")
    elif year == 0:
        raise ValueError("公元元年是从公元一年开始!!")
    elif abs(year) != year:
        raise ValueError("传入的参数不是正整数")
    elif (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
        print("%d年是闰年" % year)
        return True
    else:
        print("%d年不是闰年" % year)
        return False


class TestAssert(object):
    """对判断是否是闰年的方法进行测试"""
    def test_exception_typeerror(self):
        # 通过异常的内容捕捉异常,但具体是何种异常不清楚
        with pytest.raises(Exception, match='从公元一年开始') as err_info:
            is_leap_year(0)
        # 断言异常的类型是 ValueError,断言成功则不会抛出异常
        assert err_info.type == ValueError

警告断言

  • pytest 中对警告进行断言采用 pytest.warns() 方法,其断言的方法与 pytest.raises() 类似。
  • pytest.warns() 除了能断言告警外,还能够捕获告警信息,并对捕获的告警信息进行分类处理,可以设定出现特定告警信息时,则用例执行失败。
  • 程序中抛出警告时,并不会中断程序的执行,一般是打印警告信息,而程序抛出异常时可能直接中断程序的运行。因此对于警告类信息我们在捕获的时候,可以捕获到多个,而异常信息只能捕获到一个。

pytest.warns()的使用

  • pytest.warns(expected_warning, *args, match, **kwargs)
    --- expected_warning 预期的警告类或者警告类元组,例如:
    DeprecationWarning 弃用警告
    UserWarning 用户警告
  • match 可以自定义的匹配警告内容
import pytest
import warnings

def make_warn():
    # 抛出
    warnings.warn("deprecated", DeprecationWarning)

def not_warn():
    pass

def user_warn():
    warnings.warn("user warn", UserWarning)


class TestWarns(object):
    def test_make_warn(self):
        with pytest.warns(DeprecationWarning):
            make_warn()

    def test_not_warn(self):
        # 断言not_warn函数将会抛出警告
        # 但实际是没有抛出警告的,所以无法通过测试
        with pytest.warns(Warning):
            not_warn()

    def test_user_warn(self):
        with pytest.warns(UserWarning):
            user_warn()

运行结果如下:


================================================== test session starts ===================================================
platform linux -- Python 3.6.8, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
rootdir: /home/python/code/unit_testing/pytest_code
collected 3 items                                                                                                        

test_7.py .F.                                                                                                      [100%]

======================================================== FAILURES ========================================================
________________________________________________ TestWarns.test_not_warn _________________________________________________

self = 

    def test_not_warn(self):
        with pytest.warns(Warning):
>           not_warn()
E           Failed: DID NOT WARN. No warnings of type (,) was emitted. The list of emitted warnings is: [].

test_7.py:24: Failed
================================================ short test summary info =================================================
FAILED test_7.py::TestWarns::test_not_warn - Failed: DID NOT WARN. No warnings of type (,) was emitted...
============================================== 1 failed, 2 passed in 0.04s ===============================================

把警告信息存储到变量

将告警信息存入一个变量中,通过读取这个变量中的信息进行断言,包括:告警的个数、告警信息参数等。

# pytest_code/test_8.py
import warnings
import pytest

def warn_message():
    warnings.warn("user", UserWarning)
    warnings.warn("runtime", RuntimeWarning)

def test_warn_match():
    with pytest.warns((UserWarning, RuntimeWarning)) as record:
        warn_message()
    assert len(record) == 2
    assert str(record[0].message) == "user"
    assert str(record[1].message) == "runtime"
    assert record[0].category == UserWarning
    assert record[1].category == RuntimeWarning

运行结果如下:

$ pytest test_8.py
================================================== test session starts ===================================================
platform linux -- Python 3.6.8, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
rootdir: /home/python/code/unit_testing/pytest_code
collected 1 item                                                                                                         

test_8.py .                                                                                                        [100%]

=================================================== 1 passed in 0.01s ====================================================

通过警告的内容捕捉警告

# pytest_code/test_9.py
import warnings
import pytest


def make_warn():
    # 抛出
    warnings.warn("deprecated", DeprecationWarning)


def not_warn():
    pass

def user_warn():
    warnings.warn("user warn", UserWarning)


class TestWarns(object):
    def test_make_warn(self):
        # 捕获警告内容为deprecated的警告
        with pytest.warns(Warning, match='deprecated'):
            make_warn()

  最后我这里给你们分享一下我所积累和真理的文档和学习资料有需要是领取就可以了

1、学习思路和方法

这个大纲涵盖了目前市面上企业百分之99的技术,这个大纲很详细的写了你该学习什么内容,企业会用到什么内容。总共十个专题足够你学习

2、想学习却无从下手,该如何学习?

这里我准备了对应上面的每个知识点的学习资料、可以自学神器,已经项目练手。

3、软件测试/自动化测试【全家桶装】学习中的工具、安装包、插件....

 4、有了安装包和学习资料,没有项目实战怎么办,我这里都已经准备好了往下看

 最后送上一句话:

世界的模样取决于你凝视它的目光,自己的价值取决于你的追求和心态,一切美好的愿望,不在等待中拥有,而是在奋斗中争取。

如果我的博客

对你有帮助、如果你喜欢我的文章内容,请 “点赞” “评论” “收藏” 一键三连哦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/44289.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年高企申报准备工作,明光市企业可以提前做这些准备

为了帮助企业提前准备和更好地开展2023年高新技术企业认定申报工作,安徽省大力鼓励企业申报高新技术企业,相应出台了相关政策,同时对于高企申报也有很多奖补,下面小编汇总了滁州市2023年申报,企业提前准备工作有哪些。…

黑群晖从入门到入土,自编译适合自己硬件的黑群晖7.1.x引导(黑群晖DSM7.X引导用arpl编译教程)

写在前面的话 没啥好说的,只需要感谢在GitHub上开源代码的巴西老哥就好,好了废话不多说直接开始。 黑群晖DSM7.X引导用arpl编译教程写在前面的话一、需要的软硬件清单二、制作引导盘1、下载arpl镜像2.1.1、制作PE启动盘,这是使用msata硬盘或…

3. Vue.js 3.0 响应式系统原理

1.响应式系统原理-介绍 接下来通过模拟Vue3的响应式系统来深入了解它内部的工作原理。先来回顾一下Vue3重写了响应式系统,和Vue2相比,Vue3的响应式系统底层采用proxy对象实现,在初始化的时候不需要遍历所有的属性,把属性通过defi…

C语言——结构体(入门)

文章目录1.结构体的声明1.1.结构体是什么?1.2.结构体的声明1.3.结构体的定义和初始化2.结构体成员的访问3.结构体传参1.结构体的声明 1.1.结构体是什么? 在生活中往往很难用一个准确的数据类型来描述一个物体,例如一本书,描述它…

编码技巧——Mybatis分页插件PageHelper使用

本篇介绍Mybatis分页插件PageHelper的使用,本质上是Mybatis拦截器起作用,在执行目标SQL之前添加count语句及拼接limit到目标SQL后面,这里不再赘述,Mybatis拦截器相关知识可参考Mybatis——拦截器Interceptor,本篇仅简单…

12_AJAX

知识点1【定时器】(重要) 知识点2【日期Date对象】 知识点3【Math数学对象】(了解) ​编辑 知识点4【string对象】 indexof函数: substring()函数: 知识点5【全局函数】(了解) …

Android使用高德地图实现运动轨迹绘制和轨迹回放

功能的实现完全是使用高德地图进行实现的,先看一下效果图吧! 下图是在绘制轨迹的过程: 下图是在轨迹回放的过程: 下图是记录运动的时间区间: 其实这个实现起来还是很容易的,总体逻辑就是:定位—…

Meter接口测试使用教程哪里找?

接口测试是测试工程师的必备技能之一,运用JMeter工具一步步实现接口请求,数据参数化,断言等操作,通过常见的企业实际测试场景详解JMeter各项技术使用,最后结合Jenkins持续集成实现企业级小程序接口自动化测试&#xff…

数据结构(6)树形结构——平衡二叉树(JAVA代码实现)

目录 6.1.概述 6.2.AVL树 6.2.1.概述 6.2.2.旋转 1.RR旋转 2.LL旋转 3.LR旋转 4.RL旋转 6.2.3.代码实现 6.1.概述 二叉搜索树存在一个问题,就是树的姿态和数据的插入顺序是有关系的,有时候树会变成某一边的子树高度过高,甚至直接退化成…

百度联合哈尔滨发布城市大模型“冰城-百度·文心”, 助力城市智能化建设

本文已在【飞桨PaddlePaddle】公众号平台发布,详情请戳链接:百度联合哈尔滨发布城市大模型“冰城-百度文心”, 助力城市智能化建设 近日,哈尔滨市人民政府与百度携手,联合发布面向城市领域的行业大模型——冰城-百度文…

PyTorch学习笔记-损失函数与反向传播

1. 损失函数 具有深度学习理论基础的同学对损失函数和反向传播一定不陌生,在此不详细展开理论介绍。损失函数是指用于计算标签值和预测值之间差异的函数,在机器学习过程中,有多种损失函数可供选择,典型的有距离向量,绝…

【Oracle系列4】Oracle 数据库的层次结构,常见的GUI连接用具

【Oracle系列4】Oracle 数据库的层次结构 跟mysql不一样,mysql连上后能看到所有库,库下面直接就是表了。 跟pgsql也不一样,pgsql连上后,也是可以看到所有库,库下面是schema,schema下面才是表(…

G1D25-蜜汁APEX-RAGA代码运行友友第一次跑模型

一、APEX 英伟达开发的,压缩数据的框架 (一)安装bug 直接安装 https://blog.csdn.net/weixin_47658790/article/details/115055505 (二)运行bug 然后运行又出现了bug----------------------- IndexError: tuple …

沉睡者IT - 10个问题说清楚:什么是元宇宙?

欢迎关注沉睡者IT,点上面关注我 ↑ ↑ 人们对于元宇宙的构想十分多元且抽象,这十个问题将抽象的元宇宙具象化,帮助人们更好地理解。 一、什么是元宇宙? 1)元宇宙概念的提出 元宇宙在很长一段时间内仅存在于文学与影视作品中。…

一、spring框架的演变

1.微服务架构的演进过程 1.1 单体架构单机部署 1.运行在tomcat里面,并发量QPS一般在200多个请求左右,同一个jvm进程,直接import就行。 2.不同的功能模块可能只用文件夹区分。 3.缺点:并发量太小(如果是电商系…

【pygame游戏】用Python实现一个蔡徐坤大战篮球的小游戏,可还行?【附源码】

Python制作坤坤打篮球小游戏序言准备工作开发环境效果预览开始界面游戏规则结束游戏代码实现序言 话说在前面,我不是小黑子~ 我是超级大黑子😏 表弟大周末的跑来我家,没事干天天骚扰我,搞得我都不能跟小姐姐好好聊天了&#xf…

【813. 最大平均值和的分组】

来源:力扣(LeetCode) 描述: 给定数组 nums 和一个整数 k 。我们将给定的数组 nums 分成 最多 k 个相邻的非空子数组 。 分数 由每个子数组内的平均值的总和构成。 注意我们必须使用 nums 数组中的每一个数进行分组,…

3DMAX森林树木植物插Forest Pack Pro 预设库安装教程

Forest Pack是世界上最流行的3dMax森林树木植物散布插件。它提供了一个完整的解决方案来创建广阔的物体区域,从树木和植物到建筑物、人群、骨料、地面覆盖物、岩石等等。模拟大型场景总是非常困难,但这个插件可以帮助您以较少的难度进行模拟。 Forest P…

最近面试 Java 开发的感受:就以平时项目经验面试,通过估计很难

在上周,我密集面试了若干位 Java 后端的候选人,工作经验在 3 到 5 年间。我的标准其实不复杂:第一能干活,第二 Java 基础要好,第三最好熟悉些分布式框架,我相信其它公司招初级开发时,应该也照着…

CountDownLatch

目录 1 前言 2 常用方法 3 示例 4 解析 4.1 countDown() 4.2 await() 源码 1 前言 countDownLatch( 门阀、 计数器)是多线程控制的一种工具 ,它用来协调各个线程之间的同步。 countDownLatch相当于一个计数器,能够使…