如何在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
命令。 相反,您必须使用自定义的setuptoolstest
命令来包装该命令的运行(按顺序):- Monkey-patches private
_pytest
API。 - 调用公共
pytest.main()
函数来运行py.test
命令。
- Monkey-patches private
这个答案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