python - 元类的 Pytest 夹具
问题描述
有没有一种优雅的方法来定义在类创建之前设置的固定装置,以便元类可以使用它们?更准确地说,在我的用例中,我有一个元类,它根据模块级文件上的一些设置创建类。
设置.py:
SETTING_1 = True
SETTING_2 = False
...
在我的测试中,我想更改夹具中的一些设置,并根据这些设置,我的元类应该创建该类。
我在文档中没有找到关于它的东西。
解决方案
元类以及使用这些元类的类是在class
执行包含语句主体的代码行时创建的。
考虑到这一点,测试类或元类没有什么不同——如果类语句处于模块级别,则类和元类将在模块首次导入时构建——这意味着你必须退出你的(或测试框架的)方法,然后在测试之间重建。
但是如果你确实把它们放在函数体中,它们将在函数被调用时被重建。如果它们是夹具功能,则每次使用夹具时,都会重新构建它们(尽管我认为 Pytest 会做一些夹具缓存 - 请注意这一点)
另一方面,如果元类和使用 then 的类在应用程序代码中,那么您不能将 then 放入要重新创建的函数体中。在这种情况下,您必须精心设计imp.reload
函数的使用——这将使模块级别的代码在每次调用时重新运行。你可以imp.reload(<module>)
在你的fixture函数内部调用,但要小心在fixture运行期间重新绑定对那些元类(和使用它们的类)的任何引用。
所以,如果你的应用程序代码是这样的:
# module_b
from module_a import SETTING_1, SETTING_2
class Meta(type):
def __init__(mcls, name, bases, ns, **kw):
# code that make use of SETTING_1 and SETTING_2
...
class A(metaclass=Meta):
...
测试夹具模块:
import pytest
from unittest import mock
@pytest.fixture
def recreate_metaclass():
from imp import reload
# Drawback: fixtures file have to know and manually imported here
import test_module_1, ...
import module_b
with mock.patch("module_a.SETTING_1", val_1), mock.patch("module_a.SETTING_2" val_2):
module_b = reload(module_b)
# rebind module_a inside test modules
test_module_1.module_b = module_b
...
推荐阅读
- python - 使用远程解释器运行 Python 单元测试时连接到 mysql
- python - 从 Paramiko SSH 打印输出时如何跳过行
- android - 根据数据有两种选择的Android布局设计
- php - 在 CakePHP 2.10.24 上调用未定义的方法 Redis::delete()
- r - 如何根据单元格值创建新行?
- python - 过采样后召回率高,精度低的问题
- cross-browser - Ant Design 浏览器支持
- php - Laravel:升级 JWT 后,会话过期变得过于频繁
- javascript - 如何仅使用 Brunch 构建我的 React Web 应用程序中使用的 JavaScript?
- python - Python:计算迭代次数以实现完美的洗牌?