未提供项目描述
项目描述
Valgrind测试辅助工具,用于pytest
这是一个相当复杂的解决方案,但它可以帮助您使用valgrind测试C扩展模块。特别是如果您对检查内存泄漏感兴趣。
我何时想使用这个工具?
- 您有一个非平凡的C扩展,并且应该真正用valgrind来检查它。
- 您有一个非平凡的C扩展模块,该模块执行内存分配,并且可能会泄漏内存。
- 您不仅对引用计数泄漏(对于其他工具可能更好)感兴趣。或者希望valgrind提供有关泄漏的一些信息。
- 您正在寻找一种简单的方法来概述哪些测试会导致valgrind检测到的错误。
为什么不用valgrind直接运行测试?
- 在valgrind上进行的内存泄漏检查通常只在退出时执行。这将在每个测试后运行泄漏检查,让您能够缩小泄漏发生的位置,而无需额外的工作。
- 这会报告哪些测试失败valgrind以及与它相关的确切错误。因此,它可能更加方便
为什么我不应该使用这个工具?
- 这是一个使用您传递valgrind日志文件给pytest(如果您希望获得有用的错误摘要)的技巧。
- 错误报告可能有一些怪癖,并隐藏了正常的错误。
- 您想要检查完整的valgrind信息,这样您更有可能错过只在测试之间出现的错误(例如模块导入/拆解)。
在每次测试后测试内存泄漏似乎有些不可靠且非常缓慢。此外,我对细节了解不足,无法确定是否存在其他问题。
如何使用插件
要使用此模块,您需要首先使用pip install .
或pip install . --user
安装它。它目前仅支持Python 3,并需要一个C编译器以及典型的valgrind安装(valgrind/valgrind.h
)。
然后,使用带有--valgrind
选项的正常pytest调用使用它,但是,您还需要在valgrind本身中运行一切。
这样做最容易的方式是(据信需要python 3.6):以下示例调用(或类似的pytest命令)。在example
子目录中有一个示例测试,其中包含类似的调用,作为文档的一部分
PYTHONMALLOC=malloc valgrind --show-leak-kinds=definite --log-file=/tmp/valgrind-output \
python -m pytest -vv --valgrind --valgrind-log=/tmp/valgrind-output
请注意,PYTHONMALLOC=malloc
命令至关重要(并且仅在较新的python版本上有效)。作为替代方案,可以使用带有--valgrind
选项的python调试构建。如果不使用这两种方法,输出将因python的假阳性(可以添加抑制,但可靠性较低)而变得无用。调用者有责任传递正确的valgrind参数。您必须传递--show-leak-kinds=definite
,并应使用如上所述的--log-file
!
在这个调用中,您应该提供日志文件并将其传递给pytest。否则,pytest-valgrind
将无法提供良好的错误报告。任何正常的失败都将被跳过。例如,在numpy中,通常浮点错误无法报告,这导致测试失败。
第一个版本实际上忽略了--errors-for-leak-kinds
valgrind选项。在当前版本中,--errors-for-leak-kinds=definite
将工作(并忽略“间接”泄漏)。
在测试期间发生的任何valgrind错误或内存泄漏都会导致测试被记录为失败。您必须搜索valgrind日志文件以找到特定的错误。
作为进一步的示例,可以使用以下命令运行单个NumPy测试文件(其中一些选项可能不是必需的)
PYTHONMALLOC=malloc valgrind --show-leak-kinds=definite --log-file=/tmp/valgrind-output python runtests.py -g -t numpy/core/tests/test_dtype.py -- -vv --valgrind --valgrind-log=/tmp/valgrind-output --continue-on-collection-errors
选项
--valgrind
启用插件。--valgrind-log=<log_file>
应提供。这是传递给valgrind的同一文件,作为--log-file=<log_file>
。如果不提供,错误报告将不包含任何valgrind输出。--no-memcheck
将在每次函数调用后禁用对内存泄漏的检查(或实际上在任何时候都禁用)。如果您确定没有泄漏,这可能会加快执行速度。--memcheck-before-func
将在每个测试调用之前运行内存检查。这通常是不必要的,因此可能应该再次删除。
报告的失败和标记测试
目前,此插件忽略了所有正常异常,并将它们替换为KNOWNFAIL
/xfail
。它仅报告valgrind报告的错误/泄漏。似乎已知失败,这些失败会产生valgrind错误,也被报告为已知失败。
您可以使用pytest.mark.valgrind_known_leak(reason="?!")
或pytest.mark.valgrind_known_error(reason="Oooops")
(或两者)标记测试,使测试结果针对此插件特定于泄漏或其他由valgrind报告的错误,并标记为xfail
。
并非所有错误都一定是由于您的代码引起的,有时可能会报告来自已知良好函数的假阳性。例如,如果valgrind抑制未更新,strcmp
可能会这样做。此类失败应使用valgrind抑制文件修复,而不是使用pytest标记。
注释、警告和解决方案
如果您想修改输出,请查阅valgrind文档。Valgrind开始隐藏重复的错误,所以如果一个错误被突出显示为错误,但valgrind输出中没有错误,那么这个错误可能是前一个错误的重复,因此被隐藏了。
进一步说明
- 如果valgrind在测试收集过程中发生错误导致交互不良,这可能会导致pytest挂起。在这种情况下,您可以使用
--continue-on-collection-errors
作为快速解决方案。 - CPython总是由于实现垃圾回收器/循环引用计数而引起“可能的”泄漏。因此,我们进行一次合理性检查:如果
obj = object()
报告“泄漏”,则忽略valgrind的--errors-for-leak-kinds
(默认包括“可能的”)。忽略--errors-for-leak-kinds=definite
,并且可能还有其他方法可以使上述检查通过。 - 与使用valgrind进行简单运行相比,这种频繁的测试泄漏会使测试速度更慢。
- 这并不太优雅,因为valgrind输出文件被作为参数传递给pytest(我怀疑有没有解决方案)。
- 如果您输出中没有有用的函数名,可能是因为您没有构建调试版本?
- Valgrind有很多选项,请检查它们!
- 没有,我没有在不同的系统/编译器上检查过。所以如果它坏了,您可能需要修改代码或setup.py。
- 默认情况下,在第一次测试之前和每次测试之后都会检查泄漏。这意味着
- 在运行任何测试之前发生的泄漏不会报告!
- 泄漏不应该真的发生在测试之间,但如果确实发生了,它们将在下一个测试中报告。
- 如果您的程序有缓存(例如,numpy有一个小的数组缓存),这可能会导致泄漏的行为非确定性的,或者被泄漏的对象与实际泄漏的对象不对应(因为分配最初是为了另一个对象而发生的)。
- 该工具在每个测试之后都会重复运行垃圾回收器,这可能会非常慢。
- 我对pytest插件不太了解(而且文档在当时也不是很容易),所以pytest中许多事情的实现可以和应该做得更好。
我不喜欢这个或者没有更好的版本!
当然,如果您有更好的东西,请随时创建pull请求,我很乐意移除/重命名这个。
项目详情
哈希值 用于 pytest_valgrind-0.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 59c2ea9437e341623bd623117a01b4eb18adc82078d267c55ca4dfa742bd64c4 |
|
MD5 | 528a7cff02ab22f5033a56d0c7a9d90d |
|
BLAKE2b-256 | fafe81dea7c2497ecc736b64e1a6ac5de43b314a3165479cda87e320cccc9d25 |
哈希值 用于 pytest_valgrind-0.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | fb9c172858d97cbcb8e4409345a9064a664c11811edea6ba4f6c9ad8109747f9 |
|
MD5 | 3e6af1bb68dcade8d599f6c1defb6c74 |
|
BLAKE2b-256 | ffd42539af41ff5c0f1e78e20906b770c9c38338375e62f0bdb7c565ea3aef69 |