pytest 从单个测试中捕获标准输出并仅在某些条件下显示它们,以及默认情况下打印的测试摘要。
Extra summary info 可以使用“-r”选项显示:
pytest -rP
显示已通过测试的捕获输出。
pytest -rx
显示失败测试的捕获输出(默认行为)。
输出的格式使用 -r 比使用 -s 更漂亮。
在对 accepted answer 的 upvoted comment 中,Joe 问道:
有什么方法可以打印到控制台并捕获输出以便它显示在 junit 报告中?
在 UNIX 中,这通常称为 teeing。理想情况下, py.test 的默认设置是发球而不是捕获。不理想的是,py.test 和任何现有的第三方 py.test 插件(...我知道,无论如何)都不支持 teeing——尽管 Python 微不足道地支持 teeing out-of-the-box。
Monkey-patching py.test 做任何不受支持的事情都是不平凡的。为什么?因为:
大多数 py.test 功能被锁定在不打算从外部导入的私有 _pytest 包后面。在不知道自己在做什么的情况下尝试这样做通常会导致公共 pytest 包在运行时引发晦涩的异常。非常感谢,py.test。真正强大的架构,你在那里。
即使您确实知道如何以安全的方式对私有 _pytest API 进行猴子修补,您也必须在运行由外部 py.test 命令运行的公共 pytest 包之前这样做。您不能在插件中执行此操作(例如,测试套件中的顶级 conftest 模块)。当 py.test 懒惰地开始动态导入你的插件时,任何你想要猴子补丁的 py.test 类早就被实例化了——你无法访问那个实例。这意味着,如果您希望有意义地应用猴子补丁,则不能再安全地运行外部 py.test 命令。相反,您必须使用自定义 setuptools 测试命令来包装该命令的运行,该命令(按顺序): Monkey-patches 私有 _pytest API。调用公共 pytest.main() 函数来运行 py.test 命令。
Monkey 修补私有 _pytest API。
调用公共 pytest.main() 函数来运行 py.test 命令。
这个答案猴子补丁 py.test 的 -s
和 --capture=no
选项来捕获 stderr 但 not stdout。默认情况下,这些选项既不捕获标准错误也不捕获标准输出。当然,这并不完全是开球。但每一次伟大的旅程都始于一个乏味的前传,每个人都会在五年内忘记。
为什么要这样做?我现在告诉你。我的 py.test 驱动的测试套件包含缓慢的功能测试。显示这些测试的标准输出是有帮助和令人放心的,防止 leycec 在另一个长时间运行的功能测试连续数周未能执行任何操作时到达 killall -9 py.test
。但是,显示这些测试的标准错误会阻止 py.test 报告测试失败的异常回溯。这是完全没有帮助的。因此,我们强制 py.test 捕获 stderr 但 not 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 但不是 stdout。漂亮!
将上面的猴子补丁扩展到 tee stdout 和 stderr 留给读者作为练习,并有大量空闲时间。
--capture=tee-sys
docs.pytest.org/en/stable/… 合作
运行测试时使用 -s
选项。运行测试时,exampletest.py
中的所有打印语句都将打印在控制台上。
py.test exampletest.py -s
根据 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')
在控制台中尝试 pytest -s -v test_login.py
了解更多信息。
-v
很短--verbose
-s
表示“禁用所有捕获”
您还可以通过在项目根目录的 pytest.ini
或 tox.ini
中设置以下内容来启用 live-logging。
[pytest]
log_cli = True
或者直接在cli上指定
pytest -o log_cli=True
pytest-5.3.5
上对其进行了测试,并且可以正常工作。您可能还想添加 -s
标志。 pytest -s -o log_cli=True
pytest test_name.py -v -s
简单的!
我建议使用 -h 命令。可能会使用一些非常有趣的命令。但是,对于这种特殊情况:-s 快捷方式为 --capture=no。足够的
pytest <test_file.py> -s
如果您使用 logging
,则除了 -s
之外,您还需要指定为通用标准输出打开日志输出。基于 Logging within pytest tests,我正在使用:
pytest --log-cli-level=DEBUG -s my_directory/
如果您使用的是 PyCharm IDE,那么您可以使用运行工具栏运行单个测试或所有测试。运行工具窗口显示应用程序生成的输出,您可以在其中看到所有打印语句作为测试输出的一部分。
如果有人想从带有输出的代码运行测试:
if __name__ == '__main__':
pytest.main(['--capture=no'])
capsys、capsysbinary、capfd 和 capfdbinary 夹具允许访问在测试执行期间创建的 stdout/stderr 输出。这是一个执行一些输出相关检查的示例测试函数:
def test_print_something_even_if_the_test_pass(self, capsys):
text_to_be_printed = "Print me when the test pass."
print(text_to_be_printed)
p_t = capsys.readouterr()
sys.stdout.write(p_t.out)
# the two rows above will print the text even if the test pass.
结果如下:
test_print_something_even_if_the_test_pass PASSED [100%]当测试通过时打印我。
不定期副业成功案例分享
-s
一起使用的其他选项