如何在pytest运行过程中看到正常的打印输出?

有时候我只想在我的代码中插入一些打印语句,看看我在练习时打印出来的内容。 我常用的方式来“锻炼”它是与现有pytesttesting。 但是,当我运行这些,我似乎不能看到任何标准输出(至less从PyCharm,我的IDE)。

有一个简单的方法来看pytest运行期间的标准输出?

-s开关禁用每次testing捕获。

乔在接受的答案中提出了一个评论 ,他问道:

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

在UNIX中,这通常被称为开球 。 理想情况下,开球而不是捕捉将是py.test默认。 非理想情况下,无论py.test还是任何现有的第三方py.test插件( 我知道,无论如何 )支持开球 – 尽pipePython平凡支持开箱即用 。

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

  • 大多数py.testfunction被locking在一个打算从外部导入的私有_pytest包之后。 试图在不知道自己在做什么的情况下这样做通常会导致公共pytest包在运行时引发模糊的exception。 非常感谢py.test。 真的强大的build筑,你到了那里。
  • 即使你真的想搞清楚如何以安全的方式修改私有的_pytest API,你必须运行由外部py.test命令运行的公共pytest之前这样做。 你不能在一个插件(例如,你的testing套件中的一个最高级的conftest模块)中做到这一点。 当py.test懒洋洋地dynamic地导入你的插件的时候,任何想要猴子打补丁的py.test类都已经被实例化了,而且你没有权限访问这个实例。 这意味着,如果你想让你的猴子补丁有意义的应用,你不能再安全地运行外部的py.test命令。 相反,您必须使用自定义的setuptools test命令来包装该命令的运行(按顺序):
    1. Monkey-patches private _pytest API。
    2. 调用公共pytest.main()函数来运行py.test命令。

这个答案monkey-patches py.test的-s--capture=no选项捕获stderr而不是 stdout。 默认情况下,这些选项既不捕获stderr也不捕获stdout。 当然,这不是开球。 但是,每一次伟大的旅程都是从五年中每个人都忘记的乏味前传开始的。

为什么这样做? 我现在要告诉你。 我py.test驱动的testing套件包含慢速functiontesting。 显示这些testing的标准输出是有帮助和可靠的,防止leycec达到killall -9 py.test时,另一个长时间运行的functiontesting不能做任何事情,连续数周。 但是,显示这些testing的stderr可以防止py.test在testing失败时报告exception回溯。 这是完全无益的。 因此,我们强制py.test捕获stderr而不是 stdout。

在我们开始之前,这个答案假定你已经有一个自定义的setuptools test命令调用py.test。 如果你不这样做,请参阅py.test编写良好的良好实践页面的手册集成部分。

不要安装pytest-runner ,第三方setuptools插件提供一个自定义的setuptools test命令,同时调用py.test。 如果已经安装了pytest-runner,则可能需要卸载该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。 漂亮!

把上面的猴子补丁扩展到发球台和stderr是一个充满空闲时间的阅读练习。

根据pytest文档 , pytest的版本3可以在testing中临时禁用捕获:

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

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

 py.test exampletest.py -s