如何在pytest中打印到控制台?
Posted
技术标签:
【中文标题】如何在pytest中打印到控制台?【英文标题】:How to print to console in pytest? 【发布时间】:2014-08-28 08:05:33 【问题描述】:我正在尝试将 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")
怎么样?后者应始终写入系统定义的标准输出,它应该是控制台。如果这两个命令做不同的事情,那么标准输出正在改变;如果他们做同样的事情,那么问题就出在其他地方。
【参考方案1】:
默认情况下,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 ======================
【讨论】:
嗯...仍然没有记录我的打印语句【参考方案2】:简答
使用-s
选项:
pytest -s
详细解答
来自the docs:
在测试执行期间,任何发送到 stdout 和 stderr 的输出都会被捕获。如果测试或设置方法失败,其捕获的输出通常会与失败回溯一起显示。
pytest
具有选项--capture=method
,其中method
是每次测试捕获方法,并且可以是以下之一:fd
、sys
或no
。 pytest
也有选项-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
【讨论】:
【参考方案3】:使用-s
选项将打印所有函数的输出,这可能太多了。
如果您需要特定的输出,您提到的文档页面提供了一些建议:
在函数末尾插入assert False, "dumb assert to make PyTest print my stuff"
,由于测试失败,您将看到输出。
你有 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 不幸的是它只打印测试功能块,而不是打印语句的输出:( 还有更多技巧吗? @U.V. - 不要使用print()
函数,您应该将要打印的变量或消息放在 逗号之后的断言语句中。例如。 assert False, what_are_you
将在 pytest 报告中“打印出”what_are_you
的值。【参考方案4】:
我需要在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
运行内容,则不会打印消息,因此一切都已经过很好的测试。
【讨论】:
非常适合输出自定义测试指标。【参考方案5】:这是我所知道的将单个语句打印到 sys.stdout
的最简洁的方式(无需人为地使您的测试失败或启用 -s
选项) - 您可以看到您想要的特定输出,仅此而已:
将内置参数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 选项或创建文件的打印日志。【参考方案6】:根据pytest docs,pytest --capture=sys
应该可以工作。如果您想在测试中捕获标准输出,请参阅 capsys 夹具。
【讨论】:
当终端需要打印变量时,这对我有用... 要在每次运行pytest
时传递--capture
选项,请在文件[pytest]
的[pytest]
部分中添加行addopts = --capture=tee-sys
(documentation)。【参考方案7】:
我最初来到这里是为了找到如何在 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"
]
]
【讨论】:
【参考方案8】:您也可以通过 Pycharm GUI 进行设置:转到 Run > Edit Configurations
。在那里,选择您要为其启用打印语句的测试并将-s
添加到Additional Arguments
字段。
我这样做是因为虽然我主要使用 Pycharm 调试器来调试我的 pytest 函数(即通过 GUI),但我的特定用例还要求我知道我的代码中其他地方发生了什么,并且可以打印语句很方便。
【讨论】:
以上是关于如何在pytest中打印到控制台?的主要内容,如果未能解决你的问题,请参考以下文章
如何查看在 Django 的 manage.py test 命令期间运行了哪些测试