18 Stimmen

Ist es möglich, ein Perl-Skript zu verwenden oder zu benötigen, ohne seine Anweisungen auszuführen?

Ich muss Unit-Tests zu einigen alten Skripten hinzufügen, die Skripte sind alle grundsätzlich in der folgenden Form:

#!/usr/bin/perl

# Main code
foo();
bar();

# subs
sub foo {

}
sub bar {

}

Wenn ich versuche, diesen Code in einem Unit-Test zu "erfordern", wird der Hauptteil des Codes ausgeführt, während ich in der Lage sein möchte, nur "foo" isoliert zu testen.

Gibt es eine Möglichkeit, dies zu tun, ohne foo,bar in eine separate .pm-Datei zu verschieben?

18voto

ysth Punkte 91645

Angenommen, Sie haben keine Sicherheitsbedenken, verpacken Sie es in eine sub { ... } und werten Sie es aus:

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

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

(wobei darauf zu achten ist, dass das eval nicht in den Geltungsbereich von Lexika fällt, die durch das Skript geschlossen werden würden).

17voto

Ovid Punkte 11296

Ein weiterer gängiger Trick für Unit-Testing-Skripte besteht darin, den Hauptteil des Codes in einen "Caller"-Block zu packen:

#!/usr/bin/perl

use strict;
use warnings;

unless (caller) {
    # startup code
}

sub foo { ... }

Wenn es von der Kommandozeile, von cron, einem Bash-Skript usw. ausgeführt wird, läuft es normal. Wenn Sie es jedoch aus einem anderen Perl-Programm laden, wird der "unless (caller) {...}"-Code nicht ausgeführt. Deklarieren Sie dann in Ihrem Testprogramm einen Namespace (da das Skript wahrscheinlich Code im Paket main:: ausführt) und "do" das Skript.

#!/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' ist effizienter als eval und für diesen Zweck ziemlich sauber.

Ein weiterer Trick zum Testen von Skripten ist die Verwendung von Erwarten Sie . Das ist zwar sauberer, aber auch schwieriger zu handhaben, und Sie können nichts im Skript überschreiben, wenn Sie etwas nachbilden müssen.

10voto

Schwern Punkte 138322

Ahh, die alte Frage "wie teste ich ein Programm". Der einfachste Trick ist, dies in Ihr Programm einzubauen, bevor es anfängt, etwas zu tun:

return 1 unless $0 eq __FILE__;

__FILE__ ist die aktuelle Quelldatei. $0 ist der Name des Programms, das ausgeführt wird. Wenn sie gleich sind, wird Ihr Code als Programm ausgeführt. Wenn sie unterschiedlich sind, wird er als Bibliothek geladen.

Das reicht aus, um mit den Unit-Tests der Unterprogramme in Ihrem Programm zu beginnen.

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

Der nächste Schritt besteht darin, den gesamten Code außerhalb einer Unterroutine in main dann können Sie dies tun:

main() if $0 eq __FILE__;

und jetzt können Sie main() genau wie jedes andere Unterprogramm testen.

Sobald das erledigt ist, können Sie darüber nachdenken, die Unterprogramme des Programms in ihre eigenen Bibliotheken auszulagern.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X