ChatGPT解决这个技术问题 Extra ChatGPT

如何在pytest中打印到控制台?

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

我正在使用 pytest my_tests.py 运行它。

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

但:

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.

没有任何东西打印到我的标准输出控制台(只是正常的进度和多少测试通过/失败)。

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

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

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

有谁知道如何使打印语句得到显示?

也许标准输出正在被覆盖。如果使用 sys.stdout.write("Test") 会发生什么? sys.__stdout__.write("Test") 怎么样?后者应始终写入系统定义的标准输出,它应该是控制台。如果这两个命令做不同的事情,那么标准输出正在改变;如果他们做同样的事情,那么问题是别的。

t
tbekolay

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

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

例如,

def test_good():
    for i in range(1000):
        print(i)

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

结果如下:

>>> 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。但是,请注意,这有时可能难以解析。

>>> 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 ======================

嗯...仍然没有记录我的打印语句
l
lmiguelvargasf

简答

使用 -s 选项:

pytest -s

详细解答

the docs

在测试执行期间,任何发送到 stdout 和 stderr 的输出都会被捕获。如果测试或设置方法失败,其捕获的输出通常会与失败回溯一起显示。

pytest 具有选项 --capture=method,其中 method 是每次测试的捕获方法,可以是以下之一:fdsysnopytest 还具有选项 -s,它是 --capture=no 的快捷方式,该选项可让您在控制台中查看打印语句。

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

设置捕获方法或禁用捕获

pytest 可以通过两种方式执行捕获:

文件描述符 (FD) 级别捕获(默认):将捕获到操作系统文件描述符 1 和 2 的所有写入。 sys 级别捕获:仅会捕获对 Python 文件 sys.stdout 和 sys.stderr 的写入。不捕获对文件描述符的写入。

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

d
dmitry_romanov

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

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

在函数末尾插入 assert False,“愚蠢的断言让 PyTest 打印我的东西”,由于测试失败,您将看到您的输出。您有 PyTest 传递给您的特殊对象,您可以将输出写入文件以供稍后检查,例如 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) 您可以在单独的选项卡中打开 out 和 err 文件并让编辑器自动为你刷新它,或者做一个简单的 py.test; cat out.txt shell 命令来运行你的测试。

这是一种相当老套的做事方式,但可能是你需要的东西:毕竟,TDD 意味着你把东西弄乱了,当它准备好时让它保持干净和安静:-)。


我尝试了版本 1. 使用 pytest 3.8.1 不幸的是它只打印测试功能块,而不是打印语句的输出:( 还有更多技巧吗?
@UV - 而不是使用 print() 函数,您应该将要打印的变量或消息放在 声明语句中的逗号之后。例如 assert False, what_are_you 将在 pytest 报告中“打印”出 what_are_you 的值。
S
Sacha

这是我所知道的将单个语句打印到 sys.stdout 的最简洁的方式(无需人为地使您的测试失败或启用 -s 选项) - 您可以看到您想要的特定输出,仅此而已:

将内置参数 capsys 添加到您的测试函数中。 (这意味着您将 capsys 添加到参数列表中,例如

def test_function(existing_parameters, capsys):

在您的代码中,只需插入:

with capsys.disabled():
   print("this output will not be captured and go straight to sys.stdout")

请参阅 https://buildmedia.readthedocs.org/media/pdf/pytest/latest/pytest.pdf(2.11 如何捕获 stdout/stderr 输出)。


这应该是首选答案!它似乎可以完美地工作而没有副作用。
就这样我可以看到我的打印日志。我没有通过 -s 选项看到打印日志,也没有通过创建文件看到打印日志。
如果“将内置参数 capsys 添加到您的测试函数中”会有所帮助。为新手提供了更多细节......我不知道这意味着什么。
编辑队列已满,无法编辑:实际上只是 def test_something(capsys): ... 请参阅 docs.pytest.org/en/6.2.x/fixture.html
@BerndWechner,谢谢你的建议,我已经编辑了答案。
d
dmitry_romanov

我需要在 PyTest 完全静音一切时打印有关跳过测试的重要警告。

我不想发送信号的测试失败,所以我做了如下黑客攻击:

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 发布输出流之后打印内容。输出如下所示:

============================= 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 运行内容则打印消息,因此一切都已经过很好的测试。


非常适合输出自定义测试指标。
J
Jesse W at Z - Given up on SE

根据 pytest docspytest --capture=sys 应该可以工作。如果您想在测试中捕获标准输出,请参阅 capsys 夹具。


当终端需要打印变量时,它对我有用...
要在每次运行 pytest 时传递 --capture 选项,请在文件 pytest.ini (documentation) 的 [pytest] 部分中添加行 addopts = --capture=tee-sys
d
dummyDev

我最初来到这里是为了找到如何在 VSCode 的控制台中打印 PyTest,同时从那里运行/调试单元测试。这可以通过以下 launch.json 配置来完成。给定 .venv 虚拟环境文件夹。

    "version": "0.2.0",
    "configurations": [
        {
            "name": "PyTest",
            "type": "python",
            "request": "launch",
            "stopOnEntry": false,
            "pythonPath": "${config:python.pythonPath}",
            "module": "pytest",
            "args": [
                "-sv"
            ],
            "cwd": "${workspaceRoot}",
            "env": {},
            "envFile": "${workspaceRoot}/.venv",
            "debugOptions": [
                "WaitOnAbnormalExit",
                "WaitOnNormalExit",
                "RedirectOutput"
            ]
        }
    ]
}

w
wlo

您也可以通过 Pycharm GUI 进行设置:转到 Run > Edit Configurations。在那里,选择您要为其启用打印语句的测试并将 -s 添加到 Additional Arguments 字段。

我这样做是因为虽然我主要使用 Pycharm 调试器来调试我的 pytest 函数(即通过 GUI),但我的特定用例还需要我知道代码中其他地方发生了什么,打印语句可以派上用场那。


A
Amar Kumar

我通常使用这个命令:-

pytest -v -rs --html=report.html --self-contained-html test_Suite.py -s

上述命令还会生成一个 report.html 文件,其中所有打印语句都被捕获并保存。最后的 -s 也会在终端中显示打印语句。


A
Arka Mukherjee

已经有很多好的答案了,但我想分享一下为什么我在运行 pytest 时无法获取日志。

一个重要的注意事项是,当您编写函数时,每个测试用例必须test_ 前缀开头。没有它,使用 pytest 时将没有打印语句。

至于命令,我使用以下命令来获取非常全面的日志:

python -m pytest -v -rs <particular_file.py> -s -o log_cli-level=DEBUG

通过确保您拥有正确的函数名称并使用我的命令,您应该能够肯定地看到控制台日志。