繁体   English   中英

如何对该Python类进行单元测试?

[英]How to unit test this python class?

我的代码的可测试性有问题。 这与我的类布局和python包布局有关。

我希望此问题的下列结果之一:

  1. 改变班级布局的建议,或
  2. 更改包装布局的建议,或
  3. 提示如何在不更改布局的情况下测试这些东西

类层次结构

基类是AuthenticationToken 这两个类HardwareTokenKeyfile继承自它。

AuthenticationToken可以序列化为字符串,反之亦然。 这是我实现反序列化的方式:

class AuthenticationToken(object):

    @classmethod
    def try_deserialize(cls, spec: str):
        for subclass in cls.__subclasses__():
            token = subclass.try_deserialize(spec)
            if token:
                return token
        return None

python包布局

我每个班级只有一个文件,并将它们放在包目录中

package
+-- __init__.py
+-- authentication_token.py
+-- hardware_token.py
+-- keyfile.py

现在,我更喜欢引用诸如package.Keyfile类的类,而不是package.keyfile.Keyfile 在我可以使用try_derialize方法之前,Python还会看到Authentication令牌的所有子类定义。 这就是为什么我将所有类导入__init__.py

from .authentication_token import AuthenticationToken
from .hardware_token import HardwareToken
from .keyfile import Keyfile

可测试性问题

现在,我想对AuthenticationToken类进行单元测试,而不引用其子类。 这个想法是编写一个TestAutheticationToken类,并在测试期间将其用作单个子类:

import unittest
from package import AuthenticationToken

class TestSubclass(AuthenticationToken):
    pass

class TestAuthenticationToken(unittest.TestCase):

    # This test fails
    def test_bad_case(self):
        should_be_none = AuthenticationToken.try_deserialize("Keyfile")
        self.assertIsNone(should_be_none)

if __name__ == '__main__':
    unittest.main()

该测试失败,因为try_deserialize创建了一个Keyfile类型的对象。 这是因为__init__.py被求值。 如果我直接从模块中导入AuthenticationToken也是如此:

from package.authentication_token import AuthenticationToken

问题

所以问题是:如何在测试AuthenticationToken时防止导入KeyfileHardwareToken类?

否则,如何更改类和/或程序包的布局,以便我可以彼此独立地导入所有类,同时仍保留上述好处?

该代码很难测试,因为令牌提供者列表是隐式的 这取决于已加载的模块。 我建议您至少给出令牌提供者的明确列表选项 要么要求在启动时注册令牌提供者,要么为令牌提供者列表提供可选参数。

这是我能想到的最简单的更改:

class AuthenticationToken(object):

    @classmethod
    def try_deserialize(cls, spec: str, token_providers=None):
        if token_providers is None:
            token_providers = cls.__subclasses__()
        for subclass in token_providers:
            token = subclass.try_deserialize(spec)
            if token:
                return token
        return None

现在您的常规代码保持不变,并且您的测试可以如下所示:

    def test_bad_case(self):
        should_be_none = AuthenticationToken.try_deserialize(
            "Keyfile",
            token_providers=[TestSubclass])
        self.assertIsNone(should_be_none)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM