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

如何通过pytest定位耗时最长的n个测试用例创建过程?

找出pytest中耗时最长的测试用例创建过程

默认的--durations参数只能统计测试执行阶段的耗时,没法覆盖参数化中测试用例参数的生成过程(也就是你代码里create_test_params这类函数的执行时间)。下面是几种可行的手动统计方案:

方法1:给参数生成函数加计时装饰器

写一个简单的装饰器,用来记录每个参数生成函数的调用耗时,最后在测试结束时输出耗时最长的n个记录。

示例代码:

import time
from collections import defaultdict

# 存储每个函数的调用耗时记录
param_gen_times = defaultdict(list)

def track_param_gen_time(func):
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        # 记录函数名、参数和耗时
        param_gen_times[func.__name__].append({
            "args": args,
            "kwargs": kwargs,
            "elapsed": elapsed
        })
        return result
    return wrapper

# 用装饰器包裹你的参数生成函数
@track_param_gen_time
def create_test_params(n):
    # 原函数逻辑
    time.sleep(0.1)  # 模拟耗时操作
    return {"n": n}

@track_param_gen_time
def create_test_params_alt(n):
    # 原函数逻辑
    time.sleep(0.5)  # 模拟耗时操作
    return {"n": n}

# 在pytest结束时输出统计结果
def pytest_sessionfinish(session, exitstatus):
    print("\n=== 耗时最长的参数生成记录 ===")
    # 把所有记录合并成一个列表
    all_records = []
    for func_name, records in param_gen_times.items():
        for record in records:
            all_records.append({
                "func": func_name,
                "args": record["args"],
                "elapsed": record["elapsed"]
            })
    # 按耗时排序,取前10个
    top_n = 10
    for idx, record in enumerate(sorted(all_records, key=lambda x: x["elapsed"], reverse=True)[:top_n], 1):
        print(f"{idx}. {record['func']}{record['args']}: {record['elapsed']:.4f}s")

把这段代码放到你的conftest.py或者测试模块中,运行测试后,会在终端输出耗时最长的前10个参数生成调用记录。

方法2:在测试用例收集阶段统计总耗时

如果你的参数生成逻辑是直接写在@pytest.mark.parametrize的参数列表里(而非单独函数),可以利用pytest_generate_tests钩子统计整个参数列表的生成总耗时:

import time

def pytest_generate_tests(metafunc):
    # 检查当前测试函数是否有parametrize标记
    for param in metafunc.definition.iter_markers(name="parametrize"):
        argnames, argvalues = param.args[:2]
        # 记录参数生成的开始时间
        start = time.perf_counter()
        # 重新执行参数生成逻辑(注意:若原逻辑有副作用,需调整实现)
        _ = list(argvalues)
        elapsed = time.perf_counter() - start
        print(f"测试函数{metafunc.function.__name__}的参数生成总耗时:{elapsed:.4f}s")

这种方式适合快速定位哪组参数化的生成过程整体耗时久,若需单个参数的耗时,优先用方法1。

注意事项

  • 如果参数生成函数有缓存逻辑,统计时要排除缓存命中的情况,避免结果失真。
  • 统计短耗时推荐用time.perf_counter(),它的精度比time.time()更高。

内容的提问来源于stack exchange,提问作者Nico Schlömer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 09:09:57