【问题标题】:Pytest fixture for metaclass元类的 Pytest 夹具
【发布时间】:2019-07-13 19:46:06
【问题描述】:

有没有一种优雅的方式来定义在类创建之前设置的固定装置,以便元类可以使用它们? 更准确地说,在我的用例中,我有一个元类,它根据模块级文件上的一些设置创建类。

settings.py:

SETTING_1 = True
SETTING_2 = False
...

在我的测试中,我想更改夹具中的一些设置,根据这些设置,我的元类应该创建类。

我在文档中没有找到关于它的内容。

【问题讨论】:

  • 元类会在您的测试代码或应用程序代码中使用固定装置吗?

标签: python pytest metaclass


【解决方案1】:

元类以及使用这些元类的类是在执行包含class 语句主体的代码行时创建的。

考虑到这一点,测试类或元类没有什么不同 - 如果类语句处于模块级别,则类和元类将在模块首次导入时构建 - 这意味着您必须退出您(或测试框架的)在测试之间重建的方式。

但是如果你确实把它们放在函数体中,它们将在函数被调用时被重建。如果它们是夹具功能,则每次使用夹具时,都会重新构建它们(尽管我认为 Pytest 会做一些夹具缓存 - 请注意这一点)

另一方面,如果元类和使用 then 的类在应用程序代码中,那么您不能将 then 放入要重新创建的函数体中。在这种情况下,您必须精心设计imp.reload 函数的使用——这将使模块级别的代码在每次调用时重新运行。你可以在你的fixture函数中调用imp.reload(<module>),但要小心在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
        ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多