如何在抽象类(ABC)或Protocol类中跳过doctest避免运行失败
抽象类/Protocol文档字符串doctest兼容方案
以下方案均可保留doctest格式的同时,避免抽象类未实现方法导致的运行报错:
方案1:单条文档字符串用例独立跳过
在不需要运行的doctest行末尾添加# doctest: +SKIP标记,doctest运行时会自动跳过该行执行,仅保留文档展示效果:
from abc import ABC, abstractmethod class MyABC(ABC): """我的文档说明. 此处为所有实现类的通用使用场景示例: 示例: >>> a = MyABC() # doctest: +SKIP >>> a.do_something() # doctest: +SKIP 'some expected behaviour' """ @abstractmethod def do_something(self): pass class MyClass(MyABC): def do_something(self): return 'some expected behaviour'
如果希望doctest实际可运行验证逻辑正确性,也可以直接在示例中引用具体实现类,同时标注这是抽象类所有实现的通用行为,无需跳过用例:
class MyABC(ABC): """我的文档说明. 以下为所有MyABC子类的通用使用示例: 示例: >>> # 任意继承MyABC的实现类实例都符合以下行为逻辑 >>> a = MyClass() >>> a.do_something() 'some expected behaviour' """
方案2:全局统一跳过所有抽象类/Protocol类的doctest
如果需要批量过滤所有抽象类、Protocol类的文档字符串测试,可以自定义doctest的查找规则:
标准库doctest实现:
import doctest from abc import ABC from typing import Protocol def is_abstract_or_protocol(obj): # 判断对象是否为抽象类或Protocol类 if isinstance(obj, type): return issubclass(obj, ABC) or issubclass(obj, Protocol) return False # 自定义测试查找器,跳过抽象类和Protocol类的docstring测试 class CustomDocTestFinder(doctest.DocTestFinder): def find(self, obj, name=None, module=None, globs=None, extraglobs=None): tests = super().find(obj, name, module, globs, extraglobs) return [test for test in tests if not is_abstract_or_protocol(test.obj)] # 运行测试时使用自定义查找器 if __name__ == "__main__": finder = CustomDocTestFinder() runner = doctest.DocTestRunner() for test in finder.find(__import__(__name__)): runner.run(test)
pytest运行时配置:
在项目的conftest.py中添加钩子过滤对应类型的测试:
from abc import ABC from typing import Protocol def pytest_doctest_prepare_content(content, obj): if isinstance(obj, type) and (issubclass(obj, ABC) or issubclass(obj, Protocol)): # 抽象类和Protocol类的doctest内容直接返回空,跳过测试 return "" return content
内容的提问来源于stack exchange,提问作者AlexLoss
相关产品推荐
相关产品推荐

