2009-01-27 6 views
13

J'écris un module Perl, et j'utilise la carpe pour renvoyer un avertissement non-fatal au programme appelant. L'avertissement de carpe fonctionne bien - je vérifie si un paramètre d'entrée remplit certaines conditions - s'il ne répond pas à la condition, un avertissement est envoyé avec carpe et le module continue en utilisant une valeur par défaut pour le paramètre au lieu de la un programme d'appel est passé. L'avertissement est juste pour notifier qu'un paramètre par défaut est utilisé à la place du paramètre passé.Comment puis-je attraper la sortie d'une carpe en Perl?

Mon problème est avec mon script de test. Mon script de test envoie un mauvais paramètre au module, et j'essaie d'attraper le message d'avertissement qui revient et de m'assurer que j'ai reçu le bon message d'avertissement.

Mon Module ressemble à ceci:

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

et mon script de test ressemble à ceci:

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

Quand je lance le test, je peux voir l'avertissement (il doit être va STDERR) sur l'écran, mais le contenu de la variable $ @ est '' - vide.

Voici la sortie de mon script de 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. 

Si je change la carpe à un croassement, mon script de test fonctionne - il attrape le message d'erreur (mais je veux seulement avertir, pas avorter) .

Pour être honnête, je n'ai pas la meilleure compréhension d'eval - peut-être que ce n'est pas la meilleure façon d'attraper le signal d'alarme de la carpe. J'ai essayé d'utiliser $ SIG {WARN}, mais c'était vide aussi.

Y at-il un moyen de capturer la sortie de la carpe? Ce n'est pas la plus grosse affaire puisque c'est juste dans mon script de test, mais j'aimerais quand même que mon script de test fonctionne correctement.

Merci d'avance!

Répondre

19

À partir de cette page, http://perldoc.perl.org/perlvar.html, il semble que vous souhaitiez définir le $SIG{__WARN__} local sur un sous-programme qui transformera les avertissements en erreurs fatales pour votre script de test. L'exemple qu'ils donnent est:

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

Oui, c'était le truc! Je ne comprenais pas ce que $ SIG {__ WARN__} était. Cela fonctionne parfaitement - merci beaucoup! – BrianH

6

Une autre façon comment attraper les avertissements et aussi toutes les sorties STERR:

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

On peut faire fonction de test de fantaisie:

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

Wow - très intéressant. Ce premier exemple est assez simple et semblerait bien fonctionner aussi bien. – BrianH

6

Si vous êtes Pour ce faire, à partir d'un script de test, vous pouvez utiliser les modules Test :: * qui capturent la sortie pour vous. J'ai tendance à aimer Test::Output.

+0

Cela ressemble à une solution assez simple. Malheureusement, Test :: Output n'est pas installé dans notre environnement, et l'installation de modules est assez déconseillée ici. Même si cela ne correspond pas à mes besoins, +1 pour une excellente solution. – BrianH

+0

Test :: Exception fonctionne également très bien pour cela. –

Questions connexes