以下doctest失败:
import logging
logging.basicConfig(level=logging.DEBUG,format='%(message)s')
def say_hello():
'''
>>> say_hello()
Hello!
'''
logging.info('Hello!')
if __name__ == '__main__':
import doctest
doctest.testmod()
这些页面
似乎建议使用
logging.StreamHandler(sys.stdout)
和logger.addHandler(handler)
,但是我在这方面的尝试失败了。 (如果不是很明显,我是python的新手。)请帮助我修复上面的代码,以便测试通过。
,2017年6月4日更新:回答00prometheus'评论:当我提出这个问题时,已接受的use doctest and logging in python program答案似乎不必要地复杂。的确如此,因为这里公认的答案给出了一个更简单的解决方案。根据我的高度偏见,我的问题也比我在原始帖子中已经链接的问题更加清楚。
最佳答案
您需要定义一个“记录器”对象。通常在导入后使用以下命令完成:
import sys
import logging
log = logging.getLogger(__name__)
当您想记录一条消息时:log.info('Hello!')
在像脚本一样运行的代码中,设置basicConfig:if __name__ == '__main__':
import doctest
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout, format='%(message)s')
doctest.testmod()
编辑:好吧,你是对的。它不起作用,但是我知道它起作用了……但是不要这样做!只需使用打印语句或返回您实际需要检查的内容即可。正如您的第二个链接所说,这只是一个坏主意。您不应该检查日志记录输出(用于日志记录)。即使是第二个链接的原始发布者也说,他们通过将记录切换为使用打印来使其工作。但是,这似乎是可行的邪恶代码:
class MyDocTestRunner(doctest.DocTestRunner):
def run(self, test, compileflags=None, out=None, clear_globs=True):
if out is None:
handler = None
else:
handler = logging.StreamHandler(self._fakeout)
out = sys.stdout.write
logger = logging.getLogger() # root logger (say)
if handler:
logger.addHandler(handler)
try:
doctest.DocTestRunner.run(self, test, compileflags, out, clear_globs)
finally:
if handler:
logger.removeHandler(handler)
handler.close()
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG, format='%(message)s')
tests = doctest.DocTestFinder().find(say_hello, __name__)
dt_runner = MyDocTestRunner()
for t in tests:
dt_runner.run(t, out=True)
编辑(续):当尝试第二个链接所建议的内容时,我的尝试也失败了。这是因为内部doctest将sys.stdout重新分配给
self._fakeout
。这就是为什么除了我的hack之外什么都不会起作用的原因。我实际上告诉记录器写入此“伪装”。编辑(回答评论):
这不是链接中的代码。如果这是链接中的代码,我会说这不是一个糟糕的选择,因为它不会做任何太复杂的事情。但是,我的代码使用的是普通用户不应该使用的“私有(private)”内部实例属性。这就是为什么它是邪恶的。
是的,日志记录可以用于测试输出,但是在unittest/doctest中这样做没有多大意义,这可能就是doctest不包含开箱即用的功能的原因。您链接到的TextTest内容全部涉及功能或集成测试。单元测试(和doctest)应该测试单个的小型组件。如果您必须捕获记录的输出以确保您的unittest/doctest是正确的,那么您应该考虑将事情分开或者不在doctest中进行这些检查。
我个人仅将doctests用于简单的示例和验证。主要用于用法示例,因为任何用户都可以看到内联doctest。
编辑(确定最后一个):
相同的解决方案,更简单的代码。此代码不需要您创建自定义运行器。您仍然必须创建默认的运行器和内容,因为您需要访问“_fakeout”属性。如果不以流方式将此属性记录到日志中,则无法使用doctest来检查日志记录输出。
if __name__ == '__main__':
dt_runner = doctest.DocTestRunner()
tests = doctest.DocTestFinder().find(sys.modules[__name__])
logging.basicConfig(level=logging.DEBUG, format='%(message)s', stream=dt_runner._fakeout)
for t in tests:
dt_runner.run(t)
关于python - 如何在记录中使用doctest?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22300869/