Tests unitaires

Soyez le premier à donner votre avis sur cette source.

Vue 4 341 fois - Téléchargée 216 fois

Description

Bonjour à tous,

Je présente aujourd'hui une version plus aboutie de ce code en ligne depuis peu. Il se compose de trois classes une interfaces et un index.php

Pourquoi ne pas utiliser PHPUnit ou SimpleTest ? Par goût de la simplicité.

La classe TestManager connait les deux autres classes.
Les classes de tests (que vous devez écrire !) héritant de TestUnitaire sont chargées via la méthode addClasse et lancées ensuite dans la méthode launch.
L'affichage comprend aujourd'hui une interface et une classe HtmlOutput.

Le tout étant soumis à vos appréciations. J'ai développé des choses en vitesse, pour savoir si je ne faisais pas fausse route.

A vous de jouer !

PS : La source ne présente que la classe TestManager. Ca vous donnera l'idée générale.

Source / Exemple :


<?php
final class TestManager {
	const METHOD_PREFIX = 'test_';
	const METHOD_INDENT = "\t";
	private $tests = array();
	/**

  • Pile de logs
  • /
private $logs = array(); /**
  • public function __construct()
  • /
public function __construct(){ assert_options(ASSERT_ACTIVE,1); assert_options(ASSERT_WARNING,0); assert_options(ASSERT_BAIL,0); assert_options(ASSERT_QUIET_EVAL,1); assert_options(ASSERT_CALLBACK,array($this,'hasFail')); } public function hasFail($file,$line,$code){ // Au dernier log (le [0] du tableau), j'ajoute le contexte de l'échec. $this->logs[0]['fail'] = TRUE; //array('file' => $file, 'line' => $line, 'code' => $code); } public function log($m,$args){ $log = array( 'method' => $m, 'args' => $args, 'fail' => FALSE, ); // travail anté-historique (du plus récent au plus ancien) // comme ça, les derniers tests (ceux qui nous préoccupent) occupent le haut du tableau array_unshift($this->logs,$log); } /**
  • vide les logs un par un en les affichant
  • /
public function drainLogs(TestOutput $obj){ while ($log = array_shift($this->logs)) { $obj->show($log['method'],$log['args'],$log['fail']); } } function addClasse($name){ $this->tests[] = $name; } function launch($out_class){ // instancier la sortie $out = new $out_class(); // travail anté-historique while ($current = array_shift($this->tests)) { if (is_subclass_of($current,'TestUnitaire')) { $obj = new $current($this); $l = strlen(self::METHOD_PREFIX); // annoncer la classe $out->classBegin($current); foreach (get_class_methods($obj) as $m) { if (substr($m, 0, $l) == self::METHOD_PREFIX) { // annoncer la methode $out->methodBegin($m); // ... je les appelle dans un environnement clean $obj->setUp(); $obj->$m(); $obj->tearDown(); // Pour ne pas surcharger la mémoire, à chaque fin de méthode, je dépile la pile des logs. $this->drainLogs($out); $out->methodEnd($m); }} $out->classEnd($current); } } } function generateClassTest($name, $output = 'php://output'){ $hdle = fopen($output, 'w'); fwrite($hdle, '<?php'. PHP_EOL . 'class ' . $name . 'Test extends TestUnitaire {' . PHP_EOL); // self::write_method('setUp',$hdle); self::write_method('tearDown',$hdle); foreach(get_class_methods($name) as $m) { self::write_method($m,$hdle); } fwrite($hdle, '}' . PHP_EOL); fclose($hdle); } function write_method($method_name, $handle){ fwrite($handle, self::METHOD_INDENT . 'function ' . $method_name . '(){'. PHP_EOL . self::METHOD_INDENT . '}' . PHP_EOL); } }

Conclusion :


J'attends vos regards externes pour faire avancer ce code.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
27
Date d'inscription
lundi 12 avril 2010
Statut
Membre
Dernière intervention
15 octobre 2011

Suite aux sollicitations publiques et privees, je vais faire mon possible pour ameliorer le packaging de mon code.
Sortie possible dans deux semaines (je n ai pas d ordi, utilise un qwerty pourri dans un web bar, etc).

Votre tres oblige ;-)
Messages postés
3
Date d'inscription
dimanche 3 avril 2005
Statut
Membre
Dernière intervention
20 octobre 2011

Bonjour,

Dans la première réponse que tu m'avais faite, j'avais bien vu que tu faisais allusion à cette fonction launch mais je pensais que tu l'avais intégrée à ton fichier de livraison et je l'ai donc retéléchargé à l'aide du lien 'Télécharger le zip'...
Comment fait-on pour télécharger ta dernière version ?

Donc je viens de la rajouter (par copier coller de la fonction que tu as donnée dans ta réponse d'hier soir) juste après la fonction __destruct() dans le fichier test/testUnitaires.php et ça ne change pas grand chose.
L'autre souci, c'est que si je change un des tests pour qu'il soit fau par exemple :
$mon_adr->longueur_dom('toto@truc.fr') == 5
au lieu de :
$mon_adr->longueur_dom('toto@truc.fr') == 7

La seule différence (qui ne saute pas aux yeux) c'est la dernière ligne :
48 test(s) lancé(s). OK
au lieu de :
49 test(s) lancé(s). OK

J'ai encore dû merder quelque part...

En tous cas, merci de partager ce travail :)
Jean-Paul
Messages postés
27
Date d'inscription
lundi 12 avril 2010
Statut
Membre
Dernière intervention
15 octobre 2011

Oui, je peux te le dire ;-)

Vérifie ta classe mère "TestUnitaire",car si j'ai bien compris ton erreur, la méthode launch() ne doit pas figurer. Or, il faut, dans l'état actuel de ton code, qu'elle fasse quelque chose comme :

final public function launch(){
foreach (get_class_methods($this) as $m) {
// ... qu'il faut appeler par CONVENTION
if (substr($m, 0, 5) == 'test_') {
// ... je les appelle dans un environnement clean
$this->setUp();
$this->$m();
$this->tearDown();
}
}
}

Dans le cas de ton erreur, __call est appelé récursivement... Je prends bonne note de ce bug et vais le corriger avec ce test dans la fonction __call
if (method_exists($this,$method)){
call_user_func_array(array($this, $method), $args);
}

Merci pour ta remontée d'erreur ! Tiens-moi au courant pour ton code.

PS : une nouvelle mouture va voir le jour. Elle sera (rétro-)compatible avec tes classes ;-)
Messages postés
3
Date d'inscription
dimanche 3 avril 2005
Statut
Membre
Dernière intervention
20 octobre 2011

Bonjour ou plutôt bonsoir,

Je suis désolé mais je dois passer à côté de quelque chose : même avec tes explications, je n'arrive pas à comprendre.
Faut dire que je n'ai pas trop de temps et que je n'ai pas investi en regarder ton code...
Je me suis fait un répertoire exemple avec la classe à tester suivante (fichier=class_verifadr.php)
----------------- début code -----------------
<?php
class verifadr
{
function longueur_nom($adr)
{
return strlen(substr($adr,0,strpos($adr, '@')));
}
function longueur_dom($adr)
{
return strlen(substr($adr,strpos($adr, '@')+1));
}
}
?>
----------------- fin code -----------------
j'ai téléchargé le zip et j'ai copié le dossier test dans mon dossier exemple.

Maintenant, il faut que je crée mon fichier de tests (fichier=test_verifadr.php) et c'est là que je me demande ce qu'il faut faire...
J'imagine qu'il faut que je charge ma classe et la classe de tests unitaires donc je suis arrivé à un truc comme :
----------------- début code -----------------
<?php
require('test/testUnitaire.php');
require('class_verifadr.php');

class verifadrTest extends TestUnitaire
{

function test_alpha()
{
$mon_adr=new verifadr();
if ($mon_adr->longueur_nom('toto@truc.fr') == 4)
{
return true;
}
else
{
return false;
}
}
function test_beta()
{
$mon_adr=new verifadr();
if ($mon_adr->longueur_dom('toto@truc.fr') == 7)
{
return true;
}
else
{
return false;
}
}
}

$obj = new verifadrTest();
$obj->launch();
?>
----------------- fin code -----------------
quand je charge le fichier test_verifadr.php dans mon navigateur j'ai :
1) un warning :
Warning: Cannot modify header information
2) ça affiche :
Début des tests
3) ensuite j'ai une erreur :
Fatal error: Maximum function nesting level of '100' reached, aborting! in /home/jpaul/workspace/tests/testUnitaire/exemple/test/testUnitaire.php on line 47
4) un tableau de 99 lignes auquel je ne comprends pas grand chose voici la ligne de titre et la première et la dernière lignes :
# Time Memory Function Location
1 0.0004 337560 {main}( ) ../test_verifadr.php:0
99 0.0039 443628 TestUnitaire->__call( ) ../testUnitaire.php:0
5) une ligne qui semble être le résultat :
49 test(s) lancé(s). OK

Peux-tu me dire ce que j'ai fait de travers ?

Cordialement,
Jean-Paul OLIVIER
Messages postés
27
Date d'inscription
lundi 12 avril 2010
Statut
Membre
Dernière intervention
15 octobre 2011

Merci Akh, c'est grâce à toi que j'améliore ce source.

En fin de semaine, je déménage. Mais je ne vais pas oublier de packager ce framework. Il faudra un peu plus de patience, voilà tout.
Afficher les 14 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.