【发布时间】:2018-03-30 21:08:18
【问题描述】:
我的代码的可测试性存在问题。这与我的班级布局和我的python包布局有关。
我希望这个问题有以下结果之一:
- 建议更改课程布局,或
- 建议更改包布局,或
- 提示如何在不更改布局的情况下测试这些东西
类层次结构
基类是AuthenticationToken。 HardwareToken 和 Keyfile 这两个类都继承自它。
AuthenticationTokens 可以序列化为字符串,反之亦然。这就是我实现反序列化的方式:
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 token 的所有子类定义。这就是我在__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 时,如何防止Keyfile 和HardwareToken 类被导入?
否则我如何更改类和/或包布局,以便我可以相互独立地导入所有类,同时仍然保留上述好处?
【问题讨论】:
-
为什么你写你的
try_deserialize的方式取决于 Python 加载了哪些模块?听起来这就是这里的根本问题。
标签: python unit-testing serialization package factory-pattern