Python 中的模拟函数
unittest.mock 或 Mock 函数是一个用于在 Python 中进行测试的库,它允许您用模拟对象替换被测系统的组件,并对这些部件的使用方式做出断言。
unittest.mock 提供了一个核心模拟类,消除了在整个测试套件中创建大量存根的必要性。
执行流程后,您可以断言使用了哪些方法或属性以及调用它们的参数。 您还可以指定返回值并以通常的方式设置所需的属性。
此外,Mock 提供了一个 patch()
装饰器,可以处理测试范围内的补丁模块和类级别属性,以及一个辅助哨兵,用于创建独特的对象。
Mock 是为与 unittest 一起使用而创建的,它基于操作到断言模式而不是大多数模拟框架中使用的记录到重播。 对于以前版本的 Python,有一个 unittest.mock 的反向移植。
在 Python 中设置和安装 Pytest Mock
与unittest相比,pytest不是Python内置的包,需要安装。 这可以通过在终端中输入以下命令来安装。
pip install pytest
请注意,unittest 的最佳实践也适用于 pytest,例如:
- 需要一个 tests/ 目录来包含所有单元测试。
- 文件名必须始终以 tests_ 开头。
- 函数名称必须始终以测试开头。
必须遵守命名标准,以便检查员可以找到执行的单元测试。
在使用之前需要安装 pytest-mock。 下面是如何使用pip安装它:
pip install pytest-mock
这是 Pytest 的插件。 因此,如果您还没有这样做,它将安装 Pytest。
在 Python 中模拟一个函数
首先,创建一个简单的函数 get_os()
来告诉我们是使用 Windows 还是 Linux 作为操作系统。
创建一个名为 app.py 的文件,如下所示:
from time import sleep
def isWindows():
# This sleep can be some complex operation
sleep(5)
return True
def get_os():
return 'Windows is the current OS' if isWindows() else 'Linux is the current OS'
此函数使用 isWindows 函数来确定当前操作系统是否为 Windows。 假设这个isWindows函数比较复杂,运行需要几秒,这里我们可以模拟这个运行缓慢的函数,每次调用时让程序进入休眠5秒。
以下是 get_os()
函数的 pytest:
创建一个名为 test_app.py 的文件来进行 pytest:
from app import get_os
def test_get_os():
assert get_os() == 'Windows is the current OS'
由于 get_os()
调用较慢的函数 isWindows,因此测试进行得很慢。 这可以在下面执行 pytest 的输出中看到。
耗时 5.02 秒,可能因当前实例而异。
单元测试需要快速,我们应该能够在几秒钟内执行数百个测试。 测试套件被一个需要 5 秒的测试减慢了速度,所以应用 mocking 让我们的生活更轻松。
如果我们修补运行缓慢的函数,我们可以在不停留 5 秒的情况下验证 get_os() 函数的行为。
让我们用 pytest-mock 模拟这个函数。
Pytest-mock 在 Python 的集成模拟构造之上提供了一个称为模拟器的夹具和一个良好的接口。 您可以通过从中调用 mock 和 patch 函数并将它们作为参数发送给您的测试函数来使用模拟器。
如果您希望 isWindows 函数返回 True 而无需等待那宝贵的 5 秒,我们可以按如下方式对其进行修补:
mocker.patch('app.isWindows', return_value=True)
在这里,您必须将 isWindows 称为 app.isWindows,因为它是应用程序模块中的函数。 如果我们只修补 isWindows,它会尝试修补 test_app 文件中一个名为 isWindows 的函数,该函数不存在。
格式始终是 <module_name>.<function_name>
,知道如何正确模拟是必不可少的。
下面介绍补丁修改后的测试功能:
from app import get_os
# using'mocker' fixture provided by pytest-mock
def test_get_os(mocker):
# mocking the slow-going function and returning True always
mocker.patch('app.isWindows', return_value=True)
assert get_os() == 'Windows is the current OS'
现在,当您运行此测试时,它会更快地完成。
如您所见,测试只用了 0.02 秒,因此我们成功地修补了运行缓慢的函数并加速了测试套件。
模拟的另一个优点是你可以让模拟函数返回任何东西,甚至可以让它引发错误来测试你的代码在这些场景中的处理方式。
这里,如果要测试isWindows返回False的情况,写如下测试:
from app import get_os
def test_os_isLinux(mocker):
mocker.patch('app.isWindows', return_value=False) # set the return value to be False
assert get_os() == 'Linux is the current OS'
模拟器附带的模拟和补丁都是函数范围的,这意味着它们只能与特定函数一起使用。 因此,不同测试中同一功能的补丁之间不会有任何冲突。
总结
模拟是用模拟替换您正在测试的应用程序组件的做法,模拟是该组件的虚拟实现。 通过模拟,我们可以获得诸如提高速度、运行速度更快的测试非常有益、避免在测试过程中产生不良副作用等好处。
相关文章
Pandas DataFrame DataFrame.shift() 函数
发布时间:2024/04/24 浏览次数:133 分类:Python
-
DataFrame.shift() 函数是将 DataFrame 的索引按指定的周期数进行移位。
Python pandas.pivot_table() 函数
发布时间:2024/04/24 浏览次数:82 分类:Python
-
Python Pandas pivot_table()函数通过对数据进行汇总,避免了数据的重复。
Pandas read_csv()函数
发布时间:2024/04/24 浏览次数:254 分类:Python
-
Pandas read_csv()函数将指定的逗号分隔值(csv)文件读取到 DataFrame 中。
Pandas 多列合并
发布时间:2024/04/24 浏览次数:628 分类:Python
-
本教程介绍了如何在 Pandas 中使用 DataFrame.merge()方法合并两个 DataFrames。
Pandas loc vs iloc
发布时间:2024/04/24 浏览次数:837 分类:Python
-
本教程介绍了如何使用 Python 中的 loc 和 iloc 从 Pandas DataFrame 中过滤数据。
在 Python 中将 Pandas 系列的日期时间转换为字符串
发布时间:2024/04/24 浏览次数:894 分类:Python
-
了解如何在 Python 中将 Pandas 系列日期时间转换为字符串