L'exécution d'un test unitaire nécessite en règle générale la mise en place de bouchon (mock en anglais) qui permettent de simuler les appels systèmes ou d'api sous jacent.
En effet, il peut être difficile de tester une partie de votre code qui a des impacts sur le système externe (enregistrement sur disque, appels réseaux / webservices, stockage mémoire vive, appels base de données...), le principe du bouchon est alors bien pratique pour tester la logique sans déclencher toutes les opérations.
Tag - factory
samedi, septembre 26 2009
Test unitaire: comment bouchonner ?
Par Olivier Hoareau le samedi, septembre 26 2009, 16:59 - Méthodologie
mardi, avril 21 2009
Pourquoi Eclipse et les annotations ont révolutionné ma façon de coder
Par Olivier Hoareau le mardi, avril 21 2009, 08:55 - Outillage
Comme beaucoup d'entre vous, "vi" (prononcez "vi-aille") a longtemps été mon ami pour développer mon code PHP.
Il me plaisait bien, j'avais l'air d'être un geek et tout allait bien.
mercredi, novembre 5 2008
Pattern Factory : Ou comment faire tout en 1 ligne
Par Olivier Hoareau le mercredi, novembre 5 2008, 08:00 - Méthodologie
Vous révez de ça :
<?php
$service = new MonService()
-> setConfig(...)
-> setAdapter(...)
-> setModel(...)
-> process();
...
Commentaires récents
C'est typiquement le genre de syntaxe dont on est très friand dans Copix :-)
Il faut avouer que cela simplifie l'écriture.... par contre on se retrouve vite avec des syntaxes compact dont il faut connaître la signification :-)
_dao ('MaTable')->findBy (
_daoSp ()->addCondition ('champ', '=', $valeur)
->addCondition ('champ2', '=', $valeur2)
->orderBy ('champ3')
)
Ce qui ici signifie : Je vais récupérer dans ma table "MaTable", grâce à un "Data Access Object", les enregistrement qui correspondent aux paramètres de recherches (daoSP = Data Access Object Search Params) ....
Le plus proche de l'exemple serait la fabrique de classe, utilisée de la sorte :
_class ('classId')
...qui retourne un new 'ClassId' (en plus d'inclure le fichier en question grâce à un système d'autoload).
J'aime assez aussi la possibilité de faire un raccourcis pour obtenir des singletons de ces objets, avec par exemple
_ioClass ('classId');// (instance of class) qui retournera systématiquement la même instance de la classe 'classId'.
En tout cas c'est sûr, le nested call de PHP 5 est pour moi une grande nouveauté par rapport à la version 4 :-)
Merci beaucoup pour ce petit billet très instructif ;)
Mais comment n'y ai je pas pensé avant ?
J'utilise Komodo edit. J'ajoute les doc block à la main, mais ceux ci sont ensuite supportés par l'autocompletion ce qui est une bonne incitation à leur utilisation :)
J'avoue que je n'utilise pas trop le chainage des appels, le poids de ma pratique de PHP4 sans doute. Et généralement mes setters renvoient un booleen.
Même chose et même évolution que toi.
Au début c'était cool l'autocomplétion puis c'est devenu une vrai méthode de travail. Les appels chaînés sont devenu une religion...
Ce qui m'amène à regretter que les types scalaire de php ne soit pas objet et qu'on ai toujours les str... fonctions, les array... fonctions etc...
Attention ! Il ne faut pas mélanger les "doc block" (autrement dit PHPDoc) et les "annotations"; ce sont deux choses entièrement différentes dans Eclipse.
Ce que vous présentez-là sont les blocs de commentaire à la JavaDoc (pour PHP on dit PHPDoc). Alors que les annotations sont un ensemble de mises en relief du code que propose Eclipse. On trouve les options d'annotations dans General > Editors > Text Editors > Annotations. Elles permettent notamment avec PDT par exemple, d'avoir pour une variable toutes les occurrences surlignées en une couleur (lorsque le curseur se trouve dessus).
Il y a de très nombreux paramètres et on s'y perd vite, mais une bonne utilisation de ceux-ci permet de gagner beaucoup de temps.
Je recommande à tous ceux qui travaillent sur un fond noir de passer par là pour les problèmes de couleurs (light/light).
En passant :
"public function getInstance" n'est pas déclarée "static" ;)
@avetis: merci de la précision sur une des nombreuses fonctionnalités d'Eclipse ;)
Par contre, en PHP le terme Annotations est aussi utilisé pour ce type d'artefact, cf http://www.slideshare.net/stubbles/declarative-development-using-annotations-in-php, ou le package PEAR PHP_Annotation, entre autre.
J'en conviens il s'agit plus de doc bloc façon xdoclet (de mémoire en Java) plutôt que de réelle annotation à la sauce Java. Mais c'est un compromis déjà efficace à leur actuelle.
Merci pour la coquille sur le public final static getInstance, c'est corrigé.
Je ne suis pas un expert avec les patterns, pourrais-tu développer cette phrase ?
"je crée quasi systématiquement des factories pour éviter de passer par une variable inutile"
Dans un nouveau post éventuellement.
@Moosh: plus simplement (j'espère ;) ) :
$o = new MaClasse();
$o->maMethod1();
$o->maMethod2();
$resultat = $o->maMethod3();
Dans ce cas là, tu réalises un enchainement de méthodes qui appartiennent toutes à l'objet $o. La variable $o finalement ne te sert pas à grand chose si ce n'est de pouvoir appeller les méthodes les unes à la suite des autres. Pour factoriser tu pourrais faire :
$o = new MaClasse();
$resultat =
$o->maMethod1()
->maMethod2()
->maMethod3();
C'est déjà un peu mieux (on peut tout mettre sur une ligne si on veut), par contre on se rend compte que la variable $o ne sert à rien finalment car elle n'est plus jamais utilisée (dans la suite du script). Du coup tu pollue ton script avec des variable qui ne sont pas utilier (et aussi l'espace mémoire).
L'idée de la factory c'est finalement de faire une méthode static qui permettra d'éviter de mettre le "new MaClasse()" dans une variable :
$resultat = MaClasse::creeObjet()->maMethod1()->maMethod2()->maMethod3();Si tu as pris soin de mettre de nom de classe explicites, des noms de méthodes assez court et parlant, tes scripts peuvent être plus concis et plus parlant (tu peux aussi mettre sur plusieurs lignes).
La méthode creeObjet() peut aussi prendre un paramètre (c'est tout l'intérêt d'une factory), on sait qu'on fait souvent l'enchainement maMethod1() et maMethod2 dans notre code, et qu'en suite on a besoin de l'objet. On peut alors faire :
class MaClasse {
...
/**
* Fait quelquechose
*
* @return MaClasse
*/
public function maMethod1() {
...
return $this;
}
/**
* Fait quelquechose
*
* @return MaClasse
*/
public function maMethod2() {
...
return $this;
}
/**
* Fait quelquechose
*
* @return string
*/
public function maMethod3() {
...
return "un resultat quelconque ici";
}
/**
* Retourne une instance de la classe
*
* @param string $comment optionnel, quel type d'instance retourner ? Si null, une instance vierge, si 'm1_et_m2' => l'instance aura déjà eu maMethod1() et maMethod2() d'appellées
*
* @return MaClasse
*/
public final static function creeObjet($comment=null) {
$o = new self;
if (null !== $comment && 'm1_et_m2' === $comment) {
$o->maMethod1()->maMethod2();
}
return $o;
}
...
}
$result = MaClasse::creeObjet('m1_et_m2')->maMethod3();
Ma remarque voulais simplement dire qu'en utilisant ce principe de factory (qui prennent un paramètre éventuellement) je peux éviter de faire le new moi-même et éviter de stocker l'objet dans une variable (si combiné avec des 'return $this' dans chacune des maMethodX())
J'espère que c'est un peu plus claire, sinon n'hésites pas à demander des précis / rectifications
Pour moi, je travaille souvent sur Netbeans 6.5 grâce à ses fonctionnalités qui couvrent tous les besoins d'un developpeur professionnel
Complément d'information posté sur le blog de Clochix (http://www.clochix.net/post/2009/09...) concernant l'utilisation des fonctionnalité Mock de PHPUnit:
Pour ma part, j'évite de l'utiliser (i.e. la fonctionnalité Mock de PHPUnit) car je souhaite rester indépendant d'un quelconque framework lors de mon développement.
Les fonctionnalités Mock de PHPUnit sont très intéressantes, elles ont cependant de mon point de vue un défaut majeure dans l'utilisation que je fais des mocks. En effet, lorsque je développe j'utilise la version "mock" de mes classes (adapter) dans mon code tant que je n'ai pas développé la version native (standard). Cela me permet de prototyper / présenter rapidement les fonctionnalités "statiques" de mes développements et de "débrancher" lorsque je suis prêt le mock pour mettre la vraie implémentation (imaginez que je développe un webservice et que je doive rapidement fournir une version de mon webservice pour des consommateurs qui seraient "impatients"). Le problème avec le framework PHPUnit est qu'il n'est pas adapté a priori pour une utilisation en dehors des tests unitaires.
autre part les mocks peuvent être utiles dans d'autres cas encore que les tests unitaires et celui que je décris, par exemple certains tests d'intégration qui porte sur d'autres zones du code... même remarque dans ce cas.
Et vous quels sont vos pratiques pour mettre en place des bouchons dans les cas autres que les tests unitaires ?
J'ai tendance à faire pareil sauf que je rajoute le typage :
@param array $tab : mon commentaire