Можно ли использовать или требовать сценарий Perl без выполнения его операторов? - PullRequest
17 голосов
/ 24 октября 2008

Мне нужно добавить модульное тестирование для некоторых старых сценариев, все сценарии в основном имеют следующий вид:

#!/usr/bin/perl

# Main code
foo();
bar();

# subs
sub foo {

}
sub bar {

}

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

Есть ли способ сделать это без перемещения foo, bar в отдельный файл .pm?

Ответы [ 3 ]

17 голосов
/ 24 октября 2008

Если у вас нет проблем с безопасностью, оберните его в подпункт {...} и оцените его:

use File::Slurp "read_file";
eval "package Script; sub {" . read_file("script") . "}";

is(Script::foo(), "foo");

(с учетом того, что eval не входит в сферу действия каких-либо лексических выражений, которые будут закрыты сценарием).

16 голосов
/ 24 октября 2008

Еще одна распространенная уловка для скриптов модульного тестирования - это обернуть тело их кода в блок «вызывающего»:

#!/usr/bin/perl

use strict;
use warnings;

unless (caller) {
    # startup code
}

sub foo { ... }

При запуске из командной строки, cron, bash-скрипта и т. Д. Он работает нормально. Однако, если вы загрузите его из другой Perl-программы, код "never (caller) {...}" не будет запущен. Затем в вашей тестовой программе объявите пространство имен (поскольку сценарий, вероятно, выполняет код в пакете main: :) и «сделайте» сценарий.

#!/usr/bin/perl

package Tests::Script;   # avoid the Test:: namespace to avoid conflicts
                         # with testing modules
use strict;
use warnings;

do 'some_script' or die "Cannot (do 'some_script'): $!";

# write your tests

do более эффективен, чем eval, и достаточно чист для этого.

Еще один прием для тестирования скриптов - использовать Expect . Это чище, но также сложнее в использовании и не позволит вам переопределить что-либо в скрипте, если вам нужно что-то макетировать.

10 голосов
/ 24 октября 2008

Ааа, старый вопрос "как мне протестировать программу". Самый простой трюк - вставить это в вашу программу, прежде чем она начнет что-то делать:

return 1 unless $0 eq __FILE__;

__FILE__ - текущий исходный файл. $0 - это название программы, которая запускается. Если они совпадают, ваш код выполняется как программа. Если они разные, он загружается как библиотека.

Этого достаточно, чтобы начать модульное тестирование подпрограмм внутри вашей программы.

require "some/program";
...and test...

Следующий шаг - переместить весь код вне подпрограммы в main, тогда вы можете сделать это:

main() if $0 eq __FILE__;

и теперь вы можете проверить main (), как и любую другую подпрограмму.

Как только это будет сделано, вы можете начать думать о перемещении подпрограмм программы в свои собственные реальные библиотеки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...