Существует сценарий 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() );
К сожалению (для меня), сценарий, который я тестирую, имеет крупное "мой" блок наверху, где он объявляет все переменные, используемые в сценарии. Это препятствует тому, чтобы мой сценарий тестирования видел/изменял переменные в сценарии, против которого я запускаю тесты.
Я играл со Средством экспорта, Тестом:: Насмешка... и некоторые другие модули, но похоже, хочу ли я смочь заменить какие-либо переменные, я оказываюсь перед необходимостью изменять другой сценарий некоторым способом.
Моя цель не состоит в том, чтобы изменить другой сценарий, но получить некоторые хорошие тесты, работающие поэтому, когда я действительно начинаю изменять другой сценарий, я могу удостовериться, что ничего не повредил. Сценарий является приблизительно 10 000 строк (3,000 из них в основном блоке), таким образом, я боюсь, что, если бы я начинаю изменять вещи, я буду влиять на другие части кода, так наличие хорошего набора тестов помогло бы.
Действительно ли это возможно? Сценарий выполнения вызова может изменить переменные в другом сценарии, объявленном с "моим"?
И не вскакивайте с ответами как, "Просто перепишите сценарий с нуля", и т.д. Это может быть лучшим решением, но оно не отвечает на мой вопрос, и у нас нет времени/ресурсов для переписывания.
Если вы хотите, чтобы переменные оставались лексическими (если на их основе построены замыкания), вы можете использовать модуль PadWalker , чтобы искать .
включите что-то вроде этого в старый код:
package somepackage;
use PadWalker qw/peek_my/;
my $x = 1;
# big my block declaration...
our $lexpad = peek_my 0;
затем в свой тестовый код:
${ $somepackage::lexpad->{'$x'} } = 2;
Если в сценарии есть объявление package
(или если вы можете добавить его без изменения поведения сценария), то вы можете измените объявление my
на объявление наше
и измените переменные, используя полное имя переменной.
Старый скрипт:
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();