如何查看pytest运行期间创建的正常打印输出?

有时我只想在代码中插入一些print语句,然后看看当我使用它时会打印出什么。我通常的“锻炼”方法是使用现有的pytest测试。但是当我运行这些测试时,我似乎看不到任何标准输出(至少在我的IDE PyCharm中)。

有没有一种简单的方法可以在pytest运行期间查看标准输出?

350816 次浏览

-s开关禁用每个测试捕获(仅当测试失败时)。

-s等价于--capture=no

运行测试时使用-s选项。当测试运行时,exampletest.py中的所有打印语句都将打印在控制台上。

py.test exampletest.py -s

点赞数接受的答案中,要求:

有没有办法打印到控制台捕获输出,以便在jUnit报告中显示?

在UNIX中,这通常被称为发球。理想情况下,py.test默认设置是发球而不是捕获。非理想情况下,py.test和任何现有的第三方py.test插件(…据我所知,无论如何)都不支持发球-尽管Python非常支持发球开箱即用

猴子修补py.test做任何不受支持是不平凡的。为什么?因为:

  • 大多数py.test功能都锁定在打算从外部导入的私有_pytest没有后面。尝试在不知道自己在做什么的情况下这样做通常会导致公共pytest包在运行时引发模糊的异常。非常感谢,py.test.非常坚固的建筑。
  • 即使你想出了如何安全地给私有的_pytest API打补丁,你也必须之前运行由外部py.test命令运行的公共pytest包来这样做。你不能在插件中这样做(例如,测试套件中的顶层conftest模块)。当py.test懒洋洋地开始动态导入你的插件时,你想打补丁的任何py.test类早就被实例化了——而你没有确实有权访问该实例。这意味着,如果你希望你的猴子补丁被有意义地应用,你不能再安全地运行外部py.test命令。相反,您必须使用自定义setupolstest命令包装该命令的运行,该命令(按顺序):
    1. 猴子修补私有的_pytest API。
    2. 调用公共pytest.main()函数来运行py.test命令。

这个答案补丁了py.test的-s--capture=no选项来捕获stderr,但没有 stdout。默认情况下,这些选项既不捕获stderr也不捕获stdout。当然,这并不是很容易。但每一个伟大的旅程都始于一个乏味的前传,每个人都会在五年内忘记。

为什么这样做?我现在要告诉你。我的py.test驱动的测试套件包含缓慢的功能测试。显示这些测试的标准输出很有帮助,也让人放心,防止leycec在另一个长时间运行的功能测试连续几周都无法执行任何操作时访问killall -9 py.test。然而,显示这些测试的标准错误会阻止py.test报告测试失败的异常回溯。这完全没有帮助。因此,我们强制py.test捕获标准错误,但捕获没有标准错误。

在我们开始之前,这个答案假设您已经有一个自定义的setupolstest命令调用py.test.如果没有,请参阅py.test编写良好的良好做法页面的手动集成小节。

没有安装pytest转轮,这是一个第三方安装工具插件,提供了一个自定义的setupolstest命令,也调用py.test.如果已经安装了pytest-的运行器,你可能需要卸载那个pip3包,然后采用上面链接的手动方法。

假设您遵循上面突出显示的手动集成中的说明,您的代码库现在应该包含PyTest.run_tests()方法。修改此方法以类似于:

class PyTest(TestCommand):
.
.
.
def run_tests(self):
# Import the public "pytest" package *BEFORE* the private "_pytest"
# package. While importation order is typically ignorable, imports can
# technically have side effects. Tragicomically, that is the case here.
# Importing the public "pytest" package establishes runtime
# configuration required by submodules of the private "_pytest" package.
# The former *MUST* always be imported before the latter. Failing to do
# so raises obtuse exceptions at runtime... which is bad.
import pytest
from _pytest.capture import CaptureManager, FDCapture, MultiCapture


# If the private method to be monkey-patched no longer exists, py.test
# is either broken or unsupported. In either case, raise an exception.
if not hasattr(CaptureManager, '_getcapture'):
from distutils.errors import DistutilsClassError
raise DistutilsClassError(
'Class "pytest.capture.CaptureManager" method _getcapture() '
'not found. The current version of py.test is either '
'broken (unlikely) or unsupported (likely).'
)


# Old method to be monkey-patched.
_getcapture_old = CaptureManager._getcapture


# New method applying this monkey-patch. Note the use of:
#
# * "out=False", *NOT* capturing stdout.
# * "err=True", capturing stderr.
def _getcapture_new(self, method):
if method == "no":
return MultiCapture(
out=False, err=True, in_=False, Capture=FDCapture)
else:
return _getcapture_old(self, method)


# Replace the old with the new method.
CaptureManager._getcapture = _getcapture_new


# Run py.test with all passed arguments.
errno = pytest.main(self.pytest_args)
sys.exit(errno)

要启用此猴子补丁,请运行py.test如下:

python setup.py test -a "-s"

stderr但是没有 stdout现在将被捕获。漂亮!

将上面的猴子补丁扩展到tec stdout和stderr是留给读者的练习-充满了空闲时间。

根据pytest留档,pytest版本3可以暂时禁用测试中的捕获:

def test_disabling_capturing(capsys):
print('this output is captured')
with capsys.disabled():
print('output not captured, going directly to sys.stdout')
print('this output is also captured')

尝试pytest -s -v test_login.py控制台中的更多信息。

-v很短--verbose

-s表示“禁用所有捕获”



如果您使用的是PyCharm IDE,那么您可以使用运行工具栏运行单个测试或所有测试。运行工具窗口显示应用程序生成的输出,您可以在其中看到所有打印语句作为测试输出的一部分。

pytest从单个测试中捕获stdout并仅在某些条件下显示它们,以及默认打印的测试摘要。

额外摘要信息可以使用'-r'选项显示:

pytest -rP

显示已通过测试的捕获输出。

pytest -rx

显示失败测试的捕获输出(默认行为)。

输出的格式使用-r比使用-s更漂亮。

最近添加了pytest --capture=tee-sysv5.4.0)。您可以捕获并查看stdout/err上的输出。

您还可以通过在项目根目录中的pytest.initox.ini中设置以下内容来启用直播

[pytest]
log_cli = True

或者直接在cli上指定

pytest -o log_cli=True
pytest test_name.py -v -s

简单!

我建议使用-h命令。可能会使用一些非常有趣的命令。 但是,对于这种特殊情况:-s设置--capture=no的快捷方式就足够了

pytest <test_file.py> -s

如果您使用的是logging,除了-s之外,您还需要指定为通用标准输出打开日志记录输出。基于在pytest测试中记录,我使用:

pytest --log-cli-level=DEBUG -s my_directory/

如果有人想从带有输出的代码运行测试:

if __name__ == '__main__':
pytest.main(['--capture=no'])

capsys、capsys二进制、capfd和capfd二进制灯具允许访问创建的stdout/stderr输出 在测试执行期间。这是一个执行一些输出相关检查的示例测试函数:

def test_print_something_even_if_the_test_pass(self, capsys):
text_to_be_printed = "Print me when the test pass."
print(text_to_be_printed)
p_t = capsys.readouterr()
sys.stdout.write(p_t.out)
# the two rows above will print the text even if the test pass.

以下是结果:

test_print_something_even_if_the_test_pass通过[100%]当测试通过时打印我。