关于python:如何在Py Test中打印到控制台?

How to print to console in Py Test?

我正在尝试将TDD(测试驱动开发)与pytest结合使用。当我使用print时,pytest不会到控制台。

我用pytest my_tests.py来运行它。

documentation似乎认为它应该默认工作:http://pytest.org/latest/capture.html

但是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import myapplication as tum

class TestBlogger:

    @classmethod
    def setup_class(self):
        self.user ="alice"
        self.b = tum.Blogger(self.user)
        print"This should be printed, but it won't be!"

    def test_inherit(self):
        assert issubclass(tum.Blogger, tum.Site)
        links = self.b.get_links(posts)
        print len(links)   # This won't print either.

没有任何内容被打印到我的标准输出控制台(只是正常的进度和通过/失败的测试数量)。

我正在测试的脚本包含打印:

1
2
3
class Blogger(Site):
    get_links(self, posts):
        print len(posts)   # It won't get printed in the test.

unittest模块中,默认情况下会打印所有内容,这正是我需要的。但是,我希望出于其他原因使用pytest

有人知道如何显示打印声明吗?


默认情况下,py.test捕获标准输出的结果,以便控制它如何输出。如果不这样做,它会在没有测试所打印文本的上下文的情况下快速输出大量文本。

但是,如果一个测试失败,它将在结果报告中包含一个部分,显示在该特定测试中按标准输出的内容。

例如,

1
2
3
4
5
6
7
def test_good():
    for i in range(1000):
        print(i)

def test_bad():
    print('this should fail!')
    assert False

结果输出如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> py.test tmp.py
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items

tmp.py .F

=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________

    def test_bad():
        print('this should fail!')
>       assert False
E       assert False

tmp.py:7: AssertionError
------------------------------- Captured stdout --------------------------------
this should fail!
====================== 1 failed, 1 passed in 0.04 seconds ======================

注意Captured stdout部分。

如果希望在执行时看到print语句,可以将-s标志传递给py.test。但是,请注意,这有时很难解析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
>>> py.test tmp.py -s
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items

tmp.py 0
1
2
3
... and so on ...
997
998
999
.this should fail!
F

=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________

    def test_bad():
        print('this should fail!')
>       assert False
E       assert False

tmp.py:7: AssertionError
====================== 1 failed, 1 passed in 0.02 seconds ======================

使用-s选项将打印所有功能的输出,这可能太多。

如果您需要特定的输出,您提到的文档页面提供了一些建议:

  • 在函数末尾插入assert False,"dumb assert to make PyTest print my stuff",您将看到由于测试失败而产生的输出。

  • 您有通过pytest传递给您的特殊对象,您可以将输出写到一个文件中,以便稍后检查它,比如

    1
    2
    3
    4
    5
    6
    def test_good1(capsys):
        for i in range(5):
            print i
        out, err = capsys.readouterr()
        open("err.txt","w").write(err)
        open("out.txt","w").write(out)

    您可以在单独的选项卡中打开outerr文件,让编辑器自动为您刷新,或者执行一个简单的py.test; cat out.txtshell命令来运行测试。

  • 这是一种相当老套的做事方式,但也可能是你需要的东西:毕竟,TDD意味着你把东西搞得一团糟,准备好后保持干净和安静。


    我需要在PyTest逐字静音的情况下打印关于跳过测试的重要警告。

    我不想通过测试来发送信号,所以我进行了如下黑客攻击:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    def test_2_YellAboutBrokenAndMutedTests():
        import atexit
        def report():
            print C_patch.tidy_text("""
    In silent mode PyTest breaks low level stream structure I work with, so
    I cannot test if my functionality work fine. I skipped corresponding tests.
    Run `py.test -s` to make sure everything is tested."""
    )
        if sys.stdout != sys.__stdout__:
            atexit.register(report)

    atexit模块允许我在PyTest释放输出流后打印内容。输出如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ============================= test session starts ==============================
    platform linux2 -- Python 2.7.3, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
    rootdir: /media/Storage/henaro/smyth/Alchemist2-git/sources/C_patch, inifile:
    collected 15 items

    test_C_patch.py .....ssss....s.

    ===================== 10 passed, 5 skipped in 0.15 seconds =====================
    In silent mode PyTest breaks low level stream structure I work with, so
    I cannot test if my functionality work fine. I skipped corresponding tests.
    Run `py.test -s` to make sure everything is tested.
    ~/.../sources/C_patch$

    即使在PyTest处于静默模式时,也会打印消息,如果使用py.test -s运行资料,则不会打印消息,因此已经对所有内容进行了很好的测试。


    根据Pytest文档,pytest --capture=sys应该可以工作。如果您想在测试中捕获标准,请参考Capsys夹具。


    简短回答

    使用-s选项:

    1
    pytest -s

    详细回答

    来自文档:

    During test execution any output sent to stdout and stderr is captured. If a test or a setup method fails its according captured output will usually be shown along with the failure traceback.

    PyTest具有选择权--capture=method,其中method是每种测试捕获方法,可以是下列之一:fdsysnoPyTest也有-s选项,这是--capture=no的快捷方式,这是允许您在控制台中查看打印语句的选项。

    1
    2
    pytest --capture=no     # show print statements in console
    pytest -s               # equivalent to previous command

    设置捕获方法或禁用捕获

    有两种方法可以执行捕获:

  • 文件描述符(fd)级别捕获(默认):将捕获到操作系统文件描述符1和2的所有写入。

  • 系统级捕获:只捕获对python文件sys.stdout和sys.stderr的写入。不捕获对文件描述符的写入。

  • 1
    2
    3
    pytest -s            # disable all capturing
    pytest --capture=sys # replace sys.stdout/stderr with in-mem files
    pytest --capture=fd  # also point filedescriptors 1 and 2 to temp file