Переопределять переменные при тестировании автономного сценария Perl - PullRequest
5 голосов
/ 13 апреля 2010

В нашей среде есть Perl-скрипт, который мне нужно поддерживать. Он полон дурных практик, включая использование (и повторное использование) глобальных переменных в скрипте. Прежде чем я начал вносить изменения в сценарий, я попытался написать несколько тестовых сценариев, чтобы иметь хорошую базу регрессии. Для этого я собирался использовать метод, описанный на этой странице .

Я начал с написания тестов для одной подпрограммы. Я поместил эту строку в верхней части сценария, который я тестирую:

return 1 if ( caller() );

Таким образом, в моем тестовом скрипте я могу

require 'script_to_test.pl';

и не будет выполнен весь сценарий.

Первая подпрограмма, которую я собирался протестировать, широко использует глобальные переменные, которые устанавливаются в скрипте. Я думал попытаться переопределить эти переменные в моем тестовом скрипте, что-то вроде этого:

require_ok('script_to_test.pl');
$var_from_other_script = 'Override Value';
ok( sub_from_other_script() );

К сожалению (для меня), скрипт, который я тестирую, имеет массивный блок "my" вверху, где он объявляет все переменные, используемые в скрипте. Это мешает моему тестовому скрипту видеть / изменять переменные в скрипте, с которым я запускаю тесты.

Я играл с Exporter, Test :: Mock ... и некоторыми другими модулями, но похоже, что если я хочу изменить любые переменные, мне нужно каким-то образом изменить другой скрипт .

Моя цель - не изменять другой сценарий, а запустить несколько хороших тестов, поэтому, когда я начну менять другой сценарий, я могу быть уверен, что ничего не сломал. Сценарий около 10000 строк (3000 из них в основном блоке), поэтому я боюсь, что если я начну что-то менять, я затрону другие части кода, поэтому хороший набор тестов поможет.

Возможно ли это? Может ли вызывающий скрипт изменять переменные в другом скрипте, объявленном с помощью "my"?


И, пожалуйста, не прыгайте с ответами типа «Просто переписать сценарий с нуля» и т. Д. Это может быть лучшим решением, но оно не отвечает на мой вопрос, и мы не у него нет времени / ресурсов для переписывания.

Ответы [ 2 ]

5 голосов
/ 13 апреля 2010

Если вы хотите сохранить переменные лексическими (если с ними построены замыкания), вы можете использовать модуль PadWalker , чтобы разбираться.

включите что-то подобное в старый код:

package somepackage;

use PadWalker qw/peek_my/;

my $x = 1;
# big my block declaration...

our $lexpad = peek_my 0;

тогда в вашем тестовом коде:

${ $somepackage::lexpad->{'$x'} } = 2;
3 голосов
/ 13 апреля 2010

Если у скрипта есть объявление package (или вы можете добавить его без изменения поведения скрипта), то вы можете изменить объявление my на объявление our и изменить переменные, используя полностью уточненное имя переменной.

Старый скрипт:

my($a,@b,$c,%d);

Изменить на:

package Some::Package;
our($a,@b,$c,%d);

А в вашем тестовом скрипте:

sub_from_other_script();
$Some::Package::c = 42;
$Some::Package::d{$key} = $value;
sub_from_other_script();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...