pytest是一种流行的Python测试框架,支持创建简单的单元测试,也支持创建复杂的功能和集成测试。它提供了一系列有用的功能,能够方便地编写,组织和运行测试用例,并生成丰富的测试报告。
pytest的主要特点包括:
* 自动发现测试用例:pytest会自动查找项目中以test_或者以_test结尾的函数或类,并执行它们。
* 参数化测试:pytest允许使用@pytest.mark.parametrize标记来指定多组输入参数和预期输出值,以简化测试用例的编写和管理。
* 丰富的断言方式:pytest支持多种断言方法,如assert语句、pytest.assert函数、pytest-assume插件以及第三方断言库等,可以让开发人员更轻松地编写和维护测试用例。
* 插件化架构:pytest允许通过插件来扩展其功能,它有很多官方和社区提供的插件,可以帮助开发人员处理日志、代码覆盖率、性能测试等各种任务。
* 可与`unittest`和`nose`无缝对接
* 丰富的测试报告:pytest会自动生成丰富的测试报告,包括测试用例的执行情况、失败原因、覆盖状态等信息,并支持多种输出格式,如HTML,JUnit XML等。
使用pytest编写和运行测试用例相对于其他测试框架来说更加简洁和灵活,同时它也是Python社区中广泛使用的测试工具之一。
## 使用标准库unittest进行单元测试
介绍pytest之前, 先来看一下Python内置的测试库unittest, unittest是Python 标准库的一部分,在安装完Python之后就可以使用, 不需要安装任何其他模块。
Python unittest是Python自带的一个单元测试框架,用于编写和运行测试用例,以确保代码的正确性和可靠性。unittest提供了一系列的工具和断言方法,使得编写测试用例变得更加简单和高效。通过使用unittest,开发人员可以快速运行测试用例并自动化测试过程,从而节省时间和人力成本。
在Python中,unittest常被用作测试框架,它不仅仅用于单元测试,还可以进行集成测试和功能测试。unittest框架提供了丰富的API、测试控制器以及测试加载器,使得测试用例的编写和执行变得更容易。
使用unittest编写测试用例的流程如下:
1. 创建一个测试类,继承unittest.TestCase类。
2. 在测试类中编写测试方法。测试方法必须以test\_开头,用于测试代码的特定功能。
3. 在测试方法中使用断言方法(如assertEqual、assertTrue等)判断代码的执行结果是否符合预期。
4. 运行测试用例,并查看测试报告,根据测试结果进行代码调整和优化。
直接上代码示例:
```python
import unittest
def add(a, b):
return a + b
class TestAdd(unittest.TestCase):
def test_add(self):
self.assertEqual(add(1, 2), 3)
if __name__ == '__main__':
unittest.main()
```
一个测试用例是一个完整的单元测试流程,包括测试前的准备环节、执行测试动作的环节、与期望结果的对比的环节。在`unittest`中,测试用例是通过继承`unittest.TestCase`类来实现的,这个示例中定义了一个名为 `add` 的函数,并且使用了 Python 的 unittest 模块对这个函数进行了测试。
* `TestAdd` 类继承自 `unittest.TestCase` 类,并包含了一个名为 `test_add` 的测试方法。
* 在这个方法中,使用 `self.assertEqual` 方法来检查 `add` 函数是否正确计算了加法。最后,使用 `unittest.main()` 运行测试。
运行成功的界面如下:
![](https://img.kancloud.cn/5e/9e/5e9ef94dfa2489628e358538eac85813_1015x108.png)
如果运行失败是怎么显示的呢? 修改上面的 ` self.assertEqual(add(1, 2), 3)` => ` self.assertEqual(add(1, 2), 4)` 让测试失败, 失败的界面如下:
![](https://img.kancloud.cn/89/ec/89ec9f451785e2553f5979c1d9c36ca1_989x236.png)
## 安装 pytest
如果没有安装`pytest`,可以使用`pip`来安装:
```
pip install pytest
```
如果不确定有没有安装`pytest`, 可以使用 `pip list` 查看安装的模块, 比如:
![](https://img.kancloud.cn/19/36/1936013581c79057fb4858b44fd69adf_354x339.png)
pytest 安装成功的界面如下:
![](https://img.kancloud.cn/15/14/15149123c5f6c8c606737733f4f9264e_962x376.png)
## 使用 pytest 编写单元测试
`pytest`工具会自动找到文件名和函数名都以`test`开头的测试用例。
这里定义一个加法函数并对这个函数进行测试, 首先创建一个名为`test_sample.py`的文件,内容如下:
```python
def add(a, b):
return a + b
def test_add():
assert add(1, 2) == 3
```
## 运行pytest 测试
命令行切换到包含`test_sample.py`的目录,运行`pytest`命令,`pytest`会运行所有发现的测试,并产生一个测试报告,运行的效果如下图“
![](https://img.kancloud.cn/67/3d/673db3f888d1af91060179b9d0ae97b5_1373x157.png)
测试失败情况下,pytest 怎么显示呢?`pytest`会详细地显示哪个测试失败,以及失败的详细原因。这里故意定义一个执行错误的函数test_add2(), 代码如下:
```python
def add(a, b):
return a + b
def test_add():
assert add(1, 2) == 3
def test_add2():
assert add(1, 2) == 4
```
执行后的效果如下图:
![](https://img.kancloud.cn/62/0f/620f16a063f3653ddd2145c9408638b5_1378x359.png)
除了在命令行控制台运行和查看pytest的结果外, 也可以在VS Code 的Testing的活动栏,运行和查看结果。效果如下图:
![](https://img.kancloud.cn/33/ae/33aef3d0b6950742d297a0d29e941b14_1244x407.png)
需要注意的是: 点击Testing的活动栏之后, 需要选择测试的框架为 pytest。
## 使用pytest 运行功能测试
`pytest`是一个非常灵活强大的 Python 测试框架,它既能进行单元测试,也能进行功能测试, 通常与 Flask(轻量级的 Python web 框架)一起使用。
Flask 模块需要先安装, 安装方式是 `pip install flask`, 安装完成之后就可以编写Flask代码了,
这里定义一个 Flask Web 应用,并且需要测试当访问`/hello`时是否能返回 "Hello, World!", 代码如下:
```
from flask import Flask
def create_app():
app = Flask(__name__)
@app.route('/hello')
def hello():
return 'Hello, World!'
return app
if __name__ == '__main__':
app = create_app()
app.run()
```
运行之后通过浏览器访问的效果如下图:
![](https://img.kancloud.cn/94/af/94af1672ba354e557491f9dc2adaf45f_1038x406.png)
接下来, 使用`pytest`来进行功能测试,使用Flask的测试客户端来模拟访问, 定义测试的文件test_app.py , 内容如下:
```
import pytest
from app import create_app
@pytest.fixture
def client():
app = create_app()
app.config['TESTING'] = True
with app.test_client() as client:
yield client
def test_hello(client):
response = client.get('/hello')
assert response.data == b'Hello, World!'
```
* 使用 @pytest.fixture 装饰器定义了一个名为 client 的测试夹具。该夹具在测试过程中可以作为参数传递给测试函数。在这个夹具函数中,创建了一个测试用的 Flask 应用,并将其配置为测试模式。
* `with`语句创建了一个上下文环境,以确保客户端在每次测试运行前都被正确地初始化并且在测试完成后被清理掉。
* `yield`语句使客户端对象在测试用例中可用,例如向应用程序发出 HTTP 请求。
* `test_client()`方法是 Flask 测试客户端的简单实现。它可以模拟客户端发送 HTTP 请求,并对响应进行验证。
使用`test_client()`方法可以快速编写 Flask 应用程序的单元测试,而无需启动真实的服务器或处理实际的网络通信。在测试中,你可以发送请求并检查响应,以确保应用程序按预期工作。
* 定义了一个名为 test_hello 的测试函数,并将上述夹具 client 作为参数传递进去。在测试函数中,使用 client.get('/hello') 发起了一个 GET 请求,并检查返回值是否等于 b'Hello, World!'。如果返回值和预期值不一致,那么测试将会失败。
* 在 Python 中,当字符串前面带有前缀`b`时,表示这是一个 bytes 类型的字符串,而不是普通的 str 类型。bytes 类型的字符串在 Python 中是一种原生的二进制序列类型,它的每个字符都是一个字节,可以存储任意的二进制数据。
在 Flask 应用中,当使用`response.data`获取 HTTP 响应的内容时,返回的是 bytes 类型的内容,因为 HTTP 响应的内容是以二进制字节流的形式传输的。因此,在进行 HTTP 响应内容的比较时,需要使用 bytes 类型的字符串,而不是普通的 str 类型字符串。
运行测试的效果如下图:
![](https://img.kancloud.cn/58/ad/58ad1868e925bef70a5bff21f3f48b14_1450x544.png)
## 参考
* pytest官方站点: [https://docs.pytest.org/en/7.4.x/](https://docs.pytest.org/en/7.4.x/)
*****
*****
- 前言
- 1.入门篇
- Python介绍
- 安装与使用
- Python开发利器之VS Code
- 模块安装
- 命令行
- 一次Python无法安装模块的问题探索与解决之旅
- 命令运行
- Conda
- 下载地址
- 2.基础篇
- 基础语法
- 输入与输出
- with as的用法
- 注释
- Python命令行参数
- 编码
- 变量类型
- 列表遍历
- 运算符
- 表达式语句
- 条件
- 循环
- 日期和时间
- 函数
- 高级语法
- @符号-装饰器
- 模块和包
- name
- init.py
- 错误和异常
- 面向对象
- 3.专题篇
- 常用功能
- Python 字符串连接
- python web
- Python CGI编程
- Python OAuth2
- 认证 Flask-HTTPAuth
- 常用命令
- 内置函数
- dir()
- print(f)
- 标准模块
- sys
- pickle-数据序列化
- os
- IO(输入输出)
- 键盘输入
- 文件读写
- 测试
- Python测试框架之pytest快速入门
- pytest-bdd快速示例和问题解决
- 基于pytest-bdd的项目目录结构和命名规范
- python BDD 的相关概念
- Behave介绍和快速示例
- Python BDD之Behave测试报告
- Python BDD 框架比较之 pytest-bdd vs behave
- pytest进阶
- Flask + pytest测试
- 参考网址
- pytest-bdd进阶
- hehave进阶
- 测试路径
- python + selunium
- HTML 根据多层CSS 查找元素
- 等待执行
- 使用text 查找 span
- pytest如何在控制台输出
- 4.问题篇
- pip pip3 及区别
- TypeError: can only concatenate str (not "NoneType") to str
- 5.实战篇
- matplotlib-绘图包
- 导入类
- 命名规范
- 模块查找
- 6.进阶篇
- Flask
- Flask介绍
- Flask扩展模块
- Flask-Login
- 问题
- Jinja2
- Flask-RESTful
- Flask-JWT-Extended
- WSGI
- Flask-SQLAlchemy
- 部署
- Flask VS Django
- Flask Web
- Flask + Vue
- Flask实战
- Flask 标准目录结构
- Blueprints
- 参考
- FastAPI 测试
- https 证书 Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate