Как я должен рекламировать предупреждения Perl о фатальных ошибках во время разработки? - PullRequest
12 голосов
/ 30 августа 2009

При запуске набора тестов приложений я хочу преобразовать все предупреждения компиляции Perl и предупреждения времени выполнения (например, предупреждение «Uninitialized variable») в фатальные ошибки, чтобы я и другие разработчики исследовали и исправили код, генерирующий предупреждение. Но я хочу делать это только во время разработки и тестирования CI. В производстве предупреждения должны просто оставаться предупреждениями.

Я попробовал следующее: В "t / lib" я создал модуль TestHelper.pm:

.
# TestHelper.pm
use warnings FATAL => qw( all );
1;

Затем вызывается набор тестов следующим образом:

$ PERL5LIB=$PERL5LIB:./t/lib PERL5OPT=-MTestHelper.pm prove -l t/*.t

Но это не привело к желаемому эффекту распространения всех предупреждений о фатальных ошибках. Я получил предупреждения как обычно, но эти предупреждения не считались фатальными. Обратите внимание, что все мои скрипты test.t имеют строку «use warnings;» в них - возможно, это переопределяет тот в TestHelper.pm, потому что «использовать предупреждения» имеет локальную область видимости?

Вместо этого я сделал это:

# TestHelper.pm
# Promote all warnings to fatal 
$SIG{__WARN__} = sub { die @_; };
1;

Это работает, но имеет запах кода. Мне также не нравится, что это взрывается при первом предупреждении. Я бы предпочел, чтобы набор тестов выполнялся полностью, регистрируя все предупреждения, но в конечном итоге статус теста не удался, поскольку код выполнялся с предупреждениями.

Есть ли лучший способ достичь этого конечного результата?

Ответы [ 2 ]

21 голосов
/ 30 августа 2009

Я думаю, что вы ищете Test :: NoWarnings .

17 голосов
/ 30 августа 2009

Причина, по которой use warnings FATAL => qw( all ); не работает для вас, заключается в том, что use warnings имеет лексическую область видимости. Поэтому любые предупреждения, генерируемые внутри TestHelper.pm, будут фатальными, но предупреждения, генерируемые в других местах, будут работать как обычно.

Если вы хотите разрешить фатальные предупреждения глобально, я думаю, что обработчик $SIG{__WARN__}, вероятно, единственный способ сделать это. Если вы не хотите, чтобы оно появилось при первом предупреждении, вы можете позволить своему обработчику сохранить их в массиве, а затем проверить его в блоке END.

my @WARNINGS;
$SIG{__WARN__} = sub { push @WARNINGS, shift };

END { 
    if ( @WARNINGS )  {       
        print STDERR "There were warnings!\n";
        print "$_\n" for @WARNINGS;
        exit 1;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...