Pytest和Unittest测试框架的区别?

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

Pytest 安装
pip安装:

pip install pytest

测试安装成功:

pytest --helppy.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 pytesttest_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 = 0with pytest.raises(ZeroDivisionError) as e:num = 1/0exc_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 == 1assert 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 .......")yieldprint("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 itemtest_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):passdef 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 itemstest_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 .......")yieldprint("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 itemstest_example.py::test1 Connect Database in .......
PASSED                                            [ 50%]test1test_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)yieldprint('\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 itemstest_example.py::test_api[param0] 
Succeed to connect redis:6379
PASSED                                 [ 50%]
Succeed to close redis:6379test_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的基本使用,有兴趣的可以去看看官方文档,官方文档中还提到了如内置固件的使用,常用测试的场景等等。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

在这里插入图片描述

软件测试面试小程序

被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!

涵盖以下这些面试题板块:

1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux

6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础

 

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

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

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

相关文章

C#使用自定义的比较器对版本号(编码)字符串进行排序

给定一些数据&#xff0c;如下所示: “1.10.1.1.1.2”, “1.1”, “2.2”, “1.1.1.1”, “1.1.3.1”, “1.1.1”, “2.10.1.1.1”, “1.1.2.1”, “1.2.1.1”, “2.5.1.1”, “1.10.1.1”, “1.10.2.1”, “1.11.3.1”, “1.11.12.1”, “1.11.11.1”, “1.11.3.1”, “1”, “…

Matlab进阶绘图第26期—双向堆叠图

双向堆叠图是一种特殊的堆叠图&#xff0c;其通过在两个方向构建堆叠图&#xff0c;从而可以对两种类别的同名及综合属性进行全方位的比较。 由于Matlab中未收录双向堆叠图的绘制函数&#xff0c;因此需要大家自行设法解决。 本文分享一个简单的双向堆叠图的绘制方法&#xf…

矩阵与图的关系:矩阵是图,图是矩阵

原文连接 线性代数最被低估的一个事实&#xff1a;矩阵是图&#xff0c;图是矩阵。 将矩阵编码为图是一种取巧的行为(cheat code)&#xff0c;它其使复杂的行为变得易于研究。 让我告诉你怎么做&#xff01; 1. 非负矩阵的有向图 &#xff08;The directed graph of a nonne…

验证码识别DLL ,滑块识别SDK,OCR图片转文字,机器视觉找物品

验证码识别DLL ,滑块识别SDK 你们用过哪些OCR提取文字&#xff0c;识图DLL&#xff0c;比如Opencv,Labview机器视觉找物品之类&#xff1f;

高等数学之洛必达法则

第二种 由小到大 其他形式 解题步骤 分子分母的式子是乘积的时候可以用等价无穷小替换&#xff0c;如果是-则不允许

数据分析实战│时间序列预测

时间序列预测问题是一类常见的数据分析问题。数据中往往包含时间标签,这类问题往往根据过去一段时间的数据,建立能够比较精确地反映序列中所包含的动态依存关系的数学模型,并对未来的数据进行预测。 01、问题描述及数据挖掘目标 本案例给出二战时期的某气象站温度记录值,通…

Golang Gorm 高级查询之where查询

插入测试数据 package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm" )type Student struct {ID int64Name string gorm:"size:6"Age intEmail *string }func (*Student) TableName() string {return "student&q…

ChatGPT帮助提升工作效率和质量:完成时间下降40%,质量评分上升 18%

自ChatGPT去年11月发布以来&#xff0c;人们就开始使用它来协助工作&#xff0c;热心的用户利用它帮助撰写各种内容&#xff0c;从宣传材料到沟通话术再到调研报告。 两名MIT经济学研究生近日在《科学》杂志上发表的一项新研究表明&#xff0c;ChatGPT可能有助于减少员工之…

RedisTemplate和StringRedisTemplate的区别、对比

学习 Jedis、RedisTemplate、StringRedisTemplate之间的比较 博客中提到&#xff1a;一. Jedis是Redis官方推荐的面向Java的操作Redis的客户端。 二. RedisTemplate,StringRedisTemplate是SpringDataRedis中对JedisApi的高度封装。SpringDataRedis相对于Jedis来说可以方便地更…

maven工程的目录结构

https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html maven工程的目录结构&#xff1a; 在maven工程的根目录下面&#xff0c;是pom.xml文件。此外&#xff0c;还有README.txt、LICENSE.txt等文本文件&#xff0c;便于用户能够…

精密图纸被窃,知名手表品牌Seiko遭BlackCat勒索软件攻击

据BleepingComputer消息&#xff0c;日本著名手表制造商Seiko在7月末遭到了网络攻击&#xff0c;8月21日&#xff0c;BlackCat&#xff08;又名ALPHV&#xff09;勒索软件组织在其网站上宣布对这起攻击事件负责。 8 月 10 日&#xff0c;Seiko发布了一份数据泄露通知&#xff0…

IPv4,IPv6,TCP,路由

主要回顾一下TCP&#xff0f;IP的传输过程&#xff0c;在这个过程中&#xff0c;做了什么事情 ip : 网际协议,IP协议能让世界上任意两台计算机之间进行通信。 IP协议的三大功能&#xff1a; 寻址和路由传递服务&#xff1a;不可靠&#xff08;尽最大努力交付传输数据包&…

基于ssm校园快递代取系统源码和论文

基于ssm校园快递代取系统源码和论文056 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;…

matlab实现输出的几种方式(disp函数、fprintf函数、print函数)

matlab实现输出的几种方式&#xff08;disp函数、fprintf函数、print函数&#xff09; 输出为文本、文件、打印 1、disp函数 显示变量的值&#xff0c;如果变量包含空数组&#xff0c;则会返回 disp&#xff0c;但不显示任何内容。 矩阵 A [1 0]; disp(A)结果 字符串 S …

「UG/NX」Block UI 选择特征SelectFeature

✨博客主页何曾参静谧的博客📌文章专栏「UG/NX」BlockUI集合📚全部专栏「UG/NX」NX二次开发「UG/NX」BlockUI集合「VS」Visual Studio「QT」QT5程序设计「C/C+&#

银河麒麟arm版服务器安装docker

安装 在线安装&#xff1a;输入下面命令&#xff0c;等待安装完成即可 #关闭防火墙 systemctl stop firewalld.service systemctl disable firewalld.serviceyum install -y docker# 修改docker拉取源为国内 rm -rf /etc/docker mkdir -p /etc/docker touch /etc/docker/da…

Jetpack Compose UI架构

Jetpack Compose UI架构 引言 Jetpack Compose是我职业生涯中最激动人心的事。它改变了我工作和问题思考的方式&#xff0c;引入了易用且灵活的工具&#xff0c;几乎可轻松实现各种功能。 早期在生产项目中尝试了Jetpack Compose后&#xff0c;我迅速着迷。尽管我已有使用Co…

小项目01:尿试纸条没有放到位问题检测

目录 一、完整代码1.1 返回值含义1.2 main1.3 bvdetector.h1.4 bvdetector.cpp 二、图例1. 原图scrImg2.灰度图img_gray3.二值图binImg4.反二值图invImg 一、完整代码 1.1 返回值含义 0:表示正常&#xff08;有角度&#xff09;&#xff1b;1&#xff1a;表示没有图片&#x…

C语言实现:从RSA PEM文件中提取私钥n/e/d/p/q/dp/dq/qp因子

我们知道使用openssl命令行openssl rsa -in test_priv.pem -text 即可实现从私钥PEM文件中提取私钥因子&#xff1a;n/e/d/p/q/dp/dq/qp. 那么如何用C语言实现呢&#xff1f;如何在代码中实现呢&#xff1f; #include <stdio.h> #include <stdlib.h> #include &l…

el-button实现按钮,鼠标移入显示,移出隐藏

2023.8.18今天我学习了 如何实现鼠标移入显示按钮&#xff0c;鼠标移出隐藏按钮。 效果如图&#xff1a; 鼠标移入时&#xff1a; 鼠标移出时&#xff1a; mouseover //鼠标移入事件 mouseleave //鼠标移出事件 原本我是想直接在el-button写入这两个方法&#xff0c;但是elem…