如何在pytest中打印到控制台?
当我使用 print
时,pytest
不会在控制台上打印任何内容。看起来 文档 说默认情况下应该可以工作。
我用 pytest my_tests.py
来运行这个测试:
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.
但是我的标准输出控制台上什么都没打印出来(只显示了正常的进度,以及有多少个测试通过或失败)。
而我正在测试的脚本里确实有 print
语句:
class Blogger(Site):
get_links(self, posts):
print len(posts) # It won't get printed in the test.
在 unittest
模块中,所有内容默认都会打印出来,这正是我需要的。不过,我还是想用 pytest
,因为有其他原因。
有没有人知道怎么才能让 print
语句显示出来呢?
12 个回答
我需要在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
运行测试,这条消息就不会被打印,所以这样一来,所有的测试都能正常进行。
这是我知道的最简单的方法,可以把一条信息打印到 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
选项会打印出所有函数的输出,这可能会太多了。
如果你只需要特定的输出,你提到的文档页面提供了一些建议:
在你的函数末尾插入
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
命令来运行你的测试。
这确实是一种比较“hack”的做法,但也许这正是你需要的:毕竟,测试驱动开发(TDD)就是在搞事情,等准备好了再把它清理干净,让它安静下来 :-).
使用 -s
选项:
pytest -s
详细解答
根据 官方文档:
在测试执行过程中,任何发送到标准输出(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 的内容都会被捕获。
系统级别捕获:只有写入 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
默认情况下,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
语句的输出,可以在运行 py.test
时加上 -s
这个选项。不过要注意,这样有时候会让人看得有点费劲。
>>> 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 ======================