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

时间:2013-01-18 18:14:39

标签: python logging output pytest

有时我想在我的代码中插入一些打印语句,看看在我练习时会打印出来的内容。我通常的“锻炼”方法是使用现有的pytest测试。但是当我运行这些时,我似乎无法看到任何标准输出(至少来自PyCharm,我的IDE)。

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

14 个答案:

答案 0 :(得分:371)

-s switch禁用每次测试捕获。

答案 1 :(得分:44)

upvoted commentaccepted answerJoe询问:

  

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

在UNIX中,这通常称为teeing。理想情况下,teeing而不是捕获将是py.test默认值。非理想情况下,py.test和任何现有的第三方py.test插件(我知道的,无论如何)都支持teeing - 尽管Python平凡地支持发送out-of-the-box

猴子修补py.test以执行任何不受支持的操作是非常重要的。为什么?这是因为:

  • 大多数py.test功能都锁定在私人_pytest软件包而不是的外部导入。试图在不知道您正在做什么的情况下这样做通常会导致公共pytest包在运行时引发模糊的异常。 非常感谢,py.test。你到那里真的很健壮。
  • 即使你想出如何以安全的方式对私有_pytest API进行修补,你必须在运行公众之前 pytest包由外部py.test命令运行。您无法在插件中执行此操作(例如,测试套件中的顶级conftest模块)。当py.test懒惰地动态导入你的插件时,你想要实现猴子补丁的任何py.test类早已被实例化 - 并且可以访问该实例。这意味着,如果您希望有意义地应用monkey-patch,则无法再安全地运行外部py.test命令。相反,您必须使用自定义setuptools test命令(按顺序)包装该命令的运行:
    1. Monkey-patches私有_pytest API。
    2. 调用公共pytest.main()函数以运行py.test命令。

这个答案猴子补丁py.test的-s--capture=no选项来捕获stderr但不是标准输出。默认情况下,这些选项既不捕获stderr也不捕获stdout。当然,这不是很发球。但每一个伟大的旅程都始于一个繁琐的前传,每个人都会忘记五年。

为什么这样?我现在要告诉你。我的py.test驱动的测试套件包含慢速功能测试。显示这些测试的标准输出是有帮助的,让人放心,当另一个长期运行的功能测试在几周内没有做任何事情时,阻止leycec到达killall -9 py.test。但是,显示这些测试的stderr会阻止py.test报告测试失败时的异常回溯。这完全没有用。因此,我们强制py.test捕获stderr但标准输出。

在我们开始之前,这个答案假设您已经有一个自定义setuptools test命令调用py.test。如果您没有,请参阅py.test编写良好的Manual Integration页面的Good Practices小节。

安装pytest-runner,第三方setuptools插件,提供自定义setuptools test命令,同时调用py.test。如果已安装pytest-runner,您可能需要卸载该pip3软件包,然后采用上面链接的手动方法。

假设您按照上面突出显示的Manual Integration中的说明操作,您的代码库现在应该包含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)

要启用此Monkey-patch,请运行py.test,如下所示:

python setup.py test -a "-s"
现在将捕获

Stderr但标准输出。漂亮!

将上面的猴子补丁扩展到tee stdout和stderr,留给玩家一个充满空闲时间的练习。

答案 2 :(得分:20)

根据pytest documentation,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')

答案 3 :(得分:19)

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

py.test exampletest.py -s

答案 4 :(得分:11)

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

答案 5 :(得分:8)

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

-v 这是一个简短的 --verbose

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

答案 6 :(得分:3)

pytest捕获单个测试的标准输出,并仅在特定条件下显示它们,并默认显示其打印的测试摘要。

可以使用'-r'选项显示

Extra summary info

pytest -rP

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

pytest -rx

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

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

答案 7 :(得分:1)

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

[pytest]
log_cli = True

或直接在cli上指定

pytest -o log_cli=True

答案 8 :(得分:1)

pytest test_name.py -v -s

简单!

答案 9 :(得分:1)

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

pytest <test_file.py> -s

答案 10 :(得分:1)

如果您使用的是 logging,除了用于通用标准输出的 -s 之外,您还需要指定打开日志输出。基于 Logging within pytest tests,我正在使用:

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

答案 11 :(得分:0)

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

答案 12 :(得分:0)

pytest -v -s scriptname(for single test script)

pytest -v -s (for complete module/package)

pytest -v -s scriptname::function(indiviual function)

答案 13 :(得分:0)

其他答案无效。查看捕获输出的 only 方法是使用以下标志:

  

pytest --show-capture all