测试运行覆盖率
Run Coverage on Tests

原始链接: https://hugovk.dev/blog/2025/run-coverage-on-tests/

强烈建议对测试进行覆盖,以识别可能导致错过测试执行和未检测到错误的微妙问题。一个常见的问题是在复制和粘贴代码时无意中定义了重复的测试函数名称,导致其中一个测试被跳过而没有任何明显的指示。覆盖率报告很容易突出这些非运行测试。 当测试逻辑依赖于过早消耗的生成器时,会出现另一个更阴险的问题。这可能会导致部分测试代码永远无法执行,从而掩盖潜在的故障。Codecov等覆盖率工具可以通过在测试期间显示没有代码覆盖的区域来精确定位这些部分。通过可视化代码的哪些部分实际上正在被测试,覆盖率报告确保了测试套件的健壮性,并彻底验证了代码的功能。解决这些覆盖差距可以带来更可靠和值得信赖的测试。

Hacker Newsnew |过去|评论| ask | show | jobs | submitlogin测试运行覆盖率(hugovk.dev)7分todsacerdoti 1天前|隐藏|过去|收藏| 1条评论 IshKebab 1天前[–] “正确”的方法是定义代码的功能覆盖率,然后你会意识到,当你没有达到测试应该达到的覆盖点时,测试就失败了。不过,我从未见过在软件中使用功能覆盖率,只在硬件验证中使用过。Bug的成本不足以使其值得付出努力。也。..只要使用比Python更好的语言,这些琐碎的错误就不会那么容易发生。reply 考虑申请YC 2025年秋季批次!申请截止日期为8月4日 指南|常见问题|列表| API |安全|法律|申请YC |联系方式 搜索:
相关文章

原文

I recommend running coverage on your tests.

Here’s a couple of reasons why, from the past couple of months.

Example one #

When writing tests, it’s common to copy and paste test functions, but sometimes you forget to rename the new one (see also: the Last Line Effect).

For example:

def test_get_install_to_run_with_platform(patched_installs):
    i = installs.get_install_to_run("<none>", None, "1.0-32")
    assert i["id"] == "PythonCore-1.0-32"
    assert i["executable"].match("python.exe")
    i = installs.get_install_to_run("<none>", None, "2.0-arm64")
    assert i["id"] == "PythonCore-2.0-arm64"
    assert i["executable"].match("python.exe")


def test_get_install_to_run_with_platform(patched_installs):
    i = installs.get_install_to_run("<none>", None, "1.0-32", windowed=True)
    assert i["id"] == "PythonCore-1.0-32"
    assert i["executable"].match("pythonw.exe")
    i = installs.get_install_to_run("<none>", None, "2.0-arm64", windowed=True)
    assert i["id"] == "PythonCore-2.0-arm64"
    assert i["executable"].match("pythonw.exe")

The tests pass, but the first one is never run because its name is redefined. This clearly shows up as a non-run test in the coverage report. In this case, we only need to rename one of them, and both are covered and pass.

But sometimes there’s a bug in the test which would cause it to fail, but we just don’t know because it’s not run.

 

Example two #

This is more subtle:

im = Image.new("RGB", (1, 1))
for colors in (("#f00",), ("#f00", "#0f0")):
    append_images = (Image.new("RGB", (1, 1), color) for color in colors)
    im_reloaded = roundtrip(im, save_all=True, append_images=append_images)

    assert_image_equal(im, im_reloaded)
    assert isinstance(im_reloaded, MpoImagePlugin.MpoImageFile)
    assert im_reloaded.mpinfo is not None
    assert im_reloaded.mpinfo[45056] == b"0100"

    for im_expected in append_images:
        im_reloaded.seek(im_reloaded.tell() + 1)
        assert_image_similar(im_reloaded, im_expected, 1)

It’s not so obvious when looking at the code, but Codecov highlights a problem:

The same code, but Codecov has flagged the last two lines were not covered

The append_images generator is being consumed inside roundtrip(), so we have nothing to iterate over in the for loop – hence no coverage. The fix is to use a list instead of a generator.


Header photo: Misplaced manhole cover (CC BY-NC-SA 2.0 Hugo van Kemenade).

联系我们 contact @ memedata.com