pytest 中单例类的拆解

Boa*_*oaz 5 python singleton pytest

我在应用程序中使用了一个单例类(单例在元类中实现)

class Singleton(type):
    def __init__(self, *args, **kwargs):
        self.__instance = None
        super(Singleton, self).__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super(Singleton, self).__call__(*args, **kwargs)
            return self.__instance
        else:
            return self.__instance


class ApplicationContext(object):
    __metaclass__ = Singleton

    def __init__(self, db):
        pass
Run Code Online (Sandbox Code Playgroud)

现在我希望这个对象位于 py.test 上下文中 - 但我希望它在某些测试中不受干扰。我试图创建一个拆卸功能,但它似乎没有用......

@pytest.fixture
def context(db, request):
    _context = ApplicationContext(db)

    def teardown():
        print 'teardown'
        del _context   #this is not working. What should be done here?

    request.addfinalizer(teardown)
    return _context
Run Code Online (Sandbox Code Playgroud)

Bas*_*hur 0

很难说出你的意思:

现在我希望这个对象位于 py.test上下文中- 但我希望它在某些测试中不受影响

由于我们讨论的是单例,我假设您希望夹具可用,但并非在所有测试中都有效。在这种情况下,Pytest 固定装置可以有一个范围,引用文档中的相关部分:

需要网络访问的装置取决于连接性,并且创建起来通常非常耗时。扩展前面的示例,我们可以向 @pytest.fixture 调用添加一个 scope="module" 参数,以导致 smtp_connection 固定函数(负责创建到预先存在的 SMTP 服务器的连接)每个测试模块仅调用一次(默认是每个测试函数调用一次)。因此,测试模块中的多个测试函数将各自接收相同的 smtp_connection 夹具实例,从而节省时间。范围的可能值为:函数、类、模块、包或会话。

因此,在您的情况下,我假设 的(默认)范围function应该执行您想要的操作:固定装置在模块(范围)中可用,但您必须在每个函数中显式使用它(不妨碍)。

也许我问错了你的问题,但另一种方法可能是在你的固定装置中模拟单例ApplicationContext