以下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()

这些页面
  • doctest & logging
  • use doctest and logging in python program

  • 似乎建议使用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/

    10-12 22:08