Pytest 自动化测试框架

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

2、指定一些测试用例测试运行,可以使用-k模糊匹配

pytest -k example

3、通过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

4、通过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

5、预先知道测试用例会失败,但是不想跳过,需要显示提示信息,使用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

6、对测试用例进行多组数据测试,每组参数都能够独立执行一次(可以避免测试用例内部执行单组数据测试不通过后停止测试)

@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的基本使用,有兴趣的可以去看看官方文档,官方文档中还提到了如内置固件的使用,常用测试的场景等等。

最后: 可以在公众号:伤心的辣条 ! 免费领取一份216页软件测试工程师面试宝典文档资料。以及相对应的视频学习教程免费分享!,其中包括了有基础知识、Linux必备、Shell、互联网程序原理、Mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。

如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!喜欢软件测试的小伙伴们,可以加入我们的测试技术交流扣扣群:914172719(里面有各种软件测试资源和技术讨论)


好文推荐

转行面试,跳槽面试,软件测试人员都必须知道的这几种面试技巧!

面试经:一线城市搬砖!又面软件测试岗,5000就知足了…

面试官:工作三年,还来面初级测试?恐怕你的软件测试工程师的头衔要加双引号…

什么样的人适合从事软件测试工作?

那个准点下班的人,比我先升职了…

测试岗反复跳槽,跳着跳着就跳没了…

Pytest 自动化测试框架相关推荐

  1. pytest自动化测试框架,真正做到从0到1由浅入深详细讲解【万字级】

    目录 嗨咯铁汁们,很久不见,我还是你们的老朋友凡叔,这里也感谢各位小伙伴的点赞和关注,你们的三连是我最大的动力哈,我也不会辜负各位的期盼,这里呢给大家出了一个pytest自动化测试框架由浅入深详细讲解 ...

  2. 一、Pytest自动化测试框架 — Pytest和unittest测试框架原理

    目录 前言 ###文章内容有配套的学习视频和笔记都放在了文章末尾### 1.什么是单元测试框架 2.单元测试框架主要做什么 3.单元测试框架和自动化测试框架有什么关系 4.Pytest测试框架说明 5 ...

  3. Selenium+Pytest自动化测试框架实战

    前言 selenium自动化+ pytest测试框架 本章你需要 一定的python基础--至少明白类与对象,封装继承 一定的selenium基础--本篇不讲selenium,不会的可以自己去看sel ...

  4. 【python做接口测试的学习记录day10——pytest自动化测试框架之接口加密】

    通常出于安全性考虑,开发会对接口参数进行加密,加密方式有很多种,例如MD5.Base64.RSA双密钥加密方式等,下面我们以MD5加密方式的登录接口为例,此接口对密码进行了加密,如果测试时直接使用未加 ...

  5. Pytest自动化测试框架

    自动化测试 测试环境搭建httpbin.org开源接口网站 http://www.httpbin.org/这个网站是开放的用来做测试用网站,外网注意看脸进 笔者本来想搭一个docker+wsl2+gi ...

  6. pytest自动化测试框架详解+mark标记+fixture夹具

    介绍 pytest是python的一种单元测试框架,同自带unittest框架类似,功能,效率更强大 特点: 1. 非常容易上手,入门简单,丰富的文档 2. 支持参数化 3. 执行测试用例的过程中,跳 ...

  7. pytest自动化测试框架基础篇

    一.单元测试框架 1.什么是单元测试框架 单元测试框架是在自动化测试或者白盒测试中对软件的最小单元(函数,方法)进行测试的框架. 2.单元测试框架分类 python:unittest.pytest 3 ...

  8. 【python做接口测试的学习记录day9——pytest自动化测试框架之yaml数据驱动封装】

    之前我们的框架中,如果有多个测试用例,则需要在yaml文件中写入多个用例,而每个用例可能不同的仅仅只是个别参数值,这就导致很多重复代码,现在我们使用数据驱动就可以解决这个问题了. 我依旧采用之前的登录 ...

  9. 八、Pytest自动化测试框架 — Pytest测试报告

    1.pytest-html插件 Pytest可以通过命令⾏⽅式,⽣成xml/html格式的测试报告,并存储于⽤户指定路径. 需要用到pytest-html插件. 安装⽅式:pip install py ...

最新文章

  1. 浅析flex中的焦点focus
  2. Navicat 连接MySQL数据库 报错2059 - authentication plugin 'caching_sha2_password'的解决办法...
  3. Linux多进程开发(三)进程创建之守护进程的学习
  4. C语言中的void指针
  5. android进程 系统启动过程 android boot sequence
  6. 实践:使用FLANN.LSH进行检索
  7. MIPCache 域名升级
  8. 高数学习笔记:计算方向导数
  9. mysql c++ 存数组,c++读取数据文件到数组的实例
  10. Go语言(golang)开源项目大全
  11. 《htmlxhtml权威指南》部分标签语义学习
  12. 面试题--------9、mysql的drop delete truncate 分别在什么场景下使用
  13. Mac苹果电脑加密视频播放器使用教程
  14. Linux stty 指令设置串口参数
  15. word中的方括号怎么删_Word如何批量删除习题括号内答案
  16. HTTP VS HTTPS
  17. 已知坐标增量求坐标方位角_详解坐标计算的方式!值得收藏!
  18. Ubuntu 22.04 LTS (Jammy Jellyfish) Daily Build安装镜像PC ARM Raspberry Pi
  19. 手写笔迹鉴别系统(1)
  20. 菜鸟教程:Python练习实例1~10

热门文章

  1. c语言模拟计算机程序阶乘,辽宁省计算机二级(C语言)模拟试卷B(无答案).doc
  2. 电脑格式化的危害_防止硬盘被格式化的六大方法
  3. c语言成绩统计与学籍管理源码,[源码和文档分享]基于C语言的学生成绩管理系统...
  4. 使用Spyder控制台(console)执行带参数脚本和带参数的debug模式
  5. NSURLErrorDomain 对照
  6. 读光OCR-文字识别技术解读与应用案例分析
  7. Linux系统安装oracle时,orainstRoot.sh,root.sh脚本的作用。
  8. service $anchorScroll
  9. JS 正则(RegExp)
  10. Aspectj快速上手代码示例之Before,After,Around