Подтвердить что ты не робот

Как я могу unit test функции Perl печатать на экране?

Я пытаюсь использовать Test::More для unit test функций Perl, которые печатаются на экране.

Я понимаю, что этот вывод может помешать инструментам, таким как prove.

Как я могу захватить этот вывод, чтобы я мог распечатать его с помощью diag(), а также запустить тесты на самом выходе?

4b9b3361

Ответ 1

ОБНОВЛЕНИЕ: ИМХО, правильный ответ на этот вопрос должен состоять в использовании 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');

Вывод:

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

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

Вы можете локализовать STDOUT и снова открыть скаляр перед вызовом функции, восстановить позже:

#!/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'");

Вывод:

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

Для версий perl старше 5.8 вам, вероятно, нужно будет использовать IO::Scalar, но я мало знаю о том, как вещи работал до 5.8.

Ответ 2

Я бы посмотрел, чтобы позволить модулю справиться с этим для вас. Посмотрите Capture::Tiny.

Ответ 3

Если это код, который вы пишете самостоятельно, измените его так, чтобы операторы печати не использовали дескриптор файла по умолчанию. Вместо этого дайте себе способ установить дескриптор выходного файла на все, что вам нравится:

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

Когда вы тестируете, вы можете вызвать _set_output_fh, чтобы передать его дескриптор файла тестирования (возможно, даже IO:: Null). Когда другой человек хочет использовать ваш код, но захватить вывод, им не нужно наклоняться назад, чтобы сделать это, потому что они могут предоставить свой собственный дескриптор файла.

Когда вы находите часть своего кода, который трудно тестировать, или что вам нужно прыгать через обручи для работы, у вас, вероятно, плохой дизайн. Я все еще удивляюсь тому, как тестовый код делает эти вещи очевидными, потому что я часто не думал о них. Если это трудно проверить, попробуйте протестировать. Вы обычно выигрываете, если вы это делаете.