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

能否让Test::More报告Perl测试中间接调用者的行号?

解决Test::More显示间接调用者行号的问题

要让Test::More在测试失败时显示**间接调用者(如main中调用complex_test的行号)**而非直接调用ok()的子例程行号,核心是调整Test::Builder的caller_level属性,让它跳过中间的封装子例程,从调用栈的更上层获取行号信息。

具体实现方法

修改你的foo_OK子例程,临时调整caller_level,执行测试后再恢复原有层级:

#!/usr/bin/perl
use 5.18.2;
use warnings;
use strict;
use Test::More;

sub foo(@)
{
    # do something magical
    return undef;
}

sub foo_OK(@)
{
    my $tb = Test::More->builder;
    # 保存原始调用层级,避免影响其他测试
    my $original_level = $tb->caller_level;
    # 增加2层,跳过foo_OK和complex_test,指向main中的调用行
    $tb->caller_level($original_level + 2);
    
    ok(foo(@_), 'foo_OK: ' . join(' ', @_));
    
    # 恢复原始调用层级
    $tb->caller_level($original_level);
}

sub complex_test(@)
{
    foo_OK(qw(something special), @_);
    foo_OK(qw(something else), @_);
    #...

}

sub main()
{
    complex_test(qw(abra kadabra)); # 假设这是第28行
    complex_test(qw(more magic));   # 假设这是第29行
    #...
}

main();
done_testing();

修改后的输出效果

运行后,失败测试的行号会指向main中调用complex_test的行:

not ok 1 - foo_OK: something special abra kadabra
#   Failed test 'foo_OK: something special abra kadabra'
#   at /tmp/test.pl line 28.
not ok 2 - foo_OK: something else abra kadabra
#   Failed test 'foo_OK: something else abra kadabra'
#   at /tmp/test.pl line 28.
not ok 3 - foo_OK: something special more magic
#   Failed test 'foo_OK: something special more magic'
#   at /tmp/test.pl line 29.
not ok 4 - foo_OK: something else more magic
#   Failed test 'foo_OK: something else more magic'
#   at /tmp/test.pl line 29.
1..4
# Looks like you failed 4 tests of 4.

原理说明

Test::More的所有测试函数(如ok)都依赖Test::Builder模块跟踪调用栈。caller_level属性决定了从调用栈的哪一层提取文件名和行号:

  • 默认值为1,对应直接调用ok的子例程(即foo_OK)的行号
  • 增加该值时,会跳过中间的调用层级,指向更上层的代码(这里+2跳过了foo_OK和complex_test,直接指向main中的调用行)

如果后续有更多层级的封装,只需调整+N中的N值,确保指向你需要的调用行即可。


内容的提问来源于stack exchange,提问作者U. Windl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 23:48:16