【问题标题】:Why won't prove accept -MCarp=verbose?为什么不证明接受 -MCarp=verbose?
【发布时间】:2010-08-31 01:06:57
【问题描述】:

我运行了这个测试脚本:

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 时,如何从我的测试中获得完整的调用堆栈?

【问题讨论】:

    标签: perl testing carp


    【解决方案1】:

    prove -M 似乎不等同于perl -M。它似乎加载了一个证明扩展,而不是将模块加载到您的测试中。文档在这一点上完全不清楚,但 App::Prove 中的代码不是。所以prove -MCarp=verbose 将 Carp::verbose 导入 App::Prove 导致上述问题。

    一种简单的方法是使用 PERL5OPT 环境变量加上 Carp::Always,它将所有警告和死亡(以及鲤鱼和呱呱声)转换为堆栈跟踪。

    PERL5OPT=-MCarp::Always prove ...
    

    这具有在任何情况下工作的额外好处,无论是否有证明。

    【讨论】:

    • 好吧,你是对的,这也是正确的。错过了证明-M 覆盖线束类的部分。尽管如此,我指出的错误似乎存在。 :)
    • 嗯,调查表明你是对的。 prove -MMoose foo.pl 不加载 Moose(根据 %INC),而 PERL5OPT 技巧可以。
    【解决方案2】:

    prove 有一组与 perl 完全不同的命令行参数,是一个完全不同的程序?

    我相信,prove 的 -M 旨在启用编译指示; Carp 实际上导出了对 verbose() 子例程的前向引用,这会干扰 Prove 的内部工作。

    你可以像这样创建一个小模块:

    # Verbme.pm
    use Carp;
    $Carp::Verbose = 1;
    

    并通过证明启用它:

    prove -MVerbme -v foo.pl
    

    虽然。

    【讨论】:

    • App::Prove 中的代码将 -M 中的内容交给 App::Prove->_load_extension() 用于加载证明插件。任何导入都是在 App::Prove 中显式完成的,它甚至会寻找一个特殊的 load() 方法。它是一个记录不充分的功能。
    • @Schwern:但 -P 用于加载插件。我不能相信 -M 不仅适用于证明,而且适用于测试运行是一个意外。虽然我猜发生了奇怪的事故。
    • 完成了一些测试并打印出%INC,看来证明 -M 确实不将模块加载到测试运行中。
    • 是的,-P 用于加载证明“插件”。 -M 用于加载证明“模块”。 prove -M 不将该模块应用于测试,仅用于证明。证明“模块”和证明“插件”之间的唯一区别似乎是证明会为您在插件名称前添加“App::Prove::Plugin::”。 App::Prove->run 中的代码对此事非常清楚。我同意它的设计是为了最大程度地混淆。
    • @Schwern:谢谢,出于某种原因,我确信 -M 正在传播到运行测试中,但不知何故我显然弄错了
    【解决方案3】:

    Carp 使用 Exporter 的 EXPORT_FAIL 机制来处理 verbose 到 import 的“选项”,这是非常错误的,因为 Exporter::Heavy 仍然会尝试将 *Carp::verbose 分配给 *{"$callerpkg::verbose"},尽管事实上它“失败”了。不幸的是,App::Prove 有一个详细的子程序,它依赖于它的工作,而您的 -M 选项会导致导入在 App::Prove 内发生。我不确定应该责备谁——Carp (ab)以这种方式使用EXPORT_FAIL,或者Exporter::Heavy 没有从@imports 中删除东西,如果它在@failed 列表中,但在一起他们正在打破它:)

    【讨论】:

    • 好吧,发布的 OP 的问题是,Prove 正在爆炸,因为它的 verbose 方法被破坏了。虽然我想如果那没有发生,不久之后它就会以不同的方式爆炸。
    • 如果它没有爆炸,它就不会默默地工作。你可以通过prove -MMoose 看到这一点,它根本不会加载 Moose 并运行测试。所以我很幸运,它爆炸了,而不是默默地失败了:)
    猜你喜欢
    • 2023-03-27
    • 2022-06-10
    • 1970-01-01
    • 2015-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多