Come posso catturare l'output di una carpa in Perl?
Domanda
Sto scrivendo un modulo Perl e sto usando carp per inviare un avviso non fatale al programma chiamante.
L'avviso di carpa funziona correttamente - Sto verificando se un parametro di input soddisfa una determinata condizione - Se non soddisfa la condizione, viene inviato un avviso con carpa e il modulo continua a utilizzare un valore predefinito per il parametro anziché quello il programma chiamante è passato. L'avvertimento è solo quello di notificare che viene utilizzato un parametro predefinito anziché il parametro passato.
Il mio problema è con il mio script di prova. Il mio script di test sta inviando un parametro errato al modulo e sto cercando di catturare il messaggio di avviso che ritorna e assicurarmi di aver ricevuto il messaggio di avviso corretto.
Il mio modulo è simile al seguente:
else {
carp "value must be numeric - using default value";
}
e il mio script di test è simile al seguente:
eval {
#call to my module
};
like (
$@,
qr/value must be numeric/,
"Should abort on non-numeric value"
);
Quando eseguo il test, posso vedere l'avvertimento (deve andare su STDERR) sullo schermo, ma il contenuto della variabile $ @ è '' - vuoto.
Ecco l'output del mio script di test:
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.
Se cambio la carpa in un gracchiare, il mio script di test funziona - cattura il messaggio di errore (ma voglio solo avvisare, non interrompere).
Ad essere sincero, non ho la migliore comprensione di eval - forse questo non è il modo migliore per catturare l'output di avvertimento dalle carpe. Ho provato a usare $ SIG { WARN }, ma anche quello era vuoto.
C'è un modo per catturare l'output dalla carpa? Non è il più grande affare poiché questo è solo nel mio script di test, ma mi piacerebbe comunque far funzionare correttamente il mio script di test.
Grazie in anticipo!
Soluzione
Da questa pagina, http://perldoc.perl.org/perlvar.html , sembra che tu voglia impostare il $SIG{__WARN__}
locale su una subroutine che trasformerà gli avvisi in errori fatali per il tuo script di test. L'esempio che danno è:
local $SIG{__WARN__} = sub { die $_[0] };
eval $proggie;
Altri suggerimenti
Un altro modo per catturare gli avvisi e anche tutti gli STERR
output:
my $stderr = '';
{
local *STDERR;
open STDERR, '>', \$stderr;
do_stuf_here();
}
like( $stderr, qr/my result/, 'test stderr output' );
Si può far funzionare la fantasia test:
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';
Se lo fai da uno script di test, puoi utilizzare i moduli Test :: * che acquisiscono l'output per te. Tendo a gradire Test :: Output .