Testen von Konsole-Applikationen
Im vorangegangenen Abschnitt wurden die Module beschrieben, die hauptsächlich bei Tests von Modulen eingesetzt werden. Die Test-Strategie sollte jedoch weitergeführt werden und auch auf Applikationen angewendet werden. Dieser Abschnitt und die beiden folgenden Abschnitte zeigen, wie man auch Skripte und andere Applikationen testen kann.
Test::Cmd
Test::Cmd ist ein kleines Modul, mit dem man Konsolen-Applikationen testen kann. Es ist etwas gewöhnungsbedürftig, ist jedoch geeignet, um Programme zu testen. Das Modul
Ein einfaches Skript, das getestet werden soll:
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5
6 print "Geben Sie eine Zahl ein: ";
7 chomp(my $zahl = <STDIN>);
8
9 print '>>',$zahl,"<<\n";
Es gibt einfach die Zahl, die eingegeben wurde, umrahmt von ``>>'' und ``<<'' aus.
Getestet wird es mit dem folgenden Skript:
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5 use Test::Cmd;
6 use Test::More tests => 12;
7
8 my $test = Test::Cmd->new(prog => 'cmd_bsp.pl',
9 workdir => './testing') or die $!;
10 $test->interpreter('perl');
11
12 for(1..12){
13 my $nr = rand 2998;
14 $test->run(stdin => $nr);
15 my $result = $test->stdout();
16 like($result,qr/>>$nr<<$/);
17 }
Ich überprüfe hier, ob das Programm mir auch tatsächlich alle möglichen Eingaben wieder ausgibt. Test::Cmd bietet verschiedene Einstellmöglichkeiten zum Testen. Man kann dem zu testenden Programm auch Kommandozeilenargumente übergeben und so verschiedene Einstellungen testen.
Der Test zeigt, dass das Programm alles richtig macht:
~/entwicklung 28> perl test_cmd.pl
1..12
ok 1
ok 2
ok 3
ok 4
ok 5
ok 6
ok 7
ok 8
ok 9
ok 10
ok 11
ok 12
Das Modul legt ein temporäres Verzeichnis an, in dem verschiedene Dateien zwischengespeichert werden. Dort werden für die verschiedenen Durchläufe zum Beispiel die Ausgaben des getesteten Programms und die Ausgaben auf STDERR in Dateien gespeichert, damit diese Informationen später wieder abgerufen werden können.
So sieht es beispielhaft in dem temporären Verzeichnis aus:
~/entwicklung 4> ll testing
total 2
-rw-rw-r-- 1 reneeb bioinf 0 Oct 11 13:32 stderr.1
-rw-rw-r-- 1 reneeb bioinf 0 Oct 11 13:32 stderr.2
-rw-rw-r-- 1 reneeb bioinf 136 Oct 11 13:32 stdout.1
-rw-rw-r-- 1 reneeb bioinf 0 Oct 11 13:32 stdout.2
Bei Beendigung des Testskripts räumt das Modul wieder auf.
Das Modul geht relativ strikt vorwärts. Zum Überprüfen, ob das Skript durchgelaufen ist, oder ob es abgebrochen wurde, stehen die Funktionen pass beziehungsweise fail zur Verfügung. Das Modul liefert leider keine Funktionen, um die Ausgaben des getesteten Programms zu überprüfen. Das muss man dann mit Test::More und dessen Funktionen machen (wie im Beispielskript).
Test::Expect
Ein weiteres Modul zum Testen von Konsole-Applikationen ist Test::Expect. Dafür ist es jedoch notwendig, dass das zu testende Programm einen
Prompt hat. Dadurch erkennt das Modul, wann es Eingaben senden kann. Zusätzlich muss das Programm durch einen Befehl zu Beenden sein, da sonst das Testskript hängt wenn noch Eingaben fehlen. Aus diesem Grund wurde obiges Beispielskript erweitert und sieht somit folgendermaßen aus:
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5
6 for(0..2){
7 print "Geben Sie eine Zahl ein: ";
8 chomp(my $zahl = <STDIN>);
9 if($zahl eq 'quit'){
10 exit;
11 }
12 print '>>',$zahl,"<<\n";
13 sleep 2;
14 }
Der Test mit Test::Expect sieht dann so aus:
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5 use Test::Expect;
6 use Test::More tests => 3;
7
8 expect_run(
9 command => 'perl cmd_bsp.pl',
10 prompt => 'Geben Sie eine Zahl ein: ',
11 quit => 'quit',
12 );
13
14 expect(3,'>>3<<');
Ohne die eingebaute Abfrage nach quit würde das Testskript stehen bleiben und darauf warten, dass es etwas an das zu testende Skript senden kann. Die Dokumentation zu Test::Expect ist leider sehr rudimentär. So ist an keiner Stelle vermerkt, dass man bei Test::More zwei Tests pro expect-Aufruf rechnen muss und dass expect_run auch einen Test beinhaltet. Sieht man das Testskript, so erwartet man erstmal nur
einen Test: bei dem expect-Aufruf.
Dann sieht die Ausgabe aber wie folgt aus:
~/entwicklung 31> perl test_expect.pl
1..1
ok 1 - expect_run
ok 2
ok 3
# Looks like you planned 1 test but ran 2 extra.
An der Ausgabe kann man dann erkennen, dass expect_run einen Test beinhaltet. Ein Blick in den Quellcode des Moduls offenbart dann auch, wo der zweite zusätzliche Test herkommt: expect ruft intern zwei Funktionen auf, die jeweils einen Test machen.
Zwischenfazit ``Konsole-Applikationen''
Mit beiden Modulen lassen sich Konsolen-Anwendungen testen. Allerdings ist die Verwendung der Module nicht ganz so intuitiv wie bei anderen Test-Modulen. Das sollte aber keinen abhalten, solche Anwendungen zu testen.
Die Dokumentation von beiden Modulen ist nicht besonders gut.
Test::Cmd hat weniger Abhängigkeiten und lässt sich leichter benutzen.
--
ReneeBaecker - 15 Apr 2009