Testen mal anders: phpt

phpt ist ein schmuckes, kleines Testframework, welches u.a. auch zur PHP Quality Assurance verwendet wird, um damit PHP-eigene Funktionen in PHP zu testen. Wir beginnen mit einem Beispiel:

--TEST--
My first cool test!
--FILE--
<?php 
class Foobar
{
	public function __construct()
	{
		for ($i = 0; $i < 6; $i++)
		{
			if ($i % 2 != 0)
				echo $i;
		}
	}
}

new Foobar();
?>
--EXPECT--
135

Und das Beste: Mit PEAR kommt der Spaß gleich mit:

Pear run-tests

Pear run-tests

Das ists aber lang noch nicht gewesen. Man führe sich folgenden Test zu Gemüte:

--TEST--
Second example: errortesting
--FILE--
<?php 
$foo = array(1, 3) * array(2, 6);
?>
--EXPECTF--
Fatal error: Unsupported operand types in %s.php on line %d

Wir testen hier etwas, was schiefgehen soll. Dabei kommt gleich noch EXPECTF (für formatierte Ausgaben im Stil von scanf) zum Einsatz.

Aber es wird noch cooler. Es gibt sehr sinnvolle –BLÖCKE–, mit denen dann auch sowas realisiert werdern kann:

--TEST--
Test filter_input() with GET and POST data.
--DESCRIPTION--
This test covers both valid and invalid usages of
filter_input() with INPUT_GET and INPUT_POST data
and several differnt filter sanitizers.
--CREDIT--
Felipe Pena <felipe@php.net>
--INI--
precision=14
--SKIPIF--
<?php if (!extension_loaded("filter")) die("Skipped: filter extension required."); ?>
--GET--
a=<b>test</b>&b=http://example.com
--POST--
c=http://example.com
--FILE--
<?php
var_dump(filter_input(INPUT_GET, "a", FILTER_SANITIZE_STRIPPED));
var_dump(filter_input(INPUT_GET, "b", FILTER_SANITIZE_URL));
var_dump(filter_input(INPUT_POST, "c", FILTER_SANITIZE_URL));
?>
--EXPECTF--
string(4) "test"
string(18) "http://example.com"
string(18) "http://example.com"

Hier schön zu sehen: Per –INI– werden Werte der php.ini für diesen Test überschrieben. Per –SKIPIF– können wir den Test überspringen, wenn die notwendigen Voraussetzungen nicht erfüllt sind. Ein Test der PHP-Filter-Funktionen wäre ohne eine geladene Filter-Extension schließlich witzlos. Anderes schönes Beispiel dazu:

--SKIPIF--
<?php 
if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platforms only");
?>

Mit –GET– und –POST– lassen sich schließlich auch Requests simulieren. In Anlehnung an die tearDown()-Methode von PHPUnit gibt es zum Aufräumen noch:

--CLEAN--
<?php
      unlink($temp_filename);
?>

Weiterhin lassen sich auch Request-Header setzen und sogar ein Autoloader für vollwertige Unit-Tests einbetten:

--TEST--
Test filter_input() with GET and POST data.
--FILE--
<?php
function __autoload($classname)
{
	require $classname.".php";
}
var_dump(SomeClass::add(2, 3));
?>
--EXPECT--
int(5)

Wer nach diesem kurzen Anriss richtig einsteigen will, findet hier die Basics, eine Übersicht über alle Möglichkeiten und auf den QA-Seiten den ein oder anderen interessanten Einblick in das PHP-interne Testgebahren.

Erwähnenswert ist zum Abschluss noch das tolle Fehlerverhalten. Wir legen bewusst einen falschen Test an, um das mal zu demonstrieren:

--TEST--
Test that is intentionally incorrect
--FILE--
<?php
var_dump(cos(90 * 2*M_PI));
?>
--EXPECT--
int(0) # erwischt? cos(90) = 1 ;)

Der Test schlägt also fehl. Freundlicherweise wird zu unserer Testdatei ins Verzeichnis noch eine [testname].log angelegt, die wie folgt aussieht:

---- EXPECTED OUTPUT
int(0) # erwischt? cos(90) = 1 ;)
---- ACTUAL OUTPUT
int(1)
---- FAILED

Da lässt sich also echt was mit anfangen. Korrigiert man den Test, werden die nun überflüssigen Fehler-Logdateien selbstständig wieder bereinigt, sodass kein Dateimüll entsteht. phptest ist meiner Meinung nach völlig zu Unrecht so unbekannt.

Weitere Posts:

Dieser Beitrag wurde unter php, Software Engineering, webdev veröffentlicht. Setze ein Lesezeichen auf den Permalink.

3 Antworten auf Testen mal anders: phpt

  1. Rabbl sagt:

    Bin auf der Suche nach dem Flattr-Button auf Deiner Seite….
    Schöne Grüße aus Dresden

  2. Fatiza sagt:

    Hello, how can we download this framework, i’m looking for best way to unit test methods calling filter_input ? helllllpp

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.