34 votes

Comment puis-je tester unitairement les fonctions Perl qui impriment à l'écran ?

J'essaie d'utiliser Test::More pour tester les fonctions Perl qui s'affichent à l'écran.

Je comprends que cette sortie peut interférer avec des outils tels que prouver .

Comment puis-je capturer cette sortie afin de l'imprimer avec diag() et d'effectuer des tests sur la sortie elle-même ?

32voto

Sinan Ünür Points 76179

UPDATE : Selon moi, la bonne réponse à cette question devrait être l'utilisation de Test::Output :

#!/usr/bin/perl

use strict; use warnings;

use Test::More tests => 1;
use Test::Output;

sub myfunc { print "This is a test\n" }

stdout_is(\&myfunc, "This is a test\n", 'myfunc() returns test output');

Sortie :

C:\\Temp> tm
1..1
ok 1 - myfunc() returns test output

Je laisse la réponse originale à titre de référence, car je pense qu'elle illustre toujours une technique utile. .

Vous pouvez localiser STDOUT et rouvrir à un scalaire avant d'appeler la fonction, restaurer après :

#!/usr/bin/perl

use strict; use warnings;

use Test::More tests => 1;

sub myfunc { print "This is a test\n" }

sub invoke {
    my $sub = shift;
    my $stdout;
    {
        local *STDOUT;
        open STDOUT, '>', \$stdout
            or die "Cannot open STDOUT to a scalar: $!";
        $sub->(@_);
        close STDOUT
            or die "Cannot close redirected STDOUT: $!";
    }
    return $stdout;
}

chomp(my $ret =  invoke(\&myfunc));

ok($ret eq "This is a test", "myfunc() prints test string" );
diag("myfunc() printed '$ret'");

Sortie :

C:\\Temp> tm
1..1
ok 1 - myfunc() prints test string
# myfunc() printed 'This is a test'

Pour les versions de perl plus ancienne que la version 5.8, vous devrez probablement utiliser l'option IO::Scalar mais je ne sais pas grand chose de la façon dont les choses fonctionnaient avant la version 5.8.

7voto

mpeters Points 3304

J'envisagerais de laisser un module s'en charger pour vous. Regardez Capture::Tiny .

6voto

brian d foy Points 71781

S'il s'agit d'un code que vous écrivez vous-même, modifiez-le pour que les instructions d'impression n'utilisent pas un filehandle par défaut. Au lieu de cela, donnez-vous la possibilité de définir le filehandle de sortie comme vous le souhaitez :

sub my\_print {
     my $self = shift;
     my $fh = $self->\_get\_output\_fh;
     print { $fh } @\_;
     }

sub \_get\_output\_fh { $\_\[0\]->{\_output}  || \\\*STDOUT }
sub \_set\_output\_fh { $\_\[0\]->{\_output} = $\_\[1\] } # add validation yourself

Lors du test, vous pouvez appeler _set_output_fh pour lui donner votre nom de fichier de test (peut-être même un nom de fichier IO::Null poignée). Lorsqu'une autre personne souhaite utiliser votre code mais capturer la sortie, elle n'a pas besoin de se plier en quatre pour le faire car elle peut fournir son propre filehandle.

Lorsqu'une partie de votre code est difficile à tester ou que vous devez faire des pieds et des mains pour travailler avec elle, c'est qu'elle est probablement mal conçue. Je suis toujours étonné de voir à quel point les tests de code rendent ces choses évidentes, parce que souvent je n'y aurais pas pensé. S'il est difficile de tester, rendez-le facile à tester. Vous gagnez généralement si vous faites cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X