当Unittest没有时,鼻子测试失败

时间:2015-03-05 19:06:41

标签: python nose unit-testing

我们看到Python鼻子测试与单元测试的结果之间存在奇怪的差异。以下是导致问题的代码,特别是最后一行:

import logging

class ClassThatLogsBadly:
    log = logging.getLogger(__name__)

    def method_that_logs_badly(self):
        self.log.error('A message', 'Another string')
        return ('I ran')

上面的log是从Python的日志库中检索出来的,并且由于以下原因而调用时会产生问题(来自Python库:logging/__init__.py:328):

def getMessage(self):
    """
    Return the message for this LogRecord.

    Return the message for this LogRecord after merging any user-supplied
    arguments with the message.
    """
    msg = str(self.msg)
    if self.args:
        msg = msg % self.args
    return msg

正如您所看到的,它会尝试将Another string拼接到A message,但后者没有要填充的有效插槽(类型为%s),因此它可以'做到了。这是一个known problem,解决方案是在记录器外部格式化您的东西。但是,我们的问题是测试以确保完成此操作。

对使用unittest或py.test调用日志库的代码运行测试不会导致失败。使用nose运行相同的测试会导致错误,并且测试会失败。我们的构建工作大部分是围绕py.test库构建的,没有让这个测试失败是关注的:我们不确定这是否是由于某种原因的预期行为,这些库之间的处理之间的根本区别是什么,以及通常是什么要做的。

我们正在使用Python 3.4。以下是运行此代码的示例测试:

import logging
import unittest

from mycode import ClassThatLogsBadly

class TestClassThatLogsBadly(unittest.TestCase):
    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_method_that_logs_badly(self):
        clz = ClassThatLogsBadly()
        result = clz.method_that_logs_badly()
        self.assertEquals('I ran', result)

1 个答案:

答案 0 :(得分:2)

由于日志记录配置是全局的,因此为了正确执行日志记录功能,您必须正确配置日志记录。在您的特定情况下,没有在根级别配置处理程序,并且您没有为self.log配置处理程序,因此不会发出任何日志消息(只是"无法找到记录器的处理程序" mycode的&#34)。此消息旨在指示日志记录配置中存在错误,因为您的日志记录树如下所示:

<--""
   Level WARNING
   |
   o<--"mycode"
       Level NOTSET so inherits level WARNING

由于您没有处理程序,因此log.error消息不会执行任何操作,并且在unittestpy.test下运行时,您的代码不会被执行。

nose默认情况下在根级别添加日志捕获处理程序,因此正确配置了最终日志记录配置,并且正确执行了log.error代码。

快速解决方法是在logging.basicConfig()中的代码之上添加ClassThatLogsBadly,或者在初始化时向log类成员添加适当的处理程序。这样,unittest和py.test都会捕获它。

最后,你真的不应该在记录器之外格式化你的东西:如果没有配置级别,你根本不应该进行格式化,只是跳过整个记录加速执行。