2009-01-27 6 views
13

Estoy escribiendo un módulo Perl, y estoy usando carp para devolver una advertencia no fatal al programa de llamada.¿Cómo puedo capturar la salida de una carpa en Perl?

La advertencia de carpa funciona bien - Estoy comprobando si un parámetro de entrada cumple una determinada condición - si no cumple con la condición, se envía una advertencia con carpa y el módulo continúa usando un valor predeterminado para el parámetro en lugar del uno que pasó el programa de llamadas. La advertencia es solo para notificar que se está utilizando un parámetro predeterminado en lugar del parámetro pasado.

Mi problema es con mi script de prueba. Mi script de prueba está enviando un parámetro incorrecto al módulo, y estoy tratando de captar el mensaje de advertencia que aparece y asegurarme de que recibí el mensaje de advertencia correcto.

Mi módulo es como la siguiente:

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

y mi escritura de la prueba es el siguiente:

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

Cuando ejecuto la prueba, puedo ver el aviso (hay que va a STDERR) en la pantalla, pero el contenido de la variable $ @ está '' - en blanco.

Aquí está la salida de mi escritura de la prueba:

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. 

Si cambio de la carpa a un graznido, mi script de prueba funciona - capta el mensaje de error (pero sólo quiero advertir, sin renunciar) .

Para ser sincero, no tengo la mejor comprensión de eval - tal vez esa no sea la mejor manera de captar la salida de advertencia de la carpa. Intenté usar $ SIG {WARN}, pero eso también estaba vacío.

¿Hay alguna forma de capturar la salida de la carpa? No es el mejor negocio, ya que es solo en mi script de prueba, pero aún me gustaría que mi script de prueba funcione correctamente.

¡Gracias de antemano!

Respuesta

19

De esta página, http://perldoc.perl.org/perlvar.html, parece que desea establecer el $SIG{__WARN__} local en una subrutina que convertirá las advertencias en errores fatales para su script de prueba. El ejemplo que dan es:

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

Sí, ese fue el truco! Estaba malinterpretando lo que era $ SIG {__ WARN__}. Esto funciona perfectamente, ¡muchas gracias! – BrianH

6

Otra forma cómo atrapar advertencias y también todos los STERR de salida:

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

Uno puede hacer la función de prueba de fantasía:

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'; 
+0

Guau, muy interesante. Ese primer ejemplo es bastante directo y parece funcionar muy bien también. – BrianH

6

Si eres haciendo esto desde un script de prueba, puede usar los módulos Test :: * que capturan el resultado por usted. Tiendo a gustarme Test::Output.

+0

Parece una solución bastante simple. Desafortunadamente, no tengo Test :: Output instalado en nuestro entorno, y la instalación de módulos está bastante desaconsejada aquí. Aunque no se ajusta a mis necesidades, +1 para una gran solución. – BrianH

+0

Test :: Exception también funciona muy bien para esto. –

Cuestiones relacionadas