为什么不能证明接受-MCarp = verbose?

时间:2010-08-31 01:06:57

标签: perl testing carp

我运行了这个测试脚本:

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没有全局替换croakconfess,我如何从我的测试中获得完整的callstack?

3 个答案:

答案 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列表,但它们一起打破了它:)