Andreas Korthaus: Tests / Qualitätssicherung - aber wie?

Beitrag lesen

Hallo!

Allgemein lässt sich wenig formulieren. Ich schreibe zu jedem Modul(ich verwende fast nur Perl) sofort einen Test in einem Testverzeichnis (t/), den ich per :vsplit immer rechts neben dem eigentlichen Code habe und über F9 schlagartig durchlaufen kann. Dadurch kann ich auch tesgetriebene Entwicklung (http://www.wikiservice.at/dse/wiki.cgi?TestgetriebeneEntwicklung) betreiben.

das hört sich ja mal nett an, aber wie soll das funktionieren? Ich kann mir nicht wirklich vorstellen wie ich ein Modul testen kann. Meinst Du Du schreibst ein Testscript welches das originale Script nachbildet und das Modul einbindet und die Schnittstellen mit allen möglichen Daten füttert und bei Fehlerhafter Rückgabe irgendwas ausgibt? Das wäre ja eine tierische Arbeit!

D.h. von vorn herein sollte alles, was du schreibst, modularisiert sein, in Bibliotheken und Klassen.

Was genau wird eigentlich als Bibliothek bezeichnet - wenn ich mal fragen darf? Ich verwende das immer für Code denn ich wiederverwenden kann, z.B. Klassen wie DB-Abstraktion, Authentifizierung... das ist dann immer eine Klasse in einer Datei die ich dann bei bedarf einbinde - ist das ein Bibliothek?

Ok, eine Klasse lässt sich gut testen. Sagen wir mal ich habe verschiedene Schnittstellen, z.B. für eine Klasse "user". Darin speichere ich alle mögichen Inforamtionen über den aktuellen Benutzer, und stelle Schnittstellen bereit den Benutzernamen zu ändern, Passwort zu ändern, ein bestimmtes Recht zu überprüfen...

Mal ein Beispiel für eine Methode,

function set_username($new) {
    if($db->query('UPDATE...SET username = $new')) {
        return TRUE;
    }
    else {
        return FALSE;
    }
}

Den Benutzernamen kann ich dann mit

$user->set_username('willy');

ändern. Und wie teste ich das jetzt? Was teste ich alles? kann mir das nicht vorstellen. Soll ich testen was ich dem Methode alles für Parameter übergeben kann (Länge 0-100, Array...) nur um zu sehen was passiert...? Das wäre ja irgendwie Quatsch. Eigentlich müsste ich nur
prüfe was vom user kommen könnte, aber das wiederum fange ich ja vorher ab, also was soll ich hier noch groß prüfen? Stehe da irgendwie auf dem Schlauch.

Solche lassen sich dann auch einzeln auf Herz und Nieren testen. Afaik gibt es die Möglichkeit PHP auch auf der Kommandozeile zu interpretieren, also kannst du es im Grunde auch gleich dort beim Entwickeln testen.

sicher, das geht. Aber wie soll ich mir das vorstellen? Ich habe also obige Klasse - was bringt es mir jetzt dieses Script in der Kommandozeile auszuführen? Was soll das Script in der Kommandozeile alles machen?

Ansonsten schreib' halt ein einfaches Testprogramm, das auf dem Webserver die jeweilige Komponente prüft. Ob es so tolle Testframeworks wie Test::More für Perl auch für PHP gibt, weiß ich nicht.

Wäre mir nicht bekannt. Ich habe irgendwi eien Problem mir vorzustellen was man an so einer Komponente so alles prüfen sollte. ich könnte in PHP glaube ich ermitteln was eine Klasse für Methoden und Eigenschaften hat(http://de3.php.net/manual/de/ref.objaggregation.php - wobei, geht erst ab PHP5). Problem ist auch, dass viele Klassen nicht fr sich alleien laufen können, die User-Klasse bekommt z.B. den REMOTE_USER namen übergeben, und macht dann als erstes mal einige DB-Abfragen(mit dem DB-Abstraktions-Modul) um mehr über den aktuellen User zu erfahren und schreibt das in die entsporechenden Eigenschaften. Wäre das also ein unsauberes Design? Aber irgendwo _muss_ ich ja an die User-Daten aus der DB kommen. Aber im prinzip könnte ich das Scipt ja in seiner originalen Umgebung testen, und nur den REMOTE_USER übergeben, dann sollte es ja laufen, nur bleibt die Frage - was genau soll ich dann automatisiert testen?

Deswegen lohnt es sich spätestens beim Testen, _korrekt_ modularisiert zu haben, denn wenn alles unübersichtlich ineinander verzahnt ist, lassen sich keine wirkichen Test schreiben, sondern nur Stichproben.

Ja, ich gebe zu dass ich das nicht 100%ig durchgezogen habe, aber ich finde, dasss wenn ich eine Funktionalität nur an einer Stelle brauche, lohnt es sich nicht wirklich die in eine Modul/Klasse zu packen - Trade-Off Performance vs. Modularität. Heißt dass dann aber auch - schlechter zu testenden Code?

Ich hoffe also, deine 200 PHP-Dateien lassen sich alle isoliert testen, d.h. du schreibst 200 Tests, die jeweils nur die korrekte Funktionalität einer Datei prüfen.

Wenn ich recht überlege sind es keine 200 PHP-Dateien, das waren alle Dateien, mit Templates, JS und CSS, aber es sind sicher über 100.

Wenn die Dateien so beschaffen sind, dass sie einen komplizierten Kontext brauchen, hast du ein Problem, dann musst du diesen Kontext nämlich im test simulieren.

Kann ich nicht den Kontext der original-Umgebung verwenden, oder würde das das Testergebnis evtl. verfälschen?

Zum konkreten Testen in PHP weiß ich nichts. In Perl gibt es eine Konvention über die Ausgabe von Testprogrammen. Das sieht etwa so aus (schreibe ich gerade aktuell):

1..43
ok 1 - use Pie::Object;
ok 2 - Pie::Parent->create
ok 3 - The object isa Pie::Parent
ok 4 - The object isa Pie::Object
ok 5 - Pie::Object->new(parent)
ok 6 - The object isa Pie::Object
[...]
ok 38 - o1->push_stack
ok 39 - o2->push_stack
ok 40 - o1->run_stack walks up
ok 41 - ... in correct order (0 1 2 3 4 5)vs(0-5)
ok 42 - o2->run_stack walks up twice
ok 43 - ... in correct order (0 1 2 3 4 5 6 7 8 9 10 11 12)vs(0-12)

Diese Ausgabe wird dann wiederum von Programmen ausgewertet, die nur noch die Testinformationen von gescheiterten Tests ausgeben. So kann exakt festgestellt werden, ob und welche Test scheitern.

Das wäre wirklich gut...

Das Testpogramm selbst sieht so aus:

#!/usr/bin/perl
use strict;
use warnings;

use Test::More qw/tests 43/;
use Test::Exception;

our $CLASS;

BEGIN {
        $CLASS = 'Pie::Object';
        use_ok($CLASS)
                or die "use $CLASS failed";
}

ok(
        my $parent = Pie::Parent->create(),
        'Pie::Parent->create' );
isa_ok( $parent , 'Pie::Parent' );
isa_ok( $parent , 'Pie::Object' );

[...]

Das waren die ersten 4 von 43.

Es dürfte kaum sehr kompliziert sein, solche Programme auch in PHP zu schreiben.

Sicher nicht, nur verstehe ich das Programm nicht wirklich. Vermutlich daher weil ich das Test-Modul nicht kenne, aber was genau macht das?

BEGIN {

was ist das?

Wo bindest Du denn eine andere Datei an die Du in Pie::Object benutzt?

Also ich vermute, als erstes muss ich die zu testende Date einbinden, dann die Klasse initialisieren, und dann für jede Methode verschiedene Tests überlegen, nur welche?

isa_ok( $parent , 'Pie::Parent' );

Was genau wird denn jetzt getestet? Ich kann mir das irgendwie nicht vorstellen. Prüfst Du nicht einzelnd alle Methoden?

Was ist

ok(

?

Es kommt jetzt also darauf an, wie sauber dein Design ist.

Tja....

Vielen Dank für Deine Anregungen, auch wenn ich da noch nicht wirkich durchblicke ;-)

Viele Grüße
Andreas