python - 如何在批量 pytest 执行中使用对象的 __subclasses__() 方法?
问题描述
我正在为一些使用对象__subclasses__()
方法的代码编写单元测试。最终,我试图__subclassess__()
通过命名空间包来跟踪动态导入到我的应用程序中的类。
在某些情况下,我的代码库在 pytest 文件中创建了测试类。我的问题是,当我pytest
在源目录上批量运行时,由于从这些一次性测试类中导入污染,我发现代码中出现故障或错误。这是因为 pytest 运行在运行源树时会维护所有导入。就其自身而言,测试可以通过,但它们会按顺序失败,有时取决于它们运行的顺序。
在我当前的代码分支中,这些__subclasses__()
调用位于应用程序代码中,但我已将它们移到此处进行测试以使用 MVE 进行演示:
在my/example.py
class MyClass(object):
def __init__(self):
pass
class MySubClass(MyClass):
def __init__(self):
super().__init__()
在my/test_subclass.py
from my.example import MyClass
class TestSubClass(MyClass):
def __init__(self):
super().__init__()
def test_TestSubClass():
assert issubclass(TestSubClass, MyClass)
在my/test_subclasses.py
from my.example import MySubClass, MyClass
def test_find_subclasses():
assert all([cls == MySubClass for cls in MyClass.__subclasses__()])
结果,当在我的机器上运行时,test_find_subclasses()
由于发现TestSubClass
when running after测试失败test_subclass.py
:
def test_find_subclasses():
> assert all([cls == MySubClass for cls in MyClass.__subclasses__()])
E assert False
E + where False = all([True, False])
在排序的 pytest 运行期间保持“干净”状态的最佳方法是什么,这样我就可以避免导入错误?
解决方案
正如评论中所讨论的,您可能不想对可能扩展的类型进行硬编码MyClass
,因为您真的无法预测您的应用程序将来需要什么。如果要检查子类化,只需检查它是否有效:
def test_find_subclasses():
assert MySubClass in MyClass.__subclasses__()
更简洁地说,你可以简单地做
def test_find_subclasses():
assert issubclass(MySubClass, MyClass)
话虽如此,您可以从技术上过滤您正在查看的类。在您的特定情况下,您有一个独特的命名约定,因此您可以执行类似的操作
def only_production_classes(iterable):
return [cls for cls in iterable if not cls.__name__.lower().startswith('test')]
def test_find_subclasses():
assert all([cls == MySubClass for cls in only_production_classes(MyClass.__subclasses__())])
您可以only_production_classes
使用其他标准进行定义,例如该类出现的模块:
def only_production_classes(iterable):
return [cls for cls in iterable if not cls.__module__.lower().startswith('test_')]
您不能轻易取消链接已加载的类对象,因此您对“干净”测试环境的想法不太可行。但是您确实可以选择根据数据的导入位置过滤您使用的数据。
推荐阅读
- spring-boot - 关闭 Kafka 侦听器使 JVM 退出
- spring-webflux - 如何测试 EmitterProcessor 是否从 RestController 接收和发出消息?
- python - 如何找到字符串中具有多个“孔”的所有可能排列?
- css - 如何在 ui Material Textfield 中应用我自己的 css 样式?
- git - 无法完成github分享过程
- python - 如何使用 Django Channels 发送 websocket 延迟组消息?
- java - 批量重命名 JAX 绑定文件中的 complexType 元素,即 bindings.xjb?
- elisp - 我需要我的函数使用 LISP while 循环和欧几里得算法返回给定输入的 GCD 我得到的输出是 0
- sql - 更新表时触发重新运行 SQL 查询
- debugging - 调试:无法将预期类型“GHC.Types.Bool”与实际类型“Bool”匹配