SlipCover:近乎零开销的Python代码覆盖工具
项目介绍

SlipCover 是由UMass Amherst的PLASMA实验室开发的快速代码覆盖工具。它能够在Python程序运行时跟踪代码的执行情况,并报告哪些部分被执行,哪些部分未被执行。这对于测试(显示未被测试的代码)、调试、模糊测试或查找“死”代码非常有帮助。
传统的代码覆盖工具通常会使程序的执行速度显著降低,有时甚至会减慢到原来的两倍。而SlipCover的目标是提供相同的信息,但几乎不增加任何开销,通常与运行原始Python程序的速度相当。
项目技术分析
工作原理
传统的代码覆盖工具如Coverage.py依赖于Python的跟踪机制,这会带来显著的开销。相比之下,SlipCover采用了即时(Just-In-Time)的代码插桩和去插桩技术。当SlipCover收集覆盖信息时,它会修改程序的Python字节码,插入指令以跟踪程序执行的行。随着程序的执行,SlipCover会逐渐移除不再需要的插桩,使这些部分能够以全速运行。在Python 3.12中,SlipCover利用新的sys.monitoring API来收集覆盖信息,而不是重写字节码。
性能
SlipCover在CPython 3.10.5上的速度提升范围为1.1x到3.4x,而在PyPy 3.9上的速度提升范围为2.1x到104.9x。对于一些Python密集型的程序,SlipCover的运行时间仍然接近原始程序,而Coverage.py则会因更多的跟踪事件而产生更大的开销。
准确性
SlipCover的准确性已经通过与Coverage.py和自定义的跟踪脚本进行了验证,结果显示SlipCover在某些情况下甚至比Coverage.py更准确。
项目及技术应用场景
SlipCover适用于以下场景:
- 测试覆盖率分析:帮助开发者了解哪些代码路径未被测试,从而提高测试覆盖率。
- 调试:在调试过程中,了解哪些代码路径被执行,哪些未被执行,有助于快速定位问题。
- 模糊测试:在模糊测试中,SlipCover可以帮助识别未被测试的代码路径,从而提高模糊测试的效率。
- 代码优化:通过识别“死”代码,开发者可以优化代码结构,提高程序性能。
项目特点
- 近乎零开销:SlipCover的设计目标是在不显著增加开销的情况下提供代码覆盖信息,使其在性能上接近原始Python程序。
- 即时插桩与去插桩:通过即时插桩和去插桩技术,SlipCover能够在程序运行时动态调整插桩,从而减少开销。
- 跨平台支持:SlipCover支持Linux、MacOS和Windows,并且理论上可以在任何支持CPython/PyPy的平台上运行。
- 易于集成:SlipCover可以通过pip安装,并且可以轻松集成到现有的测试框架中,如pytest。
如何开始
SlipCover可以从PyPI安装,使用以下命令即可:
pip3 install slipcover
安装后,可以通过以下命令运行Python脚本:
python3 -m slipcover myscript.py
如果需要与测试框架集成,例如pytest,可以使用以下命令:
python3 -m slipcover -m pytest -x -v
使用示例
以下是一个使用SlipCover运行pytest的示例:
$ python3 -m slipcover -m pytest
================================================================ test session starts ================================================================
platform darwin -- Python 3.9.12, pytest-7.1.2, pluggy-1.0.0
rootdir: /Users/juan/project/wally/d2k-5, configfile: pytest.ini
plugins: hypothesis-6.39.3, mock-3.7.0, repeat-0.9.1, doctestplus-0.12.0, arraydiff-0.5.0
collected 439 items
tests/box_test.py ......................... [ 5%]
tests/image_test.py ............... [ 9%]
tests/network_equivalence_test.py .........................................s................................................................. [ 33%]
.............................................................................. [ 51%]
tests/network_test.py ....................................................................................................................... [ 78%]
............................................................................................... [100%]
=================================================== 438 passed, 1 skipped, 62 warnings in 48.43s ====================================================
File #lines #miss Cover% Lines missing
--------------------------------- -------- ------- -------- ------------------------
d2k/__init__.py 3 0 100
d2k/box.py 105 27 74 73, 142-181
d2k/image.py 38 4 89 70-73
d2k/network.py 359 1 99 236
tests/box_test.py 178 0 100
tests/darknet.py 132 11 91 146, 179-191
tests/image_test.py 45 0 100
tests/network_equivalence_test.py 304 30 90 63, 68, 191-215, 455-465
tests/network_test.py 453 0 100
$
从覆盖率报告中可以看到,d2k项目在box.py和image.py组件中存在一些未覆盖的代码。
贡献
SlipCover正在积极开发中,欢迎贡献代码。如果您有任何建议或遇到问题,请随时创建新问题。
技术细节
更多关于SlipCover的技术细节,请参阅ISSTA'23上发表的论文:SlipCover: Near Zero-Overhead Code Coverage for Python。
致谢
Logo设计由Sophia Berger完成。
本项目得到了美国国家科学基金会(NSF)的支持,项目编号为1955610。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



