简介
测试是软件开发过程中的必要环节,它确保代码按预期行为运行且没有缺陷。在Python中,pytest
是一个非常流行的测试框架,它比标准的unit test
模块(这是一个内置的Python测试框架,是标准库的一部分)提供了多个优势。pytest
包括更简单的语法、更好的输出、强大的固定件以及丰富的插件生态系统。本教程将指导您设置Flask应用程序,集成pytest
固定件,并使用pytest
编写单元测试。
先决条件
在开始之前,您需要以下内容:
- 一台运行Ubuntu的服务器和一个具有sudo权限的非root用户以及一个活动的防火墙。要了解如何设置,请从这个列表中选择您的发行版,并遵循我们的初始服务器设置指南。请确保使用受支持的Ubuntu版本。
-
熟悉Linux命令行。您可以查看这个关于Linux命令行入门的指南。
-
对Python编程和Python中的
pytest
测试框架有基本了解。您可以参考我们的教程PyTest Python测试框架,了解更多关于pytest
的信息。 -
在您的Ubuntu系统中安装Python 3.7或更高版本。要了解如何在Ubuntu上运行Python脚本,可以参考我们的教程
如何在Ubuntu上运行Python脚本
。
为什么pytest
是比unittest
更好的选择
pytest
相较于内置的unittest
框架有几个优点:
-
Pytest允许你用更少的样板代码编写测试,使用简单的断言语句而不是
unittest
需要的更冗长的方法。 -
它提供了更详细和可读的输出,使识别测试失败的原因和位置变得更加容易。
-
Pytest 的 fixtures 允许更灵活和可重用的测试设置,比 unittest 的
setUp
和tearDown
方法更为灵活。 -
它使得用多个输入集运行同一测试函数变得容易,而在
unittest
中这一点并不那么直观。 -
Pytest 拥有丰富的插件集合,扩展了它的功能,从代码覆盖工具到并行测试执行。
-
它会自动发现符合命名约定的测试文件和函数,节省了管理测试套件的时间和精力。
鉴于这些优势,pytest
通常是被现代 Python 测试的首选工具。现在我们来设置一个 Flask 应用程序,并使用 pytest
编写单元测试。
步骤1 – 设置环境
Ubuntu 24.04 默认带有 Python 3。打开终端,运行以下命令以确保 Python 3 已安装:
如果您的计算机上已经安装了 Python 3,上述命令将返回 Python 3 的当前版本。如果不安装,您可以运行以下命令来安装 Python 3:
接下来,您需要在系统上安装 pip
包安装器:
一旦安装了 pip
,让我们安装 Flask。
步骤2 – 创建 Flask 应用程序
首先,让我们创建一个简单的 Flask 应用程序。为您的项目创建一个新的目录,并进入该目录:
现在,让我们创建并激活一个虚拟环境来管理依赖关系:
使用pip
安装Flask:
现在,让我们创建一个简单的Flask应用程序。创建一个名为app.py
的新文件,并添加以下代码:
此应用程序有三个路由:
/
:返回一个简单的“你好,Flask!”消息。/about
:返回一个简单的“这是关于页面”消息。/multiply/<int:x>/<int:y>
:将两个整数相乘并返回结果。
要运行应用程序,请执行以下命令:
从上述输出中,您可以注意到服务器正在http://127.0.0.1
上运行,并监听端口5000
。打开另一个Ubuntu控制台,并依次执行以下curl
命令:
- GET:
curl http://127.0.0.1:5000/
- GET:
curl http://127.0.0.1:5000/about
- GET:
curl http://127.0.0.1:5000/multiply/10/20
让我们来了解一下这些GET请求的作用:
-
curl http://127.0.0.1:5000/
:
这个命令向我们的Flask应用的根路由(“/”)发送一个GET请求。服务器回应了一个包含消息“Hello, Flask!”的JSON对象,展示了我们主页路由的基本功能。 -
curl http://127.0.0.1:5000/about
:
这个命令向/about
路由发送一个GET请求。服务器回应了一个包含消息“This is the About page”的JSON对象。这表明我们的路由正常工作。 -
curl http://127.0.0.1:5000/multiply/10/20
:
这个命令向/multiply
路由发送一个带有两个参数(10和20)的GET请求。服务器将这些数字相乘,并回应一个包含结果(200)的JSON对象。这证明了我们的乘法路由能够正确处理URL参数并进行计算。
这些GET
请求允许我们与Flask应用程序的API端点交互,获取信息或在服务器上触发操作,而无需修改任何数据。它们对于获取数据、测试端点功能以及验证路由是否如预期响应非常有用。
让我们看看这些GET
请求的实际操作:
步骤3 – 安装pytest
并编写您的第一个测试
现在您已经有了一个基本的Flask应用程序,让我们安装pytest
并编写一些单元测试。
使用pip
安装pytest
:
创建一个tests目录来存储您的测试文件:
现在,让我们创建一个名为test_app.py
的新文件,并添加以下代码:
让我们来分解这个测试文件中的功能:
-
@pytest.fixture def client()
:
这是一个pytest固定器,为我们的Flask应用创建一个测试客户端。它使用app.test_client()
方法创建一个可以向我们的应用发送请求的客户端,而无需运行实际服务器。yield
语句允许在测试中使用客户端,并在每个测试后正确关闭。 -
def test_home(client):
这个函数测试我们应用的首页路由(
/
)。它使用测试客户端向该路由发送GET请求,然后断言响应状态码为200(OK),并且JSON响应与预期消息匹配。 -
def test_about(client):
与
test_home
类似,这个函数测试关于路由(/about
)。它检查状态码是否为200,并验证JSON响应内容。 -
def test_multiply(client):
这个函数测试有效的乘法输入路由(
/multiply/3/4
)。它检查状态码是否为200,并且JSON响应包含乘法结果的正确值。 -
def test_multiply_invalid_input(client)
:
这个函数测试了 multiply 路由在接收无效输入(multiply/three/four
)时的行为。它检查状态码是否为 404(未找到),这是当路由无法将字符串输入匹配到所需的整数参数时的预期行为。 -
def test_non_existent_route(client)
:
这个函数测试了当访问一个不存在的路由时应用程序的行为。它向/non-existent
发送一个 GET 请求,该路由在我们的 Flask 应用程序中未定义。测试断言响应状态码为 404(未找到),以确保我们的应用程序能够正确处理对未定义路由的请求。
这些测试涵盖了我们 Flask 应用程序的基本功能,确保每个路由对有效输入做出正确响应,并且 multiply 路由能够正确处理无效输入。通过使用 pytest
,我们可以轻松运行这些测试,以验证我们的应用程序是否按预期工作。
步骤 4 – 运行测试
要运行测试,请执行以下命令:
默认情况下,pytest
发现过程将递归扫描当前文件夹及其子文件夹中以 “test_” 开头或以 “_test” 结尾的文件。然后执行这些文件中找到的测试。您应该会看到类似于:
这表明所有测试都已成功通过。
步骤 5: 在 pytest
中使用固定值
固定值是用于向测试提供数据或资源的函数。它们可用于设置和拆除测试环境,加载数据或执行其他设置任务。在 pytest
中,固定值是通过使用 @pytest.fixture
装饰器来定义的。
以下是如何增强现有固定值的示例。更新客户端固定值以使用设置和拆除逻辑:
此设置在测试输出中添加了打印语句,以展示设置和拆除阶段。如有需要,这些可以被实际的资源管理代码替换。
让我们再次尝试运行测试:
`-v`标志增加了详细程度,而`-s`标志允许打印语句在控制台输出中显示。
你应该看到以下输出:
步骤6:添加一个失败测试用例
让我们在现有的测试文件中添加一个失败测试用例。修改`test_app.py`文件,在文件末尾添加以下函数,以实现一个结果错误的失败测试用例:
让我们来分解`test_multiply_edge_cases`函数并解释每个部分的作用:
-
零的测试:
这个测试检查乘法函数是否正确处理零的乘法。当任何数乘以零时,我们期望结果为0。这是一个重要的边界情况,需要进行测试,因为有些实现可能会在零的乘法上有问题。 -
大数测试:
此测试验证乘法函数是否能够处理大数而不溢出或精度问题。我们将两个一百万的值相乘,期望结果为一百亿。这个测试至关重要,因为它检查了函数的上限能力。请注意,如果服务器的实现不当处理大数,这可能表明需要大数库或不同的数据类型。 -
故意失败的测试:
这个测试被故意设置为失败。它检查2 * 3是否等于7,这是错误的。这个测试旨在展示失败的测试在测试输出中看起来如何。这有助于理解如何识别和调试失败的测试,这是测试驱动开发和调试过程中的一项基本技能。
通过包含这些边缘案例和故意失败,您不仅测试了您的乘法路由的基本功能,还测试了它在极端条件下的行为和错误报告能力。这种测试方法有助于确保我们应用程序的健壮性和可靠性。
让我们再试一次运行测试:
您应该看到以下输出:
上述失败消息表明,在tests/test_app.py
文件中的test_multiply_edge_cases
测试失败了。具体来说,这个测试函数中的最后一个断言导致了失败。
这个故意的失败很有用,它展示了测试失败是如何报告的,以及失败消息中提供了哪些信息。它显示了失败发生的确切行,期望值和实际值,以及两者之间的差异。
在实际场景中,你会修复代码使测试通过,或者在预期结果不正确时调整测试。然而,在本案例中,失败是为了教育目的而故意设置的。
结论
在本教程中,我们介绍了如何使用pytest
为 Flask 应用程序设置单元测试,集成pytest
fixtures,并展示了测试失败时的情况。通过遵循这些步骤,你可以确保 Flask 应用程序的可靠性和可维护性,减少错误并提高代码质量。
Source:
https://www.digitalocean.com/community/tutorials/unit-test-in-flask