Как я могу поймать выход из карпа в Perl?

Я пишу модуль Perl, и я использую carp для того, чтобы вызывать нефатальное предупреждение обратно вызывающей программе.

Предупреждение карпа отлично работает - я проверяю, соответствует ли входной параметр определенному условию - если он не соответствует условию, предупреждение отправляется с карпом, и модуль продолжает использовать значение по умолчанию для параметра вместо одного вызывающая программа прошла. Предупреждение состоит только в том, чтобы уведомить, что вместо переданного параметра используется параметр по умолчанию.

Моя проблема связана с моим тестом script. Мой тест script отправляет плохому параметру в модуль, и я пытаюсь поймать предупреждающее сообщение, которое возвращается, и убедитесь, что я получил правильное предупреждающее сообщение.

Мой модуль выглядит примерно так:

else {
  carp "value must be numeric - using default value";
}

и мой тест script выглядит следующим образом:

eval {
  #call to my module
};
like (
    [email protected],
    qr/value must be numeric/,
    "Should abort on non-numeric value"
);

Когда я запускаю тест, я вижу предупреждение (оно должно быть на STDERR) на экране, но содержимое переменной [email protected]равно '' - пустое.

Вот результат моего теста script:

t/04bad_method_calls....ok 10/12value must be numeric - using default value at ...
#   Failed test 'Should abort on non-numeric value'
#   at t/04bad_method_calls.t line 98.
t/04bad_method_calls....NOK 12
#                   '' doesn't match '(?-xism:value must be numeric)'
# Looks like you failed 1 test of 12.

Если я изменю карпа на каркас, мой тест script работает - он ловит сообщение об ошибке (но я хочу только предупредить, а не прервать).

Если честно, у меня нет лучшего понимания eval - возможно, это не лучший способ поймать вывод предупреждения от карпа. Я попытался использовать $SIG { WARN}, но это тоже было пустым.

Есть ли способ захватить вывод из карпа? Это не самая большая сделка, так как это только в моем тесте script, но я все равно хочу, чтобы мой тест script работал правильно.

Спасибо заранее!

Ответ 1

На этой странице http://perldoc.perl.org/perlvar.html похоже, что вы хотите установить локальную $SIG{__WARN__} в подпрограмму, которая превратит предупреждения в фатальные ошибки для вашего теста script. Пример, который они приводят:

local $SIG{__WARN__} = sub { die $_[0] };
eval $proggie;

Ответ 2

Другой способ, как уловить предупреждения, а также весь вывод STERR:

my $stderr = '';
{
    local *STDERR;
    open STDERR, '>', \$stderr;
    do_stuf_here();
}
like( $stderr, qr/my result/, 'test stderr output' );

Можно выполнить необычную тестовую функцию:

sub stderr_test (&$$) {
    my ( $code, $pattern, $text ) = @_;
    my $result = '';
    {
        local *STDERR;
        open STDERR, '>', \$result;
        $code->();
    }
    if ( UNIVERSAL::isa( $pattern, 'Regexp' ) ) {
        like( $result, $pattern, $text );
    }
    else {
        is( $result, $pattern, $text );
    }
}

# usage
stderr_test {do_stuf_here} qr/my expected STDERR output/,
    'stderr is like';
stderr_test {do_stuf_here} 'my expected STDERR output',
    'stderr is exactly';

Ответ 3

Если вы делаете это из теста script, вы можете использовать модули Test:: *, которые захватывают вывод для вас. Мне нравится Test:: Output.