简体   繁体   English

py.test将消息和测试结果/断言记录到单个文件中

[英]py.test logging messages and test results/assertions into a single file

I am starting to work with py.test at the moment for a new project. 我现在开始使用py.test进行新项目。 We are provisioning Linux servers and I need to write a script to check the setup and configuration of these servers. 我们正在配置Linux服务器,我需要编写一个脚本来检查这些服务器的设置和配置。 I thought that py.test is a good way to implement these tests and it is working quite fine until now. 我认为py.test是实现这些测试的好方法,直到现在它才能正常工作。

The problem I face right now is that I need a log file at the end of these tests showing some log messages for each test and the result of the test. 我现在面临的问题是,在这些测试结束时我需要一个日志文件,显示每个测试的一些日志消息和测试结果。 For the log messages I use logger: 对于日志消息,我使用logger:

logging.basicConfig(filename='config_check.log', level=logging.INFO)
pytest.main()
logging.info('all done')

As an example test I have this: 作为示例测试我有这个:

def test_taintedKernel():
    logging.info('checking for tainted kernel')
    output = runcmd('cat /proc/sys/kernel/tainted')
    assert output == '0', 'tainted kernel found'

So in my logfile I would like an output like that: 所以在我的日志文件中我想要一个像这样的输出:

INFO:root:checking for tainted kernel
ERROR:root:tainted kernel found
INFO:root:next test
INFO:root:successful
INFO:root:all done

But I cannot get the test results into the logfile, instead I get the standard output on stdout after the tests: 但是我无法将测试结果输入到日志文件中,而是在测试后获得stdout上的标准输出:

======================================= test session starts =======================================
platform linux2 -- Python 2.6.8 -- py-1.4.22 -- pytest-2.6.0
collected 14 items 

test_basicLinux.py .............F

============================================ FAILURES =============================================
_______________________________________ test_taintedKernel ________________________________________

    def test_taintedKernel():
        logging.info('checking for tainted kernel')
        output = runcmd('cat /proc/sys/kernel/tainted')
>       assert output == '0', 'tainted kernel found'
E       AssertionError: tainted kernel found

test_basicLinux.py:107: AssertionError
=============================== 1 failed, 13 passed in 6.07 seconds ===============================

This may be quite confusing for the users of my script. 对于我的脚本用户来说,这可能会让人感到困惑。 I tried to get into logger and pytest_capturelog since it was mentioned here quite often but I am for sure doing something wrong since I just don't get it. 我试图进入logger和pytest_capturelog,因为这里经常提到它,但我确实做错了,因为我没有得到它。 Maybe just a lack of understanding how this really works. 也许只是缺乏理解这是如何工作的。 Hope you can give me some hints on this. 希望你能给我一些暗示。 Please let me know if anything is missing here. 如果这里遗漏了什么,请告诉我。

Thanks in advance for your help, 在此先感谢您的帮助,

Stephan 斯蒂芬

pytest's job is to capture output and present it to the operator. pytest的工作是捕获输出并将其呈现给操作员。 So, rather than trying to get pytest to do the logging the way you want it, you can build the logging into your tests. 因此,您可以构建日志记录到测试中,而不是尝试让pytest以您希望的方式进行日志记录。

Python's assert command just takes a truth value, and a message. Python的assert命令只需要一个真值和一条消息。 So, instead of using a bare assert in your tests, you can write a small function that does the logging if the value is false (which is the same condition that triggers the assert to fail), then calls the assert, so that you get the logging you want, plus the assert-driven behavior that creates the console output. 因此,不是在测试中使用裸assert ,而是可以编写一个小函数来执行日志记录,如果值为false(这与触发断言失败的条件相同),然后调用断言,以便获得您想要的日志记录,以及创建控制台输出的断言驱动行为。

Here's a small test file using such a function: 这是一个使用这样一个函数的小测试文件:

# test_foo.py
import logging

def logAssert(test,msg):
    if not test:
        logging.error(msg)
        assert test,msg

def test_foo():
    logging.info("testing foo")
    logAssert( 'foo' == 'foo', "foo is not foo")

def test_foobar():
    logging.info("testing foobar")
    logAssert( 'foobar' == 'foo', "foobar is not foo")

Here's the test runner, very similar to yours: 这是测试运行器,非常类似于你的:

# runtests.py
import logging
import pytest

logging.basicConfig(filename='config_check.log', level=logging.INFO)
logging.info('start')
pytest.main()
logging.info('done')

Here's the output: 这是输出:

# python runtests.py
==== test session starts ========================
platform linux2 -- Python 2.6.6 -- py-1.4.22 -- pytest-2.6.0
collected 2 items

test_foo.py .F

========== FAILURES ============================
________ test_foobar __________________________

    def test_foobar():
        logging.info("testing foobar")
>       logAssert( 'foobar' == 'foo', "foobar is not foo")

test_foo.py:14:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

test = False, msg = 'foobar is not foo'

    def logAssert(test,msg):
        if not test:
            logging.error(msg)
>           assert test,msg
E           AssertionError: foobar is not foo

test_foo.py:6: AssertionError    ==== 1 failed, 1 passed in 0.02 seconds =======

And here's the log that gets written: 这是写入的日志:

# cat config_check.log 
INFO:root:start
INFO:root:testing foo
INFO:root:testing foobar
ERROR:root:foobar is not foo
INFO:root:done

Since version 3.3, pytest supports live logging to terminal and file. 从版本3.3开始, pytest支持对终端和文件的实时日志记录。 Example test module: 示例测试模块:

import logging
import os


def test_taintedKernel():
    logging.info('checking for tainted kernel')
    output = os.system('cat /proc/sys/kernel/tainted')
    assert output == 0, 'tainted kernel found'

Configure of logging to file can be done in pytest.ini : 记录到文件的配置可以在pytest.ini完成:

[pytest]
log_file = my.log
log_file_level = DEBUG
log_file_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_file_date_format=%Y-%m-%d %H:%M:%S

Running the test yields as usual: 像往常一样运行测试产生:

$ pytest
======================================================= test session starts ========================================================
...
collected 1 item                                                                                                                   

test_spam.py .                                                                                                               [100%]

===================================================== 1 passed in 0.01 seconds =====================================================

Now check the written log file: 现在检查写入的日志文件:

$ cat my.log
2019-07-12 23:51:41 [    INFO] checking for tainted kernel (test_spam.py:6)

For more examples of emitting live logs to both terminal and log file, check out my answer to Logging within py.test tests . 有关将终端日志发送到终端和日志文件的更多示例,请查看我在py.test测试中记录日志的答案。

Reference: Live Logs section in pytest docs. 参考: pytest docs中的Live Logs部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM