Почему не докажут, что -MCarp=verbose?

Я запустил этот тестовый скрипт:

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 отказаться от многословного карпа? Как я могу получить полный callstack из моих тестов, когда они croak без глобальной замены croak в confess?

3 ответа

Решение

prove -M не представляется эквивалентным perl -M, Похоже, что вы загружаете проверочное расширение, а не загружаете модуль в свои тесты. Документы на этот счет совершенно неясны, но код в App::Prove - нет. Так prove -MCarp=verbose импортирует Carp::verbose в App::Prove, вызывая проблему, описанную выше.

Простой способ сделать то, что вы хотите, это использовать переменную окружения PERL5OPT плюс Carp:: Always, которая превратит все предупреждения и умирает (и карпы и каркает) в следы стека.

PERL5OPT=-MCarp::Always prove ...

Это дает дополнительное преимущество работы в любой ситуации, с доказательством или без него.

Доказательство имеет совершенно другой набор аргументов командной строки, чем Perl, будучи совершенно другой программой?

Я полагаю, что доказательство -М предназначено для включения прагм; На самом деле Carp экспортирует прямую ссылку на подпрограмму verbose(), которая вмешивается во внутреннюю работу доказательства.

Вы можете создать небольшой модуль, например так:

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

и включите его от доказать:

prove -MVerbme -v foo.pl

хоть.

Карп использует Экспортер EXPORT_FAIL механизм для обработки verbose "вариант" для import, что в значительной степени неправильно, так как Exporter::Heavy все равно попробую назначить *Carp::verbose в *{"$callerpkg::verbose"} несмотря на то, что это было "провалено". К несчастью, App::Prove имеет подробный саб, от которого зависит работа, а опция -M вызывает импорт в пределах App::Prove, Я не уверен, кто здесь виноват - Carp для (ab) использования EXPORT_FAIL таким образом, или Exporter::Heavy для того, чтобы не удалять вещи из @imports если это в @failed список, но вместе они ломают его:)

Другие вопросы по тегам