Как писать модульные тесты для Perl-скрипта

Я умею писать модульные тесты test_case.t для модуля Perl ModuleOne.pm

test_case.t

use strict;
use warnings;
use Test::More;
use Test::Cmd;
use ModuleOne; # Included the module here

my $ret = ModuleOne::methodone(args);
is($ret->{val}, 1, "Checking return value"); # success 

Я пытаюсь выполнить те же модульные тесты для сценария Perl script_one.pl

script_one.pl

use strict;
use warnings;
use ModuleOne;

my $NAME;
my $ID;

# get parameters
GetOptions (
 "name" => \$NAME,
 "emp_id" => \$ID,
)

validate_params();

sub validate_params {
   # this method will validate params 
}

sub print_name {
   # this method will print name 
}

Как я могу включить этот файл perl script_one.pl в test_case.t и написать тестовые примеры для методов validate_params и print_name?


person Srikanth Jeeva    schedule 03.08.2017    source источник


Ответы (1)


Есть пара вариантов. Один из них - использовать Test :: Script, чтобы проверить, компилируется ли и выполняется ли ваш код, и делает ли он что-то вещи. Это скорее интеграционный тест, чем модульный тест, и если у вас есть внешние зависимости, такие как запись в файловую систему, сложно отмахнуться от них таким образом.

Поскольку у вас есть подпрограммы в скрипте, самый простой способ - это, вероятно, require или do скрипт в вашем тестовом файле, возможно, внутри другого package (но это не имеет особого значения). Затем вы можете вызвать эти функции, потому что они находятся в одном из ваших пространств имен.

use strict;
use warnings;
use Test::More;

package Foo {
    do 'script_one.pl';
};

is Foo::print_name, 'foo', 'prints the right name';

Таким образом, вам будет проще имитировать зависимости и получить больше контроля. Единственное, что может быть сложно, - это код, которого нет в подпрограммах и который будет запускаться при вызове, например, при вызове validate_params. Вы можете просто использовать Capture :: Tiny, чтобы смахнуть это под коврик.

Однако лучший вариант - не иметь функций в вашем скрипте. Просто создайте другой модуль, у которого есть эти функции, и вызовите его в своем скрипте. Иметь сценарий, подобный приведенному ниже, - это нормально.

#!/usr/bin/env perl
use strict;
use warnings;
use My::Modules::Foo;

My::Modules::Foo->run; # or ::run()

Неважно, ООП это или нет. По идее будет та же. Если вы правильно инкапсулируете его, вы можете проводить модульное тестирование всего кода, даже не используя этот скрипт.

Что касается GetOpts, эти переменные могут быть лексическими для сценария, но ваше имя с заглавными буквами и отсутствие аргументов для вызова validate_params указывают на то, что они действительно распространяются на весь пакет и используются внутри функции. Не делай этого. Используйте аргументы для subs. Поместите все подпрограммы в package, затем добавьте GetOpts в сценарий и передайте параметры в качестве аргументов функции.

Таким образом, вы можете протестировать все, и сценарий действительно не понадобится.

person simbabque    schedule 03.08.2017
comment
Честно говоря, правильный подход к тестированию скриптов - полностью отказаться от модульного тестирования. Вместо этого воспользуйтесь интеграционным тестированием с помощью вышеупомянутого Test::Script. С точки зрения конечного пользователя важно только то, что сценарий внешне работает так, как ожидалось; Независимо от того, работают ли частные функции, внутренне вызываемые этим скриптом, как ожидалось, не имеет значения. - person Cecil Curry; 20.03.2020