Pytest 自动化测试框架

news2024/11/23 13:03:42

Pytest和Unittest测试框架的区别?

如何区分这两者,很简单unittest作为官方的测试框架,在测试方面更加基础,并且可以再次基础上进行二次开发,同时在用法上格式会更加复杂;而pytest框架作为第三方框架,方便的地方就在于使用更加灵活,并且能够对原有unittest风格的测试用例有很好的兼容性,同时在扩展上更加丰富,可通过扩展的插件增加使用的场景,比如一些并发测试等;

Pytest 安装

pip安装:

pip install pytest

测试安装成功:

pytest --help

py.test --help

检查安装版本:

pytest --version

Pytest 示例

Pytest编写规则:

  • 测试文件以test_开头(以_test为结尾)
  • 测试的类以Test开头;
  • 测试的方法以test_开头
  • 断言使用基本的assert

test_example.py

def count_num(a: list) -> int:
    return len(a)


def test_count():
    assert count_num([1, 2, 3]) != 3

执行测试:

pytest test_example.py

执行结果:

C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest>pytest test_example.py -v
================================================================= test session starts =================================================================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- d:\coding\python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collected 1 item                                                                                                                                       

test_example.py::test_count FAILED                                                                                                               [100%]

====================================================================== FAILURES =======================================================================
_____________________________________________________________________ test_count ______________________________________________________________________

    def test_count():
>       assert count_num([1, 2, 3]) != 3
E       assert 3 != 3
E        +  where 3 = count_num([1, 2, 3])

test_example.py:11: AssertionError
=============================================================== short test summary info ===============================================================
FAILED test_example.py::test_count - assert 3 != 3
================================================================== 1 failed in 0.16s ==================================================================

备注:

  • .代表测试通过,F代表测试失败;
  • -v显示详细的测试信息, -h显示pytest命令详细的帮助信息;

标记

默认情况下,pytest会在当前目录下寻找以test_为开头(以_test结尾)的测试文件,并且执行文件内所有以test_为开头(以_test为结尾)的所有函数和方法;

  1. 指定运行测试用例,可以通过::显示标记(文件名::类名::方法名)(文件名::函数名)
pytest test_example3.py::test_odd
  1. 指定一些测试用例测试运行,可以使用-k模糊匹配
pytest -k example
  1. 通过pytest.mark.skip()或者pytest.makr.skipif()条件表达式,跳过指定的测试用例
import pytest

test_flag = False

@pytest.mark.skip()
def test_odd():
    num = random.randint(0, 100)
    assert num % 2 == 1


@pytest.mark.skipif(test_flag is False, reason="test_flag is False")
def test_even():
    num = random.randint(0, 1000)
    assert num % 2 == 0
  1. 通过pytest.raises()捕获测试用例可能抛出的异常
def test_zero():
    num = 0
    with pytest.raises(ZeroDivisionError) as e:
        num = 1/0
    exc_msg = e.value.args[0]
    print(exc_msg)
    assert num == 0
  1. 预先知道测试用例会失败,但是不想跳过,需要显示提示信息,使用pytest.mark.xfail()
@pytest.mark.xfail()
def test_sum():
    random_list = [random.randint(0, 100)  for x in range(10)]
    num = sum(random_list)
    assert num < 20
  1. 对测试用例进行多组数据测试,每组参数都能够独立执行一次(可以避免测试用例内部执行单组数据测试不通过后停止测试)
@pytest.mark.parametrize('num,num2', [(1,2),(3,4)])
def test_many_odd(num: int, num2: int):
    assert num % 2 == 1
    assert num2 % 2 == 0

固件(Fixture)

固件就是一些预处理的函数,pytest会在执行测试函数前(或者执行后)加载运行这些固件,常见的应用场景就有数据库的连接和关闭(设备连接和关闭)

简单使用

import pytest


@pytest.fixture()
def postcode():
    return "hello"


def test_count(postcode):
    assert postcode == "hello"

按照官方的解释就是当运行测试函数,会首先检测运行函数的参数,搜索与参数同名的fixture,一旦pytest找到,就会运行这些固件,获取这些固件的返回值(如果有),并将这些返回值作为参数传递给测试函数;

预处理和后处理

接下来进一步验证关于官方的说法:

import pytest


@pytest.fixture()
def connect_db():
    print("Connect Database in .......")
    yield
    print("Close Database out .......")


def read_database(key: str):
    p_info = {
        "name": "zhangsan",
        "address": "China Guangzhou",
        "age": 99
    }
    return p_info[key]


def test_count(connect_db):
    assert read_database("name") == "zhangsan"

执行测试函数结果:

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\Coding\Python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collecting ... collected 1 item

test_example.py::test_count Connect Database in .......
PASSED                                       [100%]Close Database out .......


============================== 1 passed in 0.07s ==============================

备注:

  • 首先从结果上看验证了官方的解释,pytest执行测试函数前会寻找同名的固件加载运行;
  • connect_db固件中有yield,这里pytest默认会判断yield关键词之前的代码属于预处理,会在测试前执行,yield之后的代码则是属于后处理,将在测试后执行;

作用域

从前面大致了解了固件的作用,抽离出一些重复的工作方便复用,同时pytest框架中为了更加精细化控制固件,会使用作用域来进行指定固件的使用范围,(比如在这一模块中的测试函数执行一次即可,不需要模块中的函数重复执行)更加具体的例子就是数据库的连接,这一连接的操作可能是耗时的,我只需要在这一模块的测试函数运行一次即可,不需要每次都运行。

而定义固件是,一般通过scop参数来声明作用,常用的有:

  • function: 函数级,每个测试函数都会执行一次固件;
  • class: 类级别,每个测试类执行一次,所有方法都可以使用;
  • module: 模块级,每个模块执行一次,模块内函数和方法都可使用;
  • session: 会话级,一次测试只执行一次,所有被找到的函数和方法都可用。
import pytest


@pytest.fixture(scope="function")
def func_scope():
    print("func_scope")


@pytest.fixture(scope="module")
def mod_scope():
    print("mod_scope")


@pytest.fixture(scope="session")
def sess_scope():
    print("session_scope")


def test_scope(sess_scope, mod_scope, func_scope):
    pass


def test_scope2(sess_scope, mod_scope, func_scope):
    pass

执行结果:

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\Coding\Python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collecting ... collected 2 items

test_example2.py::test_scope session_scope
mod_scope
func_scope
PASSED                                      [ 50%]
test_example2.py::test_scope2 func_scope
PASSED                                     [100%]

============================== 2 passed in 0.07s ==============================

从这里可以看出module,session作用域的固件只执行了一次,可以验证官方的使用介绍

自动执行

有人可能会说,这样子怎么那么麻烦,unittest框架中直接定义setUp就能自动执行预处理,同样的pytest框架也有类似的自动执行; pytest框架中固件一般通过参数autouse控制自动运行。

import pytest


@pytest.fixture(scope='session', autouse=True)
def connect_db():
   print("Connect Database in .......")
   yield
   print("Close Database out .......")


def test1():
   print("test1")


def test2():
   print("test")

执行结果:

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\Coding\Python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collecting ... collected 2 items

test_example.py::test1 Connect Database in .......
PASSED                                            [ 50%]test1

test_example.py::test2 PASSED                                            [100%]test
Close Database out .......


============================== 2 passed in 0.07s ==============================

从结果看到,测试函数运行前后自动执行了connect_db固件;

参数化

前面简单的提到过了@pytest.mark.parametrize通过参数化测试,而关于固件传入参数时则需要通过pytest框架中内置的固件request,并且通过request.param获取参数

import pytest


@pytest.fixture(params=[
    ('redis', '6379'),
    ('elasticsearch', '9200')
])
def param(request):
    return request.param


@pytest.fixture(autouse=True)
def db(param):
    print('\nSucceed to connect %s:%s' % param)

    yield

    print('\nSucceed to close %s:%s' % param)


def test_api():
    assert 1 == 1

执行结果:

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\Coding\Python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collecting ... collected 2 items

test_example.py::test_api[param0] 
Succeed to connect redis:6379
PASSED                                 [ 50%]
Succeed to close redis:6379

test_example.py::test_api[param1] 
Succeed to connect elasticsearch:9200
PASSED                                 [100%]
Succeed to close elasticsearch:9200


============================== 2 passed in 0.07s ==============================

这里模拟连接redis和elasticsearch,加载固件自动执行连接然后执行测试函数再断开连接。

总结

对于开发来说为什么也要学习自动化测试这一块,很重要的一点就是通过自动化测试节省一些重复工作的时间,同时对于优化代码结构,提高代码覆盖率,以及后续项目重构都是有着很重要的意义,同时理解pytest和unittest在基础上有何区别有助于不同的业务场景中选择适合自己的测试工具。
这篇文章只是简单的介绍了pytest的基本使用,有兴趣的可以去看看官方文档,官方文档中还提到了如内置固件的使用,常用测试的场景等等。

尾声

我自己收集啦许多软测资料,希望能够帮到学软件测试的朋友们软件资料分享包括但不限于:Python自动化测试、性能测试、web测试、APP测试、测试开发、安全测试

测试开发工具包:appuim安装包、fiddler安装包(也有配套视频教程)、eclipse、git、jmeter、loadrunner、monkey、postman、soapul、Xmind等等

 最后感谢每一个阅读我文章的人,一点小心意,虽然不是啥值钱的东西,需要的话点击下方小卡片直接拿走~
 

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

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

相关文章

52癫痫发作预测的有效双自注意力残差网络

Effective dual self-attentional residual networks for epileptic seizure prediction 摘要 癫痫发作预测作为慢性脑疾病中最具挑战性的数据分析任务之一&#xff0c;引起了众多研究者的广泛关注。癫痫发作预测&#xff0c;可以在许多方面大大提高患者的生活质量&#xff0…

springboot项目配置序列化,反序列化器

介绍本文介绍在项目中时间类型、枚举类型的序列化和反序列化自定义的处理类&#xff0c;也可以使用注解。建议枚举都实现一个统一的接口&#xff0c;方便处理。我这定义了一个Dict接口。枚举类型注解处理这种方式比较灵活&#xff0c;可以让枚举按照自己的方式序列化&#xff0…

三种通用方法——惠普电脑硬盘数据恢复

随着当今数字时代的到来&#xff0c;人们对于计算机硬盘上存储的数据越来越重视。然而&#xff0c;电脑硬盘也时常会发生数据丢失的情况&#xff0c;这时候就需要进行数据恢复。惠普电脑是市面上比较常见的品牌之一&#xff0c;因此本文将从惠普电脑硬盘数据恢复的角度出发&…

【你不知道的事】JavaScript 中用一种更先进的方式进行深拷贝:structuredClone

你是否知道&#xff0c;JavaScript中有一种原生的方法来做对象的深拷贝? 本文我们要介绍的是 structuredClone 函数&#xff0c;它是内置在 JavaScript 运行时中的: const calendarEvent {title: "Builder.io Conf",date: new Date(123),attendees: ["Steve…

EXCEL技能点3-常用技能1

1 引用格式 公式中引用单元格或者区域时,引用的类型可分为以下三种: 绝对引用 相对引用 混合引用 在Excel里&#xff0c;每个单元格都有一个编码&#xff0c;就像人的身份证一样&#xff0c;在Excel里是按照行列进行编码&#xff0c;例如A1就是第一列的第一行。 那么我们想要引…

QEMU启动x86-Linux内核

目录QEMU简介linux启动流程我的环境安装QEMU软件包安装源码安装编译linux内核编译busybox制作initramfs使用QEMU启动linux内核简化命令参考QEMU简介 QEMU&#xff08;quick emulator&#xff09;是一个通用的、开源的硬件模拟器&#xff0c;可以模拟不同硬件架构&#xff08;如…

Docker入门 第四部分

Docker 的优势 Docker 相比于传统虚拟化方式具有更多的优势&#xff1a; Docker 启动快速属于秒级别。虚拟机通常需要几分钟去启动。 Docker 需要的资源更少。Docker 在操作系统级别进行虚拟化&#xff0c;Docker 容器和内核交互&#xff0c;几乎没有性能损耗&#xff0c;性能…

Windows安装Hadoop

当初搭建Hadoop、Hive、HBase、Flink等这些没有截图写文&#xff0c;今为分享特重装。下载Hadoop下载地址&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/以管理员身份运行cmd切换到所在目录执行start winrar x -y hadoop-3.3.4.tar.gz&#xff0c;解压。配置…

刚刚和ChatGPT聊了聊隐私计算

开放隐私计算ChatGPT最近太火了&#xff0c;作为一个背后有庞大数据支撑&#xff0c;而且还在不断进化的人工智能&#xff0c;每个人都想和它聊一聊。我们也不例外&#xff0c;于是刚刚和它聊了聊隐私计算那些事儿。先来几个行业问题&#xff0c;毕竟它背后有所有行业新闻、论文…

Python tkinter 如何实现网站下载工具?将所有数据一键获取

前言 铁汁们有没有想过&#xff0c;如何把几个代码的功能结合到一起呢&#xff1f; 有想过的话&#xff0c;有没有实现过呢&#xff1f; 其实很简单的啊&#xff0c;咱就写一个界面就好了&#xff0c;想要哪个代码运行&#xff0c;鼠标轻轻一点就行 开发环境 python 3.8: 解…

【分布式版本控制系统Git】| Git概述、Git安装、Git常用命令

目录 一&#xff1a;概述 1.1. 何为版本控制 1.2. 为什么需要版本控制 1.3. 版本控制工具 1.4. Git 简史 1.5. Git 工作机制 1.6. Git和代码托管中心 二&#xff1a;安装 2.1. Git安装 三&#xff1a;常用命令 3.1 设置用户签名 3.2 初始化本地库 3.3 查看本地库…

多节点部署一键启动脚本

1 背景 我们在实际项目开发的时候,往往一个大的项目需要很多人协同开发,大家都开发完成在一起联调的时候需要启动很多节点,如果每次都手动去启动所有节点效率非常低,所以我们可以写一个脚本一键启动所有进程,以下统称为节点。 根据节点依赖的环境,一键启动脚本分两种情…

电力电子中逐波限流控制以及dsp实现

逐波限流是指在电力系统运行中&#xff0c;对电力设备进行电流保护的一种措施。它的实现方式是通过对电力系统的电流进行逐波监测和控制&#xff0c;每一波电流都可以独立地进行限制&#xff0c;从而保护电力系统设备不受过载损坏或短路故障的影响。 逐波限流的作用是提高电力…

1. ELK Stack 理论篇之什么是ELK Stack?

ELK Stack 理论篇之什么是ELK Stack?1.1 什么是 ELK Stack&#xff1f;1.2 ELK Stack的发展史1.2.1 Elasticsearch1.2.2 引入 Logstash 和 Kibana&#xff0c;产品更强大1.2.3 社区越来越壮大&#xff0c;用例越来越丰富1.2.4 然后我们向 ELK 中加入了 Beats1.2.5 那么&#x…

es6模块

目录 一、语法说明 二、示例代码 三、运行测试 一.语法说明 JavaScript 现在有两种模块。一种是 ES6 模块&#xff0c;简称 ESM&#xff1b;另一种是 CommonJS 模块&#xff0c;简称 CJS。CommonJS 模块是 Node.js 专用的&#xff0c;与 ES6 模块不兼容。语法上面&#xff0…

XE开发Linux应用(二)-Webservice

新建一个工程。选择如图。继续输入服务名然后就生成对应的单元。增加linux 平台。完善对应的单元代码{ Invokable implementation File for Txaliontest which implements Ixaliontest }unit xaliontestImpl;interfaceuses Soap.InvokeRegistry, System.Types, Soap.XSBuiltIns…

Hive常用内置函数、窗口函数及自定义函数

文章目录一、字符串函数二、数值函数三、日期函数四、其余常用函数五、窗口函数5.1、语法5.2、常用窗口函数六、自定义函数6.1、自定义UDF函数6.2、自定义UDTF函数6.3、将自定义函数导入hive中6.3.1、将项目打成jar包6.3.2、将jar包传入hive目录6.3.3、在hive中加载jar包6.3.4、…

C++回顾(二十五)—— map/multimap容器

25.1 map/multimap的简介 map是标准的关联式容器&#xff0c;一个map是一个键值对序列&#xff0c;即(key,value)对。它提供基于key的快速检索能力。map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入&#xff0c;所以不能指定插入位置。map的…

BN,LN,IN,GN的理解和用法

绿色区域表示将该区域作用域(四种方法都贯穿了w,h维度)&#xff0c;即将该区域数值进行归一化&#xff0c;变为均值为0&#xff0c;标准差为1。BN的作用区域时N,W,H,表示一个batch数据的每一个通道均值为0&#xff0c;标准差为1&#xff1b;LN则是让每个数据的所有channel的均值…

新一代跨平台云备份工具Duplicacy

什么是 Duplicacy &#xff1f; Duplicacy 是一款云备份软件&#xff0c;通过 Duplicacy 可以将视频&#xff0c;图片&#xff0c;文件&#xff0c;注册表等数据备份到云端。Duplicacy 通过客户端加密和最高级别的重复数据删除功能&#xff0c;将您的文件备份到许多云存储。 安…