[英]Pytest capture stdout of a certain test
Is there a way get the Captured stdout call
just for a specific test without failing the test?有没有办法只为特定测试获取
Captured stdout call
而不会使测试失败?
So lets say I have 10 tests, plus a test_summary.假设我有 10 个测试,外加一个 test_summary。 test_summary really just prints some kind of summary/statistics of the tests, but in order for me to get that output/printout, I have to currently fail that test intentionally.
test_summary 实际上只是打印测试的某种摘要/统计数据,但为了让我获得该输出/打印输出,我目前必须故意使该测试失败。 Of course this test_summary run last using pytest-ordering.
当然这个 test_summary 最后使用 pytest-ordering 运行。 But is there a better way to get that results without failing the test?
但是有没有更好的方法可以在不通过测试的情况下获得结果呢? Or should it not be in a test, but more in the conftest.py or something?
或者它不应该在测试中,而是在 conftest.py 或其他东西中? Please advice on the best practice and how I can get this summary/results (basically a printout from a specific script I wrote)
请就最佳实践以及我如何获得此摘要/结果提出建议(基本上是我编写的特定脚本的打印输出)
First, to answer your exact question:首先,回答你的确切问题:
Is there a way get the
Captured stdout call
just for a specific test without failing the test?有没有办法只为特定测试获取
Captured stdout call
而不会使测试失败?
You can add a custom section that mimics Captured stdout call
and is printed on test success.您可以添加一个自定义部分,模仿
Captured stdout call
并在测试成功时打印。 The output captured in each test is stored in the related TestReport
object and is accessed via report.capstdout
.在每个测试中捕获的 output 存储在相关的
TestReport
object 中,并通过report.capstdout
访问。 Example impl: add the following code to a conftest.py
in your project or tests root directory:示例实现:将以下代码添加到项目或测试根目录中的
conftest.py
中:
import os
def pytest_terminal_summary(terminalreporter, exitstatus, config):
# on failures, don't add "Captured stdout call" as pytest does that already
# otherwise, the section "Captured stdout call" will be added twice
if exitstatus > 0:
return
# get all reports
reports = terminalreporter.getreports('')
# combine captured stdout of reports for tests named `<smth>::test_summary`
content = os.linesep.join(
report.capstdout for report in reports
if report.capstdout and report.nodeid.endswith("test_summary")
)
# add custom section that mimics pytest's one
if content:
terminalreporter.ensure_newline()
terminalreporter.section(
'Captured stdout call',
sep='-',
blue=True,
bold=True,
)
terminalreporter.line(content)
This will add a custom section Captured stdout call
that will only print the output captured for the test whose ID ends with test_summary
(if you have multiple test functions named test_summary
, extend the check).这将添加一个自定义部分
Captured stdout call
,该调用将只打印为 ID 以 test_summary 结尾的测试捕获的test_summary
(如果您有多个名为test_summary
的测试函数,请扩展检查)。 To distinct both sections, the custom one has a blue header;为了区分这两个部分,自定义部分有一个蓝色的 header; if you want it to match the original, remove color setting via
blue=True
arg.如果您希望它与原始颜色匹配,请通过
blue=True
arg 删除颜色设置。
Now, to address your actual problem:现在,解决您的实际问题:
test_summary
really just prints some kind of summary/statistics of the teststest_summary
实际上只是打印测试的某种摘要/统计信息
Using a test for custom reporting smells a lot like a workaround to me;使用自定义报告测试对我来说很像是一种变通方法; why not collect the data in the tests and add a custom section printing that data afterwards?
为什么不在测试中收集数据并在之后添加一个自定义部分来打印该数据? To collect the data, you can eg use the
record_property
fixture:要收集数据,您可以使用
record_property
fixture:
def test_foo(record_property):
# records a key-value pair
record_property("hello", "world")
def test_bar(record_property):
record_property("spam", "eggs")
To collect and output the custom properties recorded, slightly alter the above hookimpl.收集和 output 记录的自定义属性,稍微改变上面的 hookimpl。 The data stored via
record_property
is accessible via report.user_properties
:通过
report.user_properties
record_property
:
import os
def pytest_terminal_summary(terminalreporter, exitstatus, config):
reports = terminalreporter.getreports('')
content = os.linesep.join(
f'{key}: {value}' for report in reports
for key, value in report.user_properties
)
if content:
terminalreporter.ensure_newline()
terminalreporter.section(
'My custom summary',
sep='-',
blue=True,
bold=True
)
terminalreporter.line(content)
Running the above tests now yields:运行上述测试现在产生:
$ pytest test_spam.py
=============================== test session starts ================================
platform linux -- Python 3.9.0, pytest-6.1.2, py-1.9.0, pluggy-0.13.1
rootdir: /home/oleg.hoefling/projects/private/stackoverflow/so-64812992
plugins: metadata-1.10.0, json-report-1.2.4, cov-2.10.1, forked-1.3.0, xdist-2.1.0
collected 2 items
test_spam.py .. [100%]
-------------------------------- My custom summary ---------------------------------
hello: world
spam: eggs
================================ 2 passed in 0.01s =================================
You can use the standard pytest terminal reporter.您可以使用标准的 pytest 终端记者。
def test_a(request):
reporter = request.config.pluginmanager.getplugin("terminalreporter")
reporter.write_line("Hello", yellow=True)
reporter.write_line("World", red=True)
The reporter is the standard plugin available for all pytest versions that I can recall. reporter 是我记得的所有 pytest 版本的标准插件。 It is not documented unfortunately while the API is pretty stable.
不幸的是,它没有记录在案,而 API 非常稳定。
You can find TerminalReporter
class on pytest's github: https://github.com/pytest-dev/pytest/blob/master/src/_pytest/terminal.py你可以在pytest的github上找到
TerminalReporter
class: https://github.com/pytest-dev/pytest/blob/master/src/_pytest/terminal.py
The most useful for you methods are probably ensure_line()
, write()
, flush()
and the absolute champion -- write_line()
that just do all work.对您最有用的方法可能是
ensure_line()
、 write()
、 flush()
和绝对冠军 -- write_line()
,它们可以完成所有工作。
Available styles could be found at https://github.com/pytest-dev/pytest/blob/master/src/_pytest/_io/terminalwriter.py可用的 styles 可以在https://github.com/pytest-dev/pytest/blob/master/src/_pytest/_io/terminalwriter.py找到
_esctable = dict(
black=30,
red=31,
green=32,
yellow=33,
blue=34,
purple=35,
cyan=36,
white=37,
Black=40,
Red=41,
Green=42,
Yellow=43,
Blue=44,
Purple=45,
Cyan=46,
White=47,
bold=1,
light=2,
blink=5,
invert=7,
)
Lowercased styles are for the foreground, capitalized are for background.小写 styles 表示前景,大写表示背景。
For example, the yellow on the green text should be printed as例如,绿色文本上的黄色应打印为
reporter.write_line("Text", yellow=True, Green=True)
I hope this instruction can help.我希望这个说明能有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.