2010-04-13 6 views
5

Es gibt ein Perl-Skript in unserer Umgebung, das ich jetzt pflegen muss. Es ist voll von schlechten Praktiken, einschließlich der Verwendung (und Wiederverwendung) globaler Variablen im gesamten Skript. Bevor ich mit Änderungen am Skript begann, wollte ich versuchen, einige Testskripte zu schreiben, damit ich eine gute Regressionsbasis haben kann. Um dies zu tun, würde ich eine Methode verwenden, die auf dieser page beschrieben wird.Variable überschreiben, während ein eigenständiges Perl-Skript getestet wird

Ich begann mit dem Schreiben von Tests für ein einzelnes Unterprogramm. Ich habe diese Linie etwas in der Nähe der Spitze des Skripts Ich teste:

return 1 if (caller()); 

auf diese Weise in meinem Testskript kann ich

require 'script_to_test.pl'; 

und es wird nicht das gesamte Skript auszuführen.

Die erste Subroutine, die ich testen wollte, verwendet viele globale Variablen, die im gesamten Skript festgelegt sind. Mein Gedanke war, zu versuchen, diese Variablen in meinem Testskript außer Kraft zu setzen, so etwas wie diese:

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

Leider (für mich), das Skript Ich bin Tests einen massiven „meinen“ Block an der Spitze hat, wo es erklärt alle im Skript verwendeten Variablen. Dies verhindert, dass mein Testskript die Variablen in dem Skript, für das ich Tests durchführe, sieht/ändert.

Ich habe mit Exporter, Test :: Mock ... und einigen anderen Modulen gespielt, aber es sieht so aus, als ob ich in der Lage sein würde, alle Variablen zu ändern, die ich in anderen ändern muss Mode.

Mein Ziel ist es, das andere Skript nicht zu ändern, aber einige gute Tests laufen zu lassen, also wenn ich anfange, das andere Skript zu ändern, kann ich sicherstellen, dass ich nichts kaputt gemacht habe. Das Skript ist ungefähr 10.000 Zeilen (3.000 davon im Hauptblock), daher befürchte ich, dass wenn ich anfange Dinge zu ändern, ich andere Teile des Codes beeinflussen werde, also würde eine gute Testsuite helfen.

Ist das möglich? Kann ein aufrufendes Skript Variablen in einem anderen mit "my" deklarierten Skript ändern?


Und bitte springen Sie nicht mit Antworten wie: „Nur neu schreiben das Skript von Grund auf neu“ in, etc. Das ist die beste Lösung sein kann, aber es ist nicht meine Frage zu beantworten, und wir haben nicht die Zeit/Ressourcen für ein Umschreiben.

Antwort

5

Wenn Sie die Variablen lexikalischer behalten wollen (wenn es Verschlüsse gebaut mit ihnen) können Sie das Modul PadWalker verwenden, um herumzustochern.

sind so etwas wie dies in dem alten Code:

package somepackage; 

use PadWalker qw/peek_my/; 

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

our $lexpad = peek_my 0; 

dann in Ihrem Testcode:

${ $somepackage::lexpad->{'$x'} } = 2; 
+0

Dies funktioniert perfekt, mit minimalen Änderungen am ursprünglichen Skript. – BrianH

2

Wenn das Skript eine package Erklärung hat (oder wenn Sie ein ohne Änderung des Verhaltens des Skripts hinzufügen können), dann können Sie die my Erklärung zu einer our Erklärung ändern, und Variablen ändern Sie den vollständig qualifizierten Variablennamen verwenden.

Old Skript:

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

Wechseln zu:

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

Und in Ihrem Testskript:

sub_from_other_script(); 
$Some::Package::c = 42; 
$Some::Package::d{$key} = $value; 
sub_from_other_script(); 
+2

Wenn das alte Skript ein eigenständiges Skript ist, ist es immer sicher einen Paketnamen hinzufügen und "unser" verwenden, um die Variablen zu erfassen. – mob

+0

Das Skript hat keine Paketdeklaration. Ich könnte versuchen, eine obwohl ... – BrianH

+0

Ohne die Paket-Deklaration (aber immer noch ändern "meine" -> "unsere"), vermute ich, dass Sie einfach $ $ main :: var_from_other_script aus dem Testskript manipulieren. – mob

Verwandte Themen