首页 文章

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

提问于
浏览
212

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

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

5 回答

  • 19

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

  • 40

    upvoted commentaccepted answerJoe问:

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

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

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

    • 大多数py.test功能被锁定在私有 _pytest 包之后,不打算从外部导入 . 试图在不知道你正在做什么的情况下这样做通常会导致公共 pytest 包在运行时引发模糊的异常 . 非常感谢,py.test . 你到那里真的很健壮的建筑 .

    • 即使您确定如何以安全的方式修补私有 _pytest API,也必须在运行外部 py.test 命令运行的公共 pytest 包之前执行此操作 . 您无法在插件中执行此操作(例如,测试套件中的顶级 conftest 模块) . 当py.test懒惰地动态导入你的插件时,你想要实现猴子补丁的任何py.test类早已被实例化 - 并且你无权访问该实例 . 这意味着,如果您希望有意义地应用猴子补丁,则无法再安全地运行外部 py.test 命令 . 相反,您必须使用自定义setuptools test 命令(按顺序)包装该命令的运行:

    • Monkey-patches私有 _pytest API .

    • 调用public pytest.main() 函数以运行 py.test 命令 .

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

    为什么这样?我现在要告诉你 . 我的py.test驱动的测试套件包含慢速功能测试 . 显示这些测试的标准输出是有帮助和安心的,当另一个长期运行的功能测试在几周内没有做任何事情时,阻止leycec到达 killall -9 py.test . 但是,显示这些测试的stderr会阻止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)
    

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

    python setup.py test -a "-s"
    

    现在将捕获Stderr而不是stdout . 漂亮!

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

  • 16

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

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

    py.test exampletest.py -s
    
  • 7

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

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

    -s 表示'disable all capturing'



相关问题