【问题标题】:How can I see normal print output created during pytest run?如何查看 pytest 运行期间创建的正常打印输出?
【发布时间】:2013-01-02 12:37:09
【问题描述】:

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

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

【问题讨论】:

    标签: python logging output pytest


    【解决方案1】:

    -s switch 禁用每次测试捕获(仅当测试失败时)。

    -s 等价于--capture=no

    【讨论】:

    • 这会导致输出与 Pytest 输出交错。您可能想要的是 Pytest 像往常一样捕获输出并在测试通过和失败时显示它。见stackoverflow.com/a/59156707/369977
    • 如何在运行过程中查看打印而不等待结束?
    • 如果使用日志记录,另请参阅 stackoverflow.com/questions/4673373/logging-within-pytest-tests 以了解与 -s 一起使用的其他选项
    • 我想知道您所说的“每次测试捕获”是什么意思。我猜,禁用捕获实际上与启用标准输出相同,但我不确定,因为我不知道 pytest 的来龙去脉——我只想看看我的打印语句。您介意详细说明吗?
    【解决方案2】:

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

    Extra summary info 可以使用 '-r' 选项显示:

    pytest -rP
    

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

    pytest -rx
    

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

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

    【讨论】:

    • 这是我正在寻找的实际答案!谢谢你。 (需要在测试结果之后出现标准输出。当它们交错时,打印的行会失去价值。)
    • 如何在 Pycharm 中做到这一点(不是通过命令行)?
    • @Gulzar per this question,您可以执行以下操作:编辑配置 > 附加参数 > -r P。我用 Pycharm 2021.1 成功地测试了这一点。在 add'l 参数中的含义是,您输入 -r,然后输入一个空格,然后输入 P。希望有帮助
    • @spen.smith 这是通过 pycharm 的命令行。我正在寻找内置的东西
    • pytest -rA 应该打印所有输出。 docs.pytest.org/en/6.2.x/…
    【解决方案3】:

    upvoted commentaccepted answerJoe 询问:

    有什么方法可以打印到控制台捕获输出以便它显示在 junit 报告中?

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

    Monkey-patching py.test 来做 anything 不受支持是不平凡的。为什么?因为:

    • 大多数 py.test 功能被锁定在私有 _pytest 包后面 打算从外部导入。在不知道自己在做什么的情况下尝试这样做通常会导致公共 pytest 包在运行时引发晦涩的异常。 非常感谢,py.test。真正强大的架构。
    • 即使您确实想出了如何以安全的方式对私有 _pytest API 进行猴子修补,您也必须在运行公共 @987654335 之前这样做@ 由外部py.test 命令运行的包。您不能在插件中执行此操作(例如,测试套件中的顶级 conftest 模块)。当 py.test 懒惰地开始动态导入你的插件时,任何你想要猴子补丁的 py.test 类早就被实例化了——你确实没有可以访问那个实例。这意味着,如果您希望有意义地应用猴子补丁,则不能再安全地运行外部 py.test 命令。相反,您必须使用自定义 setuptools test 命令包装该命令的运行,该命令(按顺序):
      1. Monkey 为私有 _pytest API 打补丁。
      2. 调用公共pytest.main()函数运行py.test命令。

    这个答案猴子补丁 py.test 的 -s--capture=no 选项来捕获标准错误,但不是标准输出。默认情况下,这些选项既不捕获标准错误也不捕获标准输出。当然,这并不完全是开球。但每一次伟大的旅程都始于一个乏味的前传,每个人都会在五年内忘记。

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

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

    不要安装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)
    

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

    python setup.py test -a "-s"
    

    Stderr but not stdout 现在将被捕获。漂亮!

    将上面的猴子补丁扩展到 tee stdout 和 stderr 留给读者作为练习,并有大量空闲时间。

    【讨论】:

    【解决方案4】:

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

    py.test exampletest.py -s
    

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

          请尝试 pytest -s -v test_login.py 在控制台中获取更多信息。

          -v很短--verbose

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



          【讨论】:

          • 如果你使用 pytest.ini 文件,你可以使用:addopts = -s -v python_files = test_login.py
          • 如果即使测试通过,您也想打印,这就是我需要的答案。
          【解决方案8】:

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

          [pytest]
          log_cli = True
          

          或者直接在cli上指定

          pytest -o log_cli=True
          

          【讨论】:

          • pytest-5.3.5 上进行了测试,它可以工作。您可能还想添加-s 标志。 pytest -s -o log_cli=True
          【解决方案9】:
          pytest test_name.py -v -s
          

          简单!

          【讨论】:

            【解决方案10】:

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

            【讨论】:

            • 你知道如何在测试运行时打印 PyCharm 吗? (而不是在测试通过之后)
            【解决方案11】:

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

            pytest <test_file.py> -s
            

            【讨论】:

              【解决方案12】:

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

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

              【讨论】:

                猜你喜欢
                • 2023-03-20
                • 2021-08-30
                • 1970-01-01
                • 2018-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-05-18
                • 1970-01-01
                相关资源
                最近更新 更多