我运行了这个测试脚本:
use strict;
use warnings;
use Test::More tests => 3;
use Carp;
ok(1<2);
pass();
fail();
croak "example";
使用命令行prove -MCarp=verbose -v foo.pl
,并出现以下错误:
Subroutine App::Prove::verbose redefined at /opt/ActivePerl-5.12/lib/App/Prove.pm line 407
App::Prove::_load_extension('App::Prove=HASH(0x683718)', 'Carp=verbose') called at /opt/ActivePerl-5.12/lib/App/Prove.pm line 419
App::Prove::_load_extensions('App::Prove=HASH(0x683718)', 'ARRAY(0x683850)') called at /opt/ActivePerl-5.12/lib/App/Prove.pm line 481
App::Prove::run('App::Prove=HASH(0x683718)') called at /opt/ActivePerl-5.12/bin/prove line 11
Undefined subroutine &Carp::verbose called at /opt/ActivePerl-5.12/lib/App/Prove.pm line 484.
如果我使用perl -MCarp=verbose foo.pl
运行它,那就没问题了。导致prove
拒绝详细鲤鱼的原因是什么?如果croak
没有全局替换croak
到confess
,我如何从我的测试中获得完整的callstack?
答案 0 :(得分:10)
prove -M
似乎与perl -M
不同。它似乎加载了证明扩展,而不是将模块加载到您的测试中。文档在这一点上完全不清楚,但App :: Prove中的代码却不是。所以prove -MCarp=verbose
将Carp :: verbose导入App :: Prove导致上述问题。
一个简单的方法就是使用PERL5OPT环境变量加上Carp::Always,它会将所有警告和死亡(以及鲤鱼和呱呱声)变成堆栈痕迹。
PERL5OPT=-MCarp::Always prove ...
无论是否有证明,这都可以在任何情况下工作。
答案 1 :(得分:3)
证明有一组非常不同的命令行参数而不是perl,是一个完全不同的程序吗?
证明-M,我相信,是为了实现pragma; Carp实际上导出了一个verbose()子程序的前向引用,这会干扰证明的内部工作。
您可以创建一个这样的小模块:
# Verbme.pm
use Carp;
$Carp::Verbose = 1;
并通过证明启用它:
prove -MVerbme -v foo.pl
虽然。
答案 2 :(得分:2)
Carp使用导出程序的EXPORT_FAIL
机制来处理verbose
“选项”到import
,这是非常错误的,因为Exporter::Heavy
仍然会尝试分配{{1}尽管事实是“失败”,但{}为*Carp::verbose
。不幸的是,*{"$callerpkg::verbose"}
有一个依赖于工作的详细子,而您的-M选项会导致导入在App::Prove
内发生。我不确定在这里应该责怪谁 - App::Prove
因为(ab)以这种方式使用Carp
,或EXPORT_FAIL
因为Exporter::Heavy
没有从@imports
移除内容@failed
列表,但它们一起打破了它:)