使用 pytest.hookimpl 将 pytest 测试函数 return 值写入文件
write pytest test function return value to file with pytest.hookimpl
我正在寻找一种方法来访问测试函数的 return 值,以便将该值包含在测试报告文件中(类似于 http://doc.pytest.org/en/latest/example/simple.html#post-process-test-reports-failures)。
我想使用的代码示例:
# modified example code from http://doc.pytest.org/en/latest/example/simple.html#post-process-test-reports-failures
import pytest
import os.path
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
# execute all other hooks to obtain the report object
outcome = yield
rep = outcome.get_result()
if rep.when == "call" and rep.passed:
mode = "a" if os.path.exists("return_values") else "w"
with open("return_values.txt", mode) as f:
# THE FOLLOWING LINE IS THE ONE I CANNOT FIGURE OUT
# HOW DO I ACCESS THE TEST FUNCTION RETURN VALUE?
return_value = item.return_value
f.write(rep.nodeid + ' returned ' + str(return_value) + "\n")
我希望将 return 值写入文件 "return_values.txt"。相反,我得到一个 AttributeError。
背景(如果您可以推荐完全不同的方法):
我有一个 Python 库用于对给定问题进行数据分析。我有一组标准的测试数据,我会定期 运行 我的分析以生成各种 "benchmark" 分析算法质量指标。例如,一个这样的指标是由分析代码生成的归一化混淆矩阵的轨迹(我希望它尽可能接近 1)。另一个指标是 CPU 生成分析结果的时间。
我正在寻找一种将这些基准测试结果包含到 CI 框架(目前是 Jenkins)中的好方法,这样就可以很容易地看出提交是提高还是降低了分析性能。由于我已经在 CI 序列中 运行ning pytest,并且由于我想将 pytest 的各种功能用于我的基准测试(夹具、标记、跳过、清理),我想简单地添加一个 post-pytest 中的处理挂钩(参见 http://doc.pytest.org/en/latest/example/simple.html#post-process-test-reports-failures),它收集测试函数 运行 时间和 return 值并将它们(或仅标记为基准的那些)报告到文件中,它将被我的 CI 框架收集并存档为测试工件。
我对解决这个问题的其他方法持开放态度,但我的 google 搜索结论是 pytest 是最接近已经提供我需要的框架。
pytest
忽略测试函数return值,可以看出in the code:
@hookimpl(trylast=True)
def pytest_pyfunc_call(pyfuncitem):
testfunction = pyfuncitem.obj
...
testfunction(**testargs)
return True
但是,您可以在测试函数中存储您需要的任何内容;我通常为此使用 config
对象。示例:将以下代码段放入 conftest.py
:
import pathlib
import pytest
def pytest_configure(config):
# create the dict to store custom data
config._test_results = dict()
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
# execute all other hooks to obtain the report object
outcome = yield
rep = outcome.get_result()
if rep.when == "call" and rep.passed:
# get the custom data
return_value = item.config._test_results.get(item.nodeid, None)
# write to file
report = pathlib.Path('return_values.txt')
with report.open('a') as f:
f.write(rep.nodeid + ' returned ' + str(return_value) + "\n")
现在将数据存储在测试中:
def test_fizz(request):
request.config._test_results[request.node.nodeid] = 'mydata'
遇到同样的问题,这是我想出的不同解决方案:
在测试中使用夹具 record_property
:
def test_mytest(record_property):
record_property("key", 42)
然后在 conftest.py
中我们可以使用 pytest_runtest_teardown
hook:
#conftest.py
def pytest_runtest_teardown(item, nextitem):
results = dict(item.user_properties)
if not results:
return
with open(f'{item.name}_return_values.txt','a') as f:
for key, value in results.items():
f.write(f'{key} = {value}\n')
然后是test_mytest_return_values.txt
的内容:
key = 42
两个重要说明:
- 即使测试失败也会执行这段代码。我找不到获取测试结果的方法。
- 这可以与 heofling 的答案结合使用
results = dict(item.user_properties)
来获取在测试中添加的键和值,而不是将字典添加到配置中,然后在测试中访问它.
我正在寻找一种方法来访问测试函数的 return 值,以便将该值包含在测试报告文件中(类似于 http://doc.pytest.org/en/latest/example/simple.html#post-process-test-reports-failures)。
我想使用的代码示例:
# modified example code from http://doc.pytest.org/en/latest/example/simple.html#post-process-test-reports-failures
import pytest
import os.path
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
# execute all other hooks to obtain the report object
outcome = yield
rep = outcome.get_result()
if rep.when == "call" and rep.passed:
mode = "a" if os.path.exists("return_values") else "w"
with open("return_values.txt", mode) as f:
# THE FOLLOWING LINE IS THE ONE I CANNOT FIGURE OUT
# HOW DO I ACCESS THE TEST FUNCTION RETURN VALUE?
return_value = item.return_value
f.write(rep.nodeid + ' returned ' + str(return_value) + "\n")
我希望将 return 值写入文件 "return_values.txt"。相反,我得到一个 AttributeError。
背景(如果您可以推荐完全不同的方法):
我有一个 Python 库用于对给定问题进行数据分析。我有一组标准的测试数据,我会定期 运行 我的分析以生成各种 "benchmark" 分析算法质量指标。例如,一个这样的指标是由分析代码生成的归一化混淆矩阵的轨迹(我希望它尽可能接近 1)。另一个指标是 CPU 生成分析结果的时间。
我正在寻找一种将这些基准测试结果包含到 CI 框架(目前是 Jenkins)中的好方法,这样就可以很容易地看出提交是提高还是降低了分析性能。由于我已经在 CI 序列中 运行ning pytest,并且由于我想将 pytest 的各种功能用于我的基准测试(夹具、标记、跳过、清理),我想简单地添加一个 post-pytest 中的处理挂钩(参见 http://doc.pytest.org/en/latest/example/simple.html#post-process-test-reports-failures),它收集测试函数 运行 时间和 return 值并将它们(或仅标记为基准的那些)报告到文件中,它将被我的 CI 框架收集并存档为测试工件。
我对解决这个问题的其他方法持开放态度,但我的 google 搜索结论是 pytest 是最接近已经提供我需要的框架。
pytest
忽略测试函数return值,可以看出in the code:
@hookimpl(trylast=True)
def pytest_pyfunc_call(pyfuncitem):
testfunction = pyfuncitem.obj
...
testfunction(**testargs)
return True
但是,您可以在测试函数中存储您需要的任何内容;我通常为此使用 config
对象。示例:将以下代码段放入 conftest.py
:
import pathlib
import pytest
def pytest_configure(config):
# create the dict to store custom data
config._test_results = dict()
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
# execute all other hooks to obtain the report object
outcome = yield
rep = outcome.get_result()
if rep.when == "call" and rep.passed:
# get the custom data
return_value = item.config._test_results.get(item.nodeid, None)
# write to file
report = pathlib.Path('return_values.txt')
with report.open('a') as f:
f.write(rep.nodeid + ' returned ' + str(return_value) + "\n")
现在将数据存储在测试中:
def test_fizz(request):
request.config._test_results[request.node.nodeid] = 'mydata'
遇到同样的问题,这是我想出的不同解决方案:
在测试中使用夹具 record_property
:
def test_mytest(record_property):
record_property("key", 42)
然后在 conftest.py
中我们可以使用 pytest_runtest_teardown
hook:
#conftest.py
def pytest_runtest_teardown(item, nextitem):
results = dict(item.user_properties)
if not results:
return
with open(f'{item.name}_return_values.txt','a') as f:
for key, value in results.items():
f.write(f'{key} = {value}\n')
然后是test_mytest_return_values.txt
的内容:
key = 42
两个重要说明:
- 即使测试失败也会执行这段代码。我找不到获取测试结果的方法。
- 这可以与 heofling 的答案结合使用
results = dict(item.user_properties)
来获取在测试中添加的键和值,而不是将字典添加到配置中,然后在测试中访问它.