You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用pytest检查每个函数是否有对应单元测试并区分调用来源?

问题描述

我需要确保代码库中每个实现的函数都有对应的单元测试。举个例子:

def top_level_function():
    sub_function()

def sub_function():
    print('hello')

如果测试top_level_function时忘了patch/mock子函数调用,原sub_function会被执行——哪怕它没有单元测试,测试覆盖率仍会显示100%。这说明测试覆盖率根本不足以判断单元测试是否充足。

我想搞清楚两个问题:
a) 怎么确认函数是被对应的单元测试调用的(符合预期的测试路径);
b) 怎么确认函数是被父函数调用的(这是测试时要避免的情况)。

有没有额外的pytest包或pytest-cov设置能报告缺失的单元测试?我还没找到合适的工具。
(注:我希望top_level_function的单元测试只在自身出错时失败,而不是因为sub_function有bug才失败,所以测试函数时通常会mock子函数调用。)

补充说明

  • 试过pytest-func-cov插件,但它似乎没法正常工作(有公开问题),有没有能用的替代插件?
  • PyCharm的Pycrunch插件能显示代码行被哪个单元测试覆盖,但解决不了我的问题,只能辅助识别覆盖异常的代码行。
解决方案

针对问题a和b:追踪函数的测试调用来源

1. 用pytest-cov的函数级覆盖+自定义标记

pytest-cov本身不直接追踪调用来源,但可以结合自定义测试标记和coverage的context功能,区分不同测试对函数的覆盖:

  • 给每个函数的专属测试用例加标记,比如@pytest.mark.test_sub_function
  • 在测试sub_function的用例里,设置coverage的context:
import coverage
cov = coverage.Coverage()
cov.start()
cov.set_context("test_sub_function")
# 执行测试逻辑
cov.stop()
cov.save()

生成报告时按context筛选,就能看到sub_function的覆盖是来自它自己的测试用例,还是被top_level_function的测试间接触发的。

2. 用pytest-trace插件或自定义追踪装饰器

  • pytest-trace:这个插件能追踪每个函数被哪些测试用例调用,运行测试时加--trace参数,输出里就能看到函数的调用链路,直接区分是被自身测试调用还是父函数调用。
  • 自定义装饰器:给需要追踪的函数加个装饰器,记录调用它的测试用例名称:
import inspect
import pytest

def track_test_calls(func):
    def wrapper(*args, **kwargs):
        # 获取当前运行的测试用例名称
        frame = inspect.currentframe()
        while frame:
            if "request" in frame.f_locals:
                test_name = frame.f_locals["request"].nodeid
                print(f"{func.__name__} called by test: {test_name}")
                break
            frame = frame.f_back
        return func(*args, **kwargs)
    return wrapper

# 给函数加装饰器
@track_test_calls
def sub_function():
    print('hello')

运行测试时就能看到sub_function是被哪个测试触发的,从而判断是否符合预期。

检测缺失单元测试的工具

1. 自定义脚本对比函数与测试用例

用inspect模块遍历代码中的所有函数,再用pytest的API收集所有测试用例,提取每个测试用例直接调用的函数,对比两者就能找出没有对应测试用例的函数。也可以结合pytest-mock-generator生成mock,辅助确认哪些函数没被直接测试。

2. pytest-cov的函数级覆盖强制检查

开启coverage的函数级覆盖,设置--cov-report term --cov-fail-under 100,同时在.coveragerc里配置:

[report]
show_missing = True
function_coverage = True

这样如果某个函数没有被任何测试直接调用(哪怕被间接覆盖),函数级覆盖率会显示缺失,从而触发失败。不过这个方法需要确保所有间接调用都被mock,否则会误判,得配合mock策略使用。

3. pytest-testmon

这个插件能追踪测试用例和代码的依赖关系,识别哪些代码没有对应的测试用例,还能只运行受代码变更影响的测试。虽然不是直接报告缺失测试,但能帮你发现哪些函数从未被测试用例直接触发。

替代pytest-func-cov的插件

可以试试pytest-cov的函数级覆盖(上面提到的配置),或者pytest-coverage-report插件——它提供更详细的函数级覆盖报告,能明确显示每个函数的覆盖来源。

内容的提问来源于stack exchange,提问作者Stefan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 13:45:38