跳转到主要内容

简单的但功能强大的日志行断言和验证。

项目描述

日志断言

Python package

什么?

Python unittests的简单日志断言机制。

为什么?

正如民意所诉,您还必须测试您程序中的日志调用。

使用logassert现在非常简单。

太棒了!我该如何使用它?

以两种非常不同的方式暴露了相同的功能,一种更适合pytest语义,另一种更适合经典单元测试。

对于pytest

您只需在测试参数中声明logs,它就像任何其他固定装置一样工作。

然后您只需检查(使用assert,如通常与pytest一样)是否特定行出现在特定级别的日志中。

示例

def test_bleh(logs)
    (...)
    assert "The meaning of life is 42" in logs.debug

实际上,您所写的行是一个正则表达式,所以您可以完全做到(如果您不确定生命的意义是什么)

    assert "The meaning of life is \d+" in logs.debug

指示的字符串将在日志行中进行搜索,不需要与整行完全匹配。如果您需要这样,只需像使用任何正则表达式一样指示即可。

    assert "^The meaning of life is \d+$" in logs.debug

以类似的方式,您还可以表达希望检查它是否位于日志行的开头或结尾。

注意:检查的消息是最终的,在日志系统将所有指示的参数替换到指示的字符串之后。

如果您想验证某个文本已记录,无论级别如何,只需这样做

    assert "The meaning of life is 42" in logs.any_level

要验证某些文本未被记录,只需使用Python的语法!例如

    assert "A problem happened" not in logs.error

但是我不喜欢正则表达式,我想要确切的字符串

那么您只需从logassert导入Exact,并用它来包装字符串。

例如,在这种情况下,..意味着正好两个点,完全没有正则表达式的语义。

    assert Exact("The meaning of life is ..") in logs.any_level

无论如何,我喜欢旧的搜索多个字符串的行为

那么您可能想从logassert导入Multiple,并在每个调用中包装不同的字符串以获得经典行为。

例如

    assert Multiple("life", "meaning", "42") in logs.any_level

如果我想要检查没有任何内容被记录呢?

最简单的方法是使用可以从logassert导入的NOTHING验证器。

    assert NOTHING in logs.debug

注意,使用否定(...NOTHING not in logs...)没有意义:在测试级别知道“已记录某些内容”并没有真正的作用,您应该改进测试以具体验证什么被记录。

打破“每行障碍”

有时验证多个连续记录的行并确保它们按顺序记录,构建一个“复合消息”是有用的。

为了控制记录的行,您可以使用接收所有要验证的行的Sequence辅助工具(默认情况下为正则表达式,但您也可以使用其他辅助工具)。

    assert Sequence(
        "Got 2 errors and \d+ warnings:",
        Exact("  error 1: foo"),
        Exact("  error 2: bar"),
    ) in logs.debug

示例

记录之后...

    person = "madam"
    item = "wallet"
    logger.debug("Excuse me %s, you dropped your %s", person, item)

...以下测试将仅通过

    assert "Excuse me .*?, you dropped your wallet" in logs.debug

然而,以下将失败(不同的文本)...

    assert "Excuse me .*?, you lost your wallet" in logs.debug

...在您的测试中产生此消息

assert for regex 'Excuse me .*?, you lost your wallet' check in DEBUG, failed; logged lines:
      DEBUG     'Excuse me madam, you dropped your wallet'

这个也会失败(不同的级别)...

    assert "Excuse me .*?, you dropped your wallet" in logs.info

...在您的测试中产生此消息

assert for regex 'Excuse me .*?, you dropped your wallet' check in INFO, failed; logged lines:
       DEBUG     'Excuse me madam, you dropped your wallet'

一个更复杂的示例,有多个日志行,并且有特定的断言

    logger.info("Starting system")
    places = ['/tmp/', '~/temp']
    logger.debug("Checking for config XYZ in all these places %s", places)
    logger.warning("bad config XYZ")

    assert "bad config XYZ" in logs.debug

看看测试失败消息是如何非常有帮助的

assert for regex 'bad config XYZ' check in DEBUG, failed; logged lines:
       INFO      'Starting system'
       DEBUG     "Checking for config XYZ in all these places ['/tmp/', '~/temp']"
       WARNING   'bad config XYZ'

关于重复验证呢?

有时需要验证某物仅记录一次(例如欢迎消息)。在这种情况下,使用reset方法非常有用。

参见以下测试序列

def test_welcoming message(logs):
    logger.info("foo")  # first log! it should trigger the welcoming message
    assert "Welcome" in logs.info

    logs.reset()
    logger.info("foo")  # second log! it should NOT trigger the welcoming message
    assert "Welcome" not in logs.info

对于经典测试用例

您只需要调用此模块的setup(),传入测试用例实例和您想要监督的记录器。

例如

class MyTestCase(unittest.TestCase):
    """Example."""

    def setUp(self):
        logassert.setup(self, 'mylogger')

在示例中,mylogger是您要监督的记录器的名称。如果您的代码的不同子系统使用不同的记录器记录,则该测试器不会注意到。

然后,为了使用它,只需调用assertLogged方法及其家族,传入您想要找到的所有字符串。这是向后兼容的默认行为。

示例

    def test_blah(self):
        (...)
        self.assertLoggedDebug('secret', 'life', '42')

该行将检查“secret”、“life”和“42”在同一个记录调用中都被记录,在DEBUG级别。

因此,如果您记录了这些,则测试将通过

logger.debug("The secret of life, the universe and everything is %d", 42)

注意,检查的消息是带有所有参数替换的消息。

但是,如果您记录了以下任何内容,则测试将失败(第一个因为它缺少一个字符串,第二个因为它有错误的日志级别):

logger.debug("The secret of life, the universe and everything is lost")
logger.info("The secret of life, the universe and everything is 42")

我可以测试什么?

您将可以使用多个断言方法

  • self.assertLogged:将检查字符串是否被记录,无论级别如何

  • self.assertLoggedLEVEL(其中LEVEL是错误、警告、信息或调试之一):将检查字符串是否在特定级别被记录。

  • self.assertNotLogged:将检查字符串没有被记录,无论级别如何。

  • self.assertNotLoggedLEVEL(其中LEVEL可以是Error、Warning、Info或Debug之一):将检查字符串是否未在该特定级别上记录。

不错!但是...

如果您需要帮助,或有任何问题,或者发现了任何问题,请在此处打开工单

感谢您抽出宝贵时间。

项目详情


下载文件

下载适用于您平台文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分发

logassert-7.tar.gz (13.9 kB 查看哈希值)

上传时间:

构建分发

logassert-7-py3-none-any.whl (12.6 kB 查看哈希值)

上传时间: Python 3

支持者